Merge pull request #896 from jasonrhansen/extract-archives
Use Open Folder dialog for Extract To
This commit is contained in:
commit
17971a5d70
4 changed files with 65 additions and 52 deletions
|
|
@ -43,7 +43,7 @@ create-archive = Create archive
|
||||||
## Extract Dialog
|
## Extract Dialog
|
||||||
extract-password-required = Password required
|
extract-password-required = Password required
|
||||||
extract-to = Extract To...
|
extract-to = Extract To...
|
||||||
extract-to-prompt = Input a location to extract the archive to.
|
extract-to-title = Extract to folder
|
||||||
|
|
||||||
## Empty Trash Dialog
|
## Empty Trash Dialog
|
||||||
empty-trash = Empty trash
|
empty-trash = Empty trash
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ create-archive = Tömörített fájl létrehozása
|
||||||
## Extract Dialog
|
## Extract Dialog
|
||||||
extract-password-required = Jelszó szükséges
|
extract-password-required = Jelszó szükséges
|
||||||
extract-to = Kibontás ide...
|
extract-to = Kibontás ide...
|
||||||
extract-to-prompt = Adja meg a helyet, ahová ki szeretné bontani a tömörített fájlt.
|
|
||||||
|
|
||||||
## Empty Trash Dialog
|
## Empty Trash Dialog
|
||||||
empty-trash = Kuka ürítése
|
empty-trash = Kuka ürítése
|
||||||
|
|
@ -321,4 +320,4 @@ sort-z-a = Z-A
|
||||||
sort-newest-first = Legújabb előre
|
sort-newest-first = Legújabb előre
|
||||||
sort-oldest-first = Legrégibb előre
|
sort-oldest-first = Legrégibb előre
|
||||||
sort-smallest-to-largest = Legkisebbtől a legnagyobbig
|
sort-smallest-to-largest = Legkisebbtől a legnagyobbig
|
||||||
sort-largest-to-smallest = Legnagyobbtól a legkisebbig
|
sort-largest-to-smallest = Legnagyobbtól a legkisebbig
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ create-archive = Maak een archiefbestand
|
||||||
## Extract Dialog
|
## Extract Dialog
|
||||||
extract-password-required = Wachtwoord vereist
|
extract-password-required = Wachtwoord vereist
|
||||||
extract-to = Uitpakken naar...
|
extract-to = Uitpakken naar...
|
||||||
extract-to-prompt = Voer een locatie in om dit archief naar uit te pakken.
|
|
||||||
|
|
||||||
## Empty Trash Dialog
|
## Empty Trash Dialog
|
||||||
empty-trash = Prullenbak legen?
|
empty-trash = Prullenbak legen?
|
||||||
|
|
|
||||||
111
src/app.rs
111
src/app.rs
|
|
@ -63,11 +63,10 @@ use trash::TrashItem;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
||||||
|
|
||||||
use crate::mime_app::MimeApp;
|
|
||||||
use crate::operation::{OperationError, OperationErrorType};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
||||||
config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig, TypeToSearch},
|
config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig, TypeToSearch},
|
||||||
|
dialog::{DialogKind, DialogMessage},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::key_binds,
|
key_bind::key_binds,
|
||||||
localize::LANGUAGE_SORTER,
|
localize::LANGUAGE_SORTER,
|
||||||
|
|
@ -77,6 +76,11 @@ use crate::{
|
||||||
spawn_detached::spawn_detached,
|
spawn_detached::spawn_detached,
|
||||||
tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION},
|
tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION},
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
dialog::Dialog,
|
||||||
|
operation::{OperationError, OperationErrorType},
|
||||||
|
};
|
||||||
|
use crate::{dialog::DialogResult, mime_app::MimeApp};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
|
|
@ -291,11 +295,13 @@ pub enum Message {
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
DialogCancel,
|
DialogCancel,
|
||||||
DialogComplete,
|
DialogComplete,
|
||||||
|
FileDialogMessage(DialogMessage),
|
||||||
DialogPush(DialogPage),
|
DialogPush(DialogPage),
|
||||||
DialogUpdate(DialogPage),
|
DialogUpdate(DialogPage),
|
||||||
DialogUpdateComplete(DialogPage),
|
DialogUpdateComplete(DialogPage),
|
||||||
ExtractHere(Option<Entity>),
|
ExtractHere(Option<Entity>),
|
||||||
ExtractTo(Option<Entity>),
|
ExtractTo(Option<Entity>),
|
||||||
|
ExtractToResult(DialogResult),
|
||||||
#[cfg(all(feature = "desktop", feature = "wayland"))]
|
#[cfg(all(feature = "desktop", feature = "wayland"))]
|
||||||
Focused(window::Id),
|
Focused(window::Id),
|
||||||
Key(Modifiers, Key, Option<SmolStr>),
|
Key(Modifiers, Key, Option<SmolStr>),
|
||||||
|
|
@ -434,11 +440,6 @@ pub enum DialogPage {
|
||||||
archive_type: ArchiveType,
|
archive_type: ArchiveType,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
},
|
},
|
||||||
ExtractTo {
|
|
||||||
paths: Vec<PathBuf>,
|
|
||||||
to: PathBuf,
|
|
||||||
password: Option<String>,
|
|
||||||
},
|
|
||||||
EmptyTrash,
|
EmptyTrash,
|
||||||
FailedOperation(u64),
|
FailedOperation(u64),
|
||||||
ExtractPassword {
|
ExtractPassword {
|
||||||
|
|
@ -503,6 +504,7 @@ pub enum WindowKind {
|
||||||
Desktop(Entity),
|
Desktop(Entity),
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
Preview(Option<Entity>, PreviewKind),
|
Preview(Option<Entity>, PreviewKind),
|
||||||
|
FileDialog(Option<Vec<PathBuf>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WatcherWrapper {
|
pub struct WatcherWrapper {
|
||||||
|
|
@ -570,6 +572,7 @@ pub struct App {
|
||||||
nav_drag_id: DragId,
|
nav_drag_id: DragId,
|
||||||
tab_drag_id: DragId,
|
tab_drag_id: DragId,
|
||||||
auto_scroll_speed: Option<i16>,
|
auto_scroll_speed: Option<i16>,
|
||||||
|
file_dialog_opt: Option<Dialog<Message>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -1794,6 +1797,7 @@ impl Application for App {
|
||||||
nav_drag_id: DragId::new(),
|
nav_drag_id: DragId::new(),
|
||||||
tab_drag_id: DragId::new(),
|
tab_drag_id: DragId::new(),
|
||||||
auto_scroll_speed: None,
|
auto_scroll_speed: None,
|
||||||
|
file_dialog_opt: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut commands = vec![app.update_config()];
|
let mut commands = vec![app.update_config()];
|
||||||
|
|
@ -2237,17 +2241,6 @@ impl Application for App {
|
||||||
DialogPage::EmptyTrash => {
|
DialogPage::EmptyTrash => {
|
||||||
self.operation(Operation::EmptyTrash);
|
self.operation(Operation::EmptyTrash);
|
||||||
}
|
}
|
||||||
DialogPage::ExtractTo {
|
|
||||||
paths,
|
|
||||||
to,
|
|
||||||
password,
|
|
||||||
} => {
|
|
||||||
self.operation(Operation::Extract {
|
|
||||||
paths,
|
|
||||||
to,
|
|
||||||
password: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
DialogPage::FailedOperation(id) => {
|
DialogPage::FailedOperation(id) => {
|
||||||
log::warn!("TODO: retry operation {}", id);
|
log::warn!("TODO: retry operation {}", id);
|
||||||
}
|
}
|
||||||
|
|
@ -2402,13 +2395,49 @@ impl Application for App {
|
||||||
.and_then(|first| first.parent())
|
.and_then(|first| first.parent())
|
||||||
.map(|parent| parent.to_path_buf())
|
.map(|parent| parent.to_path_buf())
|
||||||
{
|
{
|
||||||
self.dialog_pages.push_back(DialogPage::ExtractTo {
|
let (mut dialog, dialog_task) = Dialog::new(
|
||||||
paths,
|
DialogKind::OpenFolder,
|
||||||
to: destination,
|
Some(destination),
|
||||||
password: None,
|
Message::FileDialogMessage,
|
||||||
});
|
Message::ExtractToResult,
|
||||||
|
);
|
||||||
|
let set_title_task = dialog.set_title(fl!("extract-to-title"));
|
||||||
|
dialog.set_accept_label(fl!("extract-here"));
|
||||||
|
self.windows
|
||||||
|
.insert(dialog.window_id(), WindowKind::FileDialog(Some(paths)));
|
||||||
|
self.file_dialog_opt = Some(dialog);
|
||||||
|
return Task::batch([set_title_task, dialog_task]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Message::ExtractToResult(result) => {
|
||||||
|
match result {
|
||||||
|
DialogResult::Cancel => {}
|
||||||
|
DialogResult::Open(selected_paths) => {
|
||||||
|
let mut archive_paths = None;
|
||||||
|
if let Some(file_dialog) = &self.file_dialog_opt {
|
||||||
|
let window = self.windows.remove(&file_dialog.window_id());
|
||||||
|
if let Some(WindowKind::FileDialog(paths)) = window {
|
||||||
|
archive_paths = paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(archive_paths) = archive_paths {
|
||||||
|
if !selected_paths.is_empty() {
|
||||||
|
self.operation(Operation::Extract {
|
||||||
|
paths: archive_paths,
|
||||||
|
to: selected_paths[0].clone(),
|
||||||
|
password: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.file_dialog_opt = None;
|
||||||
|
}
|
||||||
|
Message::FileDialogMessage(dialog_message) => {
|
||||||
|
if let Some(dialog) = &mut self.file_dialog_opt {
|
||||||
|
return dialog.update(dialog_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::Key(modifiers, key, text) => {
|
Message::Key(modifiers, key, text) => {
|
||||||
let entity = self.tab_model.active();
|
let entity = self.tab_model.active();
|
||||||
for (key_bind, action) in self.key_binds.iter() {
|
for (key_bind, action) in self.key_binds.iter() {
|
||||||
|
|
@ -2887,6 +2916,12 @@ impl Application for App {
|
||||||
)
|
)
|
||||||
.map(cosmic::Action::App),
|
.map(cosmic::Action::App),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
commands.push(
|
||||||
|
self.toasts
|
||||||
|
.push(widget::toaster::Toast::new(description))
|
||||||
|
.map(cosmic::Action::App),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2935,7 +2970,7 @@ impl Application for App {
|
||||||
self.dialog_pages.push_back(match err.kind {
|
self.dialog_pages.push_back(match err.kind {
|
||||||
OperationErrorType::Generic(_) => DialogPage::FailedOperation(id),
|
OperationErrorType::Generic(_) => DialogPage::FailedOperation(id),
|
||||||
OperationErrorType::PasswordRequired => DialogPage::ExtractPassword {
|
OperationErrorType::PasswordRequired => DialogPage::ExtractPassword {
|
||||||
id: id,
|
id,
|
||||||
password: String::from(""),
|
password: String::from(""),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -4121,30 +4156,6 @@ impl Application for App {
|
||||||
.secondary_action(
|
.secondary_action(
|
||||||
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
),
|
),
|
||||||
DialogPage::ExtractTo {
|
|
||||||
paths,
|
|
||||||
to,
|
|
||||||
password,
|
|
||||||
} => widget::dialog()
|
|
||||||
.title(fl!("extract-to"))
|
|
||||||
.body(fl!("extract-to-prompt"))
|
|
||||||
.control(
|
|
||||||
widget::text_input("Enter the path to extract to", to.to_string_lossy())
|
|
||||||
.on_input(move |to| {
|
|
||||||
Message::DialogUpdate(DialogPage::ExtractTo {
|
|
||||||
paths: paths.clone(),
|
|
||||||
to: PathBuf::from(to),
|
|
||||||
password: password.clone(),
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.primary_action(
|
|
||||||
widget::button::suggested(fl!("extract-here"))
|
|
||||||
.on_press(Message::DialogComplete),
|
|
||||||
)
|
|
||||||
.secondary_action(
|
|
||||||
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
|
||||||
),
|
|
||||||
DialogPage::FailedOperation(id) => {
|
DialogPage::FailedOperation(id) => {
|
||||||
//TODO: try next dialog page (making sure index is used by Dialog messages)?
|
//TODO: try next dialog page (making sure index is used by Dialog messages)?
|
||||||
let (operation, _, err) = self.failed_operations.get(id)?;
|
let (operation, _, err) = self.failed_operations.get(id)?;
|
||||||
|
|
@ -4935,6 +4946,10 @@ impl Application for App {
|
||||||
Some(WindowKind::Preview(entity_opt, kind)) => self
|
Some(WindowKind::Preview(entity_opt, kind)) => self
|
||||||
.preview(entity_opt, kind, false)
|
.preview(entity_opt, kind, false)
|
||||||
.map(|x| Message::TabMessage(*entity_opt, x)),
|
.map(|x| Message::TabMessage(*entity_opt, x)),
|
||||||
|
Some(WindowKind::FileDialog(..)) => match &self.file_dialog_opt {
|
||||||
|
Some(dialog) => return dialog.view(id),
|
||||||
|
None => widget::text("Unknown window ID").into(),
|
||||||
|
},
|
||||||
None => {
|
None => {
|
||||||
//TODO: distinct views per monitor in desktop mode
|
//TODO: distinct views per monitor in desktop mode
|
||||||
return self.view_main().map(|message| match message {
|
return self.view_main().map(|message| match message {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue