chore: add rustfmt config

Also adds a Zed editor config for automatic formatting with nightly.
This commit is contained in:
Vukašin Vojinović 2026-04-28 15:05:08 +02:00 committed by Michael Murphy
parent e91a984da9
commit d5dbcc7677
31 changed files with 349 additions and 420 deletions

15
.zed/settings.json Normal file
View file

@ -0,0 +1,15 @@
{
"format_on_save": "on",
"lsp": {
"rust-analyzer": {
"initialization_options": {
"check": {
"command": "clippy",
},
"rustfmt": {
"extraArgs": ["+nightly"],
},
},
},
},
}

View file

@ -1,4 +1,5 @@
use std::{env, fs, path::PathBuf}; use std::path::PathBuf;
use std::{env, fs};
use xdgen::{App, Context, FluentString}; use xdgen::{App, Context, FluentString};
fn main() { fn main() {

View file

@ -1,6 +1,8 @@
use cosmic_files::operation::recursive::Method; use cosmic_files::operation::recursive::{Context, Method};
use cosmic_files::operation::{Controller, ReplaceResult, recursive::Context}; use cosmic_files::operation::{Controller, ReplaceResult};
use std::{error::Error, io, path::PathBuf}; use std::error::Error;
use std::io;
use std::path::PathBuf;
#[compio::main] #[compio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {

View file

@ -1,15 +1,12 @@
use cosmic::{ use cosmic::app::{self, Core, Settings, Task};
Application, Element, use cosmic::iced::{Subscription, window};
app::{self, Core, Settings, Task}, use cosmic::{Application, Element, executor, widget};
executor,
iced::{Subscription, window},
widget,
};
use cosmic_files::dialog::{ use cosmic_files::dialog::{
Dialog, DialogChoice, DialogChoiceOption, DialogFilter, DialogFilterPattern, DialogKind, Dialog, DialogChoice, DialogChoiceOption, DialogFilter, DialogFilterPattern, DialogKind,
DialogMessage, DialogResult, DialogSettings, DialogMessage, DialogResult, DialogSettings,
}; };
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let log_format = tracing_subscriber::fmt::format() let log_format = tracing_subscriber::fmt::format()

1
rustfmt.toml Normal file
View file

@ -0,0 +1 @@
imports_granularity = "Module"

View file

@ -1,8 +1,23 @@
// Copyright 2023 System76 <info@system76.com> // Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::app::{self, Core, Task, context_drawer};
use cosmic::cosmic_config::{self, ConfigSet};
use cosmic::iced::clipboard::dnd::DndAction;
use cosmic::iced::core::SmolStr;
use cosmic::iced::core::widget::operation::focusable::unfocus;
use cosmic::iced::futures::{self, SinkExt};
use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
use cosmic::iced::platform_specific::shell::wayland::commands::overlap_notify::overlap_notify; use cosmic::iced::platform_specific::shell::wayland::commands::overlap_notify::overlap_notify;
use cosmic::iced::runtime::{clipboard, task};
use cosmic::iced::widget::button::focus;
use cosmic::iced::widget::scrollable;
use cosmic::iced::widget::scrollable::AbsoluteOffset;
use cosmic::iced::window::{self, Event as WindowEvent, Id as WindowId};
use cosmic::iced::{
self, Alignment, Event, Length, Rectangle, Size, Subscription, event, mouse, stream,
};
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
use cosmic::iced::{ use cosmic::iced::{
Limits, Point, Limits, Point,
@ -14,92 +29,59 @@ use cosmic::iced::{
Anchor, KeyboardInteractivity, Layer, destroy_layer_surface, get_layer_surface, Anchor, KeyboardInteractivity, Layer, destroy_layer_surface, get_layer_surface,
}, },
}; };
use cosmic::{ use cosmic::widget::about::About;
Application, ApplicationExt, Element, use cosmic::widget::dnd_destination::DragId;
app::{self, Core, Task, context_drawer}, use cosmic::widget::menu::action::MenuAction;
cosmic_config::{self, ConfigSet}, use cosmic::widget::menu::key_bind::KeyBind;
cosmic_theme, executor, use cosmic::widget::segmented_button::{self, Entity, ReorderEvent};
iced::core::widget::operation::focusable::unfocus, use cosmic::widget::{self, icon, settings, space};
iced::runtime::{clipboard, task}, use cosmic::{Application, ApplicationExt, Element, cosmic_theme, executor, style, surface, theme};
iced::widget::{button::focus, scrollable::AbsoluteOffset},
iced::{
self, Alignment, Event, Length, Rectangle, Size, Subscription,
clipboard::dnd::DndAction,
core::SmolStr,
event,
futures::{self, SinkExt},
keyboard::{Event as KeyEvent, Key, Modifiers},
mouse, stream,
widget::scrollable,
window::{self, Event as WindowEvent, Id as WindowId},
},
style, surface, theme,
widget::{
self,
about::About,
dnd_destination::DragId,
icon,
menu::{action::MenuAction, key_bind::KeyBind},
segmented_button::{self, Entity, ReorderEvent},
settings, space,
},
};
use mime_guess::Mime; use mime_guess::Mime;
use notify_debouncer_full::{ use notify_debouncer_full::notify::{self, RecommendedWatcher};
DebouncedEvent, Debouncer, RecommendedCache, new_debouncer, use notify_debouncer_full::{DebouncedEvent, Debouncer, RecommendedCache, new_debouncer};
notify::{self, RecommendedWatcher},
};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use slotmap::Key as SlotMapKey; use slotmap::Key as SlotMapKey;
use std::{ use std::any::TypeId;
any::TypeId, use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
collections::{BTreeMap, BTreeSet, HashMap, VecDeque}, use std::future::Future;
env, fmt, fs, use std::num::NonZeroU16;
future::Future, use std::path::{Path, PathBuf};
io, use std::pin::Pin;
num::NonZeroU16, use std::sync::{Arc, LazyLock, Mutex};
path::{Path, PathBuf}, use std::time::{self, Duration, Instant};
pin::Pin, use std::{env, fmt, fs, io, process};
process,
sync::{Arc, LazyLock, Mutex},
time::{self, Duration, Instant},
};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use trash::TrashItem; use trash::TrashItem;
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
use wayland_client::{Proxy, protocol::wl_output::WlOutput}; use wayland_client::{Proxy, protocol::wl_output::WlOutput};
use crate::{ use crate::clipboard::{
FxOrderMap,
clipboard::{
ClipboardCache, ClipboardCopy, ClipboardKind, ClipboardPaste, ClipboardPasteImage, ClipboardCache, ClipboardCopy, ClipboardKind, ClipboardPaste, ClipboardPasteImage,
ClipboardPasteText, ClipboardPasteVideo, ClipboardPasteText, ClipboardPasteVideo,
}, };
config::{ use crate::config::{
AppTheme, Config, DesktopConfig, Favorite, IconSizes, State, TIME_CONFIG_ID, TabConfig, AppTheme, Config, DesktopConfig, Favorite, IconSizes, State, TIME_CONFIG_ID, TabConfig,
TimeConfig, TypeToSearch, TimeConfig, TypeToSearch,
}, };
context_action, use crate::dialog::{Dialog, DialogKind, DialogMessage, DialogResult, DialogSettings};
dialog::{Dialog, DialogKind, DialogMessage, DialogResult, DialogSettings}, use crate::key_bind::key_binds;
fl, home_dir, use crate::localize::LANGUAGE_SORTER;
key_bind::key_binds, use crate::mime_app::{self, MimeApp, MimeAppCache};
localize::LANGUAGE_SORTER, use crate::mounter::{
menu, MOUNTERS, MounterAuth, MounterItem, MounterItems, MounterKey, MounterMessage,
mime_app::{self, MimeApp, MimeAppCache}, };
mime_icon, use crate::operation::{
mounter::{MOUNTERS, MounterAuth, MounterItem, MounterItems, MounterKey, MounterMessage}, Controller, Operation, OperationError, OperationErrorType, OperationSelection, ReplaceResult,
operation::{ copy_unique_path,
Controller, Operation, OperationError, OperationErrorType, OperationSelection, };
ReplaceResult, copy_unique_path, use crate::spawn_detached::spawn_detached;
}, use crate::tab::{
spawn_detached::spawn_detached,
tab::{
self, HOVER_DURATION, HeadingOptions, ItemMetadata, Location, SORT_OPTION_FALLBACK, self, HOVER_DURATION, HeadingOptions, ItemMetadata, Location, SORT_OPTION_FALLBACK,
SearchLocation, Tab, SearchLocation, Tab,
},
trash::{Trash, TrashExt},
zoom::{zoom_in_view, zoom_out_view, zoom_to_default},
}; };
use crate::trash::{Trash, TrashExt};
use crate::zoom::{zoom_in_view, zoom_out_view, zoom_to_default};
use crate::{FxOrderMap, context_action, fl, home_dir, menu, mime_icon};
static PERMANENT_DELETE_BUTTON_ID: LazyLock<widget::Id> = static PERMANENT_DELETE_BUTTON_ID: LazyLock<widget::Id> =
LazyLock::new(|| widget::Id::new("permanent-delete-button")); LazyLock::new(|| widget::Id::new("permanent-delete-button"));
@ -7033,21 +7015,17 @@ impl Application for App {
// Ideally, tests would use the cap-std crate which limits path traversal. // Ideally, tests would use the cap-std crate which limits path traversal.
#[cfg(test)] #[cfg(test)]
pub(crate) mod test_utils { pub(crate) mod test_utils {
use std::{ use std::cmp::Ordering;
cmp::Ordering, use std::fs::File;
fs::File, use std::io::{self, Write};
io::{self, Write}, use std::iter;
iter, use std::path::Path;
path::Path,
};
use log::{debug, trace}; use log::{debug, trace};
use tempfile::{TempDir, tempdir}; use tempfile::{TempDir, tempdir};
use crate::{ use crate::config::{IconSizes, TabConfig, ThumbCfg};
config::{IconSizes, TabConfig, ThumbCfg}, use crate::tab::Item;
tab::Item,
};
use super::*; use super::*;

View file

@ -1,16 +1,14 @@
use crate::{ use crate::mime_icon::mime_for_path;
mime_icon::mime_for_path, use crate::operation::{Controller, OpReader, OperationError, OperationErrorType, sync_to_disk};
operation::{Controller, OpReader, OperationError, OperationErrorType, sync_to_disk},
};
use cosmic::iced::futures; use cosmic::iced::futures;
use jiff::{Zoned, civil::DateTime, tz::TimeZone}; use jiff::Zoned;
use std::{ use jiff::civil::DateTime;
collections::HashSet, use jiff::tz::TimeZone;
fs, use std::collections::HashSet;
io::{self, Read, Write}, use std::fs;
path::{Path, PathBuf}, use std::io::{self, Read, Write};
time::SystemTime, use std::path::{Path, PathBuf};
}; use std::time::SystemTime;
use zip::result::ZipError; use zip::result::ZipError;
pub const SUPPORTED_ARCHIVE_TYPES: &[&str] = &[ pub const SUPPORTED_ARCHIVE_TYPES: &[&str] = &[
@ -112,7 +110,8 @@ fn zip_extract<R: io::Read + io::Seek, P: AsRef<Path>>(
password: Option<&str>, password: Option<&str>,
controller: Controller, controller: Controller,
) -> zip::result::ZipResult<()> { ) -> zip::result::ZipResult<()> {
use std::{ffi::OsString, fs}; use std::ffi::OsString;
use std::fs;
use zip::result::ZipError; use zip::result::ZipError;
fn make_writable_dir_all<T: AsRef<Path>>( fn make_writable_dir_all<T: AsRef<Path>>(

View file

@ -1,13 +1,9 @@
// Copyright 2025 System76 <info@system76.com> // Copyright 2025 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use std::{ use std::collections::VecDeque;
collections::VecDeque, use std::sync::atomic::{AtomicBool, Ordering};
sync::{ use std::sync::{Arc, Mutex};
Arc, Mutex,
atomic::{AtomicBool, Ordering},
},
};
/// Create a channel backed by `tokio::sync::Notify` and a sync mutex with a vec deque. /// Create a channel backed by `tokio::sync::Notify` and a sync mutex with a vec deque.
pub fn channel<Message>() -> (Sender<Message>, Receiver<Message>) { pub fn channel<Message>() -> (Sender<Message>, Receiver<Message>) {

View file

@ -2,12 +2,10 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes};
use std::{ use std::borrow::Cow;
borrow::Cow, use std::error::Error;
error::Error, use std::path::{Path, PathBuf};
path::{Path, PathBuf}, use std::str;
str,
};
use url::Url; use url::Url;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]

View file

@ -1,20 +1,18 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use std::{any::TypeId, num::NonZeroU16, path::PathBuf}; use std::any::TypeId;
use std::num::NonZeroU16;
use std::path::PathBuf;
use cosmic::{ use cosmic::cosmic_config::cosmic_config_derive::CosmicConfigEntry;
Application, use cosmic::cosmic_config::{self, CosmicConfigEntry};
cosmic_config::{self, CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry}, use cosmic::iced::Subscription;
iced::Subscription, use cosmic::{Application, theme};
theme,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::FxOrderMap;
FxOrderMap, use crate::app::App;
app::App, use crate::tab::{HeadingOptions, Location, View};
tab::{HeadingOptions, Location, View},
};
pub use crate::context_action::{ContextActionPreset, ContextActionSelection}; pub use crate::context_action::{ContextActionPreset, ContextActionSelection};

View file

@ -4,7 +4,8 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{mime_app, spawn_detached::spawn_detached}; use crate::mime_app;
use crate::spawn_detached::spawn_detached;
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub enum ContextActionSelection { pub enum ContextActionSelection {

View file

@ -1,58 +1,46 @@
// Copyright 2023 System76 <info@system76.com> // Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::{ use cosmic::app::cosmic::Cosmic;
Application, ApplicationExt, Element, use cosmic::app::{Core, Task, context_drawer};
app::{Core, Task, context_drawer, cosmic::Cosmic}, use cosmic::iced::core::SmolStr;
cosmic_config, cosmic_theme, executor, use cosmic::iced::core::widget::operation;
iced::core::widget::operation, use cosmic::iced::futures::{self, SinkExt};
iced::platform_specific::shell::{self as iced_winit, SurfaceIdWrapper}, use cosmic::iced::keyboard::key::Named;
iced::widget::scrollable::AbsoluteOffset, use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
iced::{ use cosmic::iced::platform_specific::shell::{self as iced_winit, SurfaceIdWrapper};
self, Alignment, Event, Length, Size, Subscription, use cosmic::iced::widget::scrollable;
core::SmolStr, use cosmic::iced::widget::scrollable::AbsoluteOffset;
event, use cosmic::iced::{
futures::{self, SinkExt}, self, Alignment, Event, Length, Size, Subscription, event, mouse, stream, window,
keyboard::{Event as KeyEvent, Key, Modifiers, key::Named},
mouse, stream,
widget::scrollable,
window,
},
theme,
widget::{
self, Operation,
menu::{Action as MenuAction, KeyBind, key_bind::Modifier},
segmented_button,
},
}; };
use cosmic::widget::menu::key_bind::Modifier;
use cosmic::widget::menu::{Action as MenuAction, KeyBind};
use cosmic::widget::{self, Operation, segmented_button};
use cosmic::{Application, ApplicationExt, Element, cosmic_config, cosmic_theme, executor, theme};
use mime_guess::{Mime, mime}; use mime_guess::{Mime, mime};
use notify_debouncer_full::{ use notify_debouncer_full::notify::{self, RecommendedWatcher};
DebouncedEvent, Debouncer, RecommendedCache, new_debouncer, use notify_debouncer_full::{DebouncedEvent, Debouncer, RecommendedCache, new_debouncer};
notify::{self, RecommendedWatcher},
};
use recently_used_xbel::update_recently_used; use recently_used_xbel::update_recently_used;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::{ use std::any::TypeId;
any::TypeId, use std::collections::{HashMap, VecDeque};
collections::{HashMap, VecDeque}, use std::path::PathBuf;
env, fmt, fs, use std::time::{self, Instant};
path::PathBuf, use std::{env, fmt, fs};
time::{self, Instant},
};
use crate::{ use crate::app::{
app::{
Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind, REPLACE_BUTTON_ID, Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind, REPLACE_BUTTON_ID,
},
config::{Config, DialogConfig, Favorite, TIME_CONFIG_ID, ThumbCfg, TimeConfig, TypeToSearch},
fl, home_dir,
key_bind::key_binds,
localize::LANGUAGE_SORTER,
menu,
mounter::{MOUNTERS, MounterItem, MounterItems, MounterKey, MounterMessage},
tab::{self, ItemMetadata, Location, SearchLocation, Tab},
zoom::{zoom_in_view, zoom_out_view, zoom_to_default},
}; };
use crate::config::{
Config, DialogConfig, Favorite, TIME_CONFIG_ID, ThumbCfg, TimeConfig, TypeToSearch,
};
use crate::key_bind::key_binds;
use crate::localize::LANGUAGE_SORTER;
use crate::mounter::{MOUNTERS, MounterItem, MounterItems, MounterKey, MounterMessage};
use crate::tab::{self, ItemMetadata, Location, SearchLocation, Tab};
use crate::zoom::{zoom_in_view, zoom_out_view, zoom_to_default};
use crate::{fl, home_dir, menu};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DialogMessage(cosmic::Action<Message>); pub struct DialogMessage(cosmic::Action<Message>);

View file

@ -1,11 +1,10 @@
use cosmic::{ use cosmic::iced::core::keyboard::key::Named;
iced::core::keyboard::key::Named, use cosmic::iced::keyboard::Key;
iced::keyboard::Key, use cosmic::widget::menu::key_bind::{KeyBind, Modifier};
widget::menu::key_bind::{KeyBind, Modifier},
};
use std::collections::HashMap; use std::collections::HashMap;
use crate::{app::Action, tab}; use crate::app::Action;
use crate::tab;
//TODO: load from config //TODO: load from config
pub fn key_binds(mode: &tab::Mode) -> HashMap<KeyBind, Action> { pub fn key_binds(mode: &tab::Mode) -> HashMap<KeyBind, Action> {

View file

@ -1,9 +1,7 @@
use cosmic::widget; use cosmic::widget;
use image::ImageReader; use image::ImageReader;
use std::{ use std::collections::{HashMap, HashSet};
collections::{HashMap, HashSet}, use std::path::{Path, PathBuf};
path::{Path, PathBuf},
};
/// Bytes per pixel in RGBA format (Red, Green, Blue, Alpha = 4 bytes) /// Bytes per pixel in RGBA format (Red, Green, Blue, Alpha = 4 bytes)
pub const RGBA_BYTES_PER_PIXEL: u64 = 4; pub const RGBA_BYTES_PER_PIXEL: u64 = 4;

View file

@ -1,15 +1,16 @@
// Copyright 2023 System76 <info@system76.com> // Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::{app::Settings, iced::Limits}; use cosmic::app::Settings;
use std::{env, fs, path::PathBuf, process}; use cosmic::iced::Limits;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use std::path::PathBuf;
use std::{env, fs, process};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use crate::{ use crate::app::{App, Flags};
app::{App, Flags}, use crate::config::{Config, State};
config::{Config, State}, use crate::tab::Location;
tab::Location,
};
pub mod app; pub mod app;
mod archive; mod archive;

View file

@ -1,11 +1,10 @@
use cosmic::iced::{core as iced_core, widget as iced_widget}; use cosmic::iced::{core as iced_core, widget as iced_widget};
use iced_core::event::Event; use iced_core::event::Event;
use iced_core::layout;
use iced_core::mouse;
use iced_core::overlay;
use iced_core::renderer;
use iced_core::widget::{Operation, Tree}; use iced_core::widget::{Operation, Tree};
use iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget}; use iced_core::{
Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, overlay,
renderer,
};
pub fn loaded_image<'a, Message: 'static, Theme>( pub fn loaded_image<'a, Message: 'static, Theme>(
handle: <cosmic::Renderer as iced_core::image::Renderer>::Handle, handle: <cosmic::Renderer as iced_core::image::Renderer>::Handle,

View file

@ -1,13 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use i18n_embed::{ use i18n_embed::fluent::{FluentLanguageLoader, fluent_language_loader};
DefaultLocalizer, LanguageLoader, Localizer, use i18n_embed::{DefaultLocalizer, LanguageLoader, Localizer};
fluent::{FluentLanguageLoader, fluent_language_loader}, use icu::collator::options::CollatorOptions;
}; use icu::collator::preferences::CollationNumericOrdering;
use icu::collator::{ use icu::collator::{Collator, CollatorBorrowed, CollatorPreferences};
Collator, CollatorBorrowed, CollatorPreferences, options::CollatorOptions,
preferences::CollationNumericOrdering,
};
use icu::locale::Locale; use icu::locale::Locale;
use rust_embed::RustEmbed; use rust_embed::RustEmbed;
use std::sync::LazyLock; use std::sync::LazyLock;

View file

@ -1,30 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::{ use cosmic::app::Core;
Element, use cosmic::iced::advanced::widget::text::Style as TextStyle;
app::Core, use cosmic::iced::keyboard::Modifiers;
iced::{ use cosmic::iced::{Alignment, Background, Border, Length};
Alignment, Background, Border, Length, advanced::widget::text::Style as TextStyle, use cosmic::widget::menu::key_bind::KeyBind;
keyboard::Modifiers, use cosmic::widget::menu::{self, ItemHeight, ItemWidth, MenuBar};
}, use cosmic::widget::{
theme, self, Row, button, column, container, divider, responsive_menu_bar, space, text,
widget::{
self, Row, button, column, container, divider,
menu::{self, ItemHeight, ItemWidth, MenuBar, key_bind::KeyBind},
responsive_menu_bar, space, text,
},
}; };
use cosmic::{Element, theme};
use i18n_embed::LanguageLoader; use i18n_embed::LanguageLoader;
use mime_guess::Mime; use mime_guess::Mime;
use std::{collections::HashMap, sync::LazyLock}; use std::collections::HashMap;
use std::sync::LazyLock;
use crate::{ use crate::app::{Action, Message};
app::{Action, Message}, use crate::config::{Config, ContextActionPreset};
config::{Config, ContextActionPreset}, use crate::fl;
fl, use crate::tab::{self, HeadingOptions, Location, LocationMenuAction, SearchLocation, Tab};
tab::{self, HeadingOptions, Location, LocationMenuAction, SearchLocation, Tab}, use crate::trash::{Trash, TrashExt};
trash::{Trash, TrashExt},
};
static MENU_ID: LazyLock<cosmic::widget::Id> = static MENU_ID: LazyLock<cosmic::widget::Id> =
LazyLock::new(|| cosmic::widget::Id::new("responsive-menu")); LazyLock::new(|| cosmic::widget::Id::new("responsive-menu"));

View file

@ -6,14 +6,11 @@ use cosmic::desktop;
use cosmic::widget; use cosmic::widget;
pub use mime_guess::Mime; pub use mime_guess::Mime;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::{ use std::cmp::Ordering;
cmp::Ordering, use std::ffi::OsStr;
ffi::OsStr, use std::path::{Path, PathBuf};
fs, io, use std::time::Instant;
path::{Path, PathBuf}, use std::{fs, io, process};
process,
time::Instant,
};
// Supported exec key field codes // Supported exec key field codes
const EXEC_HANDLERS: [&str; 4] = ["%f", "%F", "%u", "%U"]; const EXEC_HANDLERS: [&str; 4] = ["%f", "%F", "%u", "%U"];

View file

@ -3,11 +3,9 @@
use cosmic::widget::icon; use cosmic::widget::icon;
use mime_guess::Mime; use mime_guess::Mime;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::{ use std::fs;
fs, use std::path::Path;
path::Path, use std::sync::{LazyLock, Mutex};
sync::{LazyLock, Mutex},
};
pub const FALLBACK_MIME_ICON: &str = "text-x-generic"; pub const FALLBACK_MIME_ICON: &str = "text-x-generic";

View file

@ -1,18 +1,20 @@
use cosmic::{ use cosmic::iced::futures::SinkExt;
Task, use cosmic::iced::{Subscription, stream};
iced::{Subscription, futures::SinkExt, stream}, use cosmic::{Task, widget};
widget, use gio::glib;
}; use gio::prelude::*;
use gio::{glib, prelude::*}; use std::any::TypeId;
use std::{any::TypeId, cell::Cell, future::pending, hash::Hash, path::PathBuf, sync::Arc}; use std::cell::Cell;
use std::future::pending;
use std::hash::Hash;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use super::{Mounter, MounterAuth, MounterItem, MounterItems, MounterMessage}; use super::{Mounter, MounterAuth, MounterItem, MounterItems, MounterMessage};
use crate::{ use crate::config::IconSizes;
config::IconSizes, use crate::err_str;
err_str, use crate::tab::{self, DirSize, ItemMetadata, ItemThumbnail, Location};
tab::{self, DirSize, ItemMetadata, ItemThumbnail, Location},
};
const TARGET_URI_ATTRIBUTE: &str = "standard::target-uri"; const TARGET_URI_ATTRIBUTE: &str = "standard::target-uri";

View file

@ -1,13 +1,13 @@
use cosmic::{Task, iced::Subscription, widget}; use cosmic::iced::Subscription;
use std::{ use cosmic::{Task, widget};
collections::BTreeMap, use std::collections::BTreeMap;
fmt, use std::fmt;
path::PathBuf, use std::path::PathBuf;
sync::{Arc, LazyLock}, use std::sync::{Arc, LazyLock};
};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::{config::IconSizes, tab}; use crate::config::IconSizes;
use crate::tab;
#[cfg(feature = "gvfs")] #[cfg(feature = "gvfs")]
mod gvfs; mod gvfs;

View file

@ -3,21 +3,17 @@
use std::time::Instant; use std::time::Instant;
use crate::tab::DOUBLE_CLICK_DURATION; use crate::tab::DOUBLE_CLICK_DURATION;
use cosmic::{ use cosmic::iced::core::border::Border;
Element, Renderer, Theme, use cosmic::iced::core::event::Event;
iced::core::{ use cosmic::iced::core::mouse::{self, click};
Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, use cosmic::iced::core::renderer::{self, Quad, Renderer as _};
border::Border, use cosmic::iced::core::widget::{Operation, Tree, tree};
event::Event, use cosmic::iced::core::{
layout, Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, layout,
mouse::{self, click}, overlay, touch,
overlay,
renderer::{self, Quad, Renderer as _},
touch,
widget::{Operation, Tree, tree},
},
widget::Id,
}; };
use cosmic::widget::Id;
use cosmic::{Element, Renderer, Theme};
/// Emit messages on mouse events. /// Emit messages on mouse events.
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]

View file

@ -1,20 +1,15 @@
use crate::{ use crate::app::{ArchiveType, DialogPage, Message, REPLACE_BUTTON_ID};
app::{ArchiveType, DialogPage, Message, REPLACE_BUTTON_ID}, use crate::config::IconSizes;
archive, use crate::spawn_detached::spawn_detached;
config::IconSizes, use crate::{archive, fl, tab};
fl, use cosmic::iced::futures::channel::mpsc::Sender;
spawn_detached::spawn_detached, use cosmic::iced::futures::{self, SinkExt, StreamExt, stream};
tab, use std::borrow::Cow;
}; use std::fmt::Formatter;
use cosmic::iced::futures::{self, SinkExt, StreamExt, channel::mpsc::Sender, stream}; use std::fs;
use std::{ use std::io::{self, Read, Write};
borrow::Cow, use std::path::{Path, PathBuf};
fmt::Formatter, use std::sync::Arc;
fs,
io::{self, Read, Write},
path::{Path, PathBuf},
sync::Arc,
};
use tokio::sync::{Mutex as TokioMutex, mpsc}; use tokio::sync::{Mutex as TokioMutex, mpsc};
use walkdir::WalkDir; use walkdir::WalkDir;
use zip::AesMode::Aes256; use zip::AesMode::Aes256;
@ -1243,28 +1238,23 @@ fn wrap_compio_spawn_error(err: Box<dyn std::any::Any + Send>) -> OperationError
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ use std::fs::{self, File};
fs::{self, File}, use std::io;
io, use std::path::PathBuf;
path::PathBuf,
};
use cosmic::iced::futures::{StreamExt, channel::mpsc, future}; use cosmic::iced::futures::channel::mpsc;
use cosmic::iced::futures::{StreamExt, future};
use log::debug; use log::debug;
use test_log::test; use test_log::test;
use tokio::sync; use tokio::sync;
use super::{Controller, Operation, OperationError, OperationSelection, ReplaceResult}; use super::{Controller, Operation, OperationError, OperationSelection, ReplaceResult};
use crate::{ use crate::app::test_utils::{
app::{ NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, NUM_NESTED, empty_fs, filter_dirs, filter_files,
DialogPage, Message, simple_fs,
test_utils::{
NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, NUM_NESTED, empty_fs, filter_dirs,
filter_files, simple_fs,
},
},
fl,
}; };
use crate::app::{DialogPage, Message};
use crate::fl;
/// Simple wrapper around `[Operation::Copy]` /// Simple wrapper around `[Operation::Copy]`
pub async fn operation_copy( pub async fn operation_copy(

View file

@ -1,4 +1,5 @@
use std::{fs, io, path::Path}; use std::path::Path;
use std::{fs, io};
use crate::operation::OperationError; use crate::operation::OperationError;

View file

@ -6,15 +6,20 @@ use crate::operation::{OperationError, sync_to_disk};
use anyhow::Context as AnyhowContext; use anyhow::Context as AnyhowContext;
use compio::BufResult; use compio::BufResult;
use compio::buf::{IntoInner, IoBuf}; use compio::buf::{IntoInner, IoBuf};
use compio::driver::{ToSharedFd, op::AsyncifyFd}; use compio::driver::ToSharedFd;
use compio::driver::op::AsyncifyFd;
use compio::io::{AsyncReadAt, AsyncWriteAt}; use compio::io::{AsyncReadAt, AsyncWriteAt};
use cosmic::iced::futures; use cosmic::iced::futures;
use futures::{FutureExt, StreamExt}; use futures::{FutureExt, StreamExt};
use std::cell::Cell;
use std::error::Error;
use std::fs;
use std::future::Future; use std::future::Future;
use std::ops::ControlFlow;
use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::time::Instant; use std::time::Instant;
use std::{cell::Cell, error::Error, fs, ops::ControlFlow, path::PathBuf};
use walkdir::WalkDir; use walkdir::WalkDir;
#[cfg(feature = "gvfs")] #[cfg(feature = "gvfs")]

View file

@ -1,91 +1,71 @@
#[cfg(feature = "desktop")] #[cfg(feature = "desktop")]
use cosmic::desktop::fde::{DesktopEntry, get_languages_from_env}; use cosmic::desktop::fde::{DesktopEntry, get_languages_from_env};
use cosmic::{ use cosmic::iced::advanced::graphics;
Apply, Element, cosmic_theme, font, use cosmic::iced::advanced::text::{self, Paragraph};
iced::core::{mouse::ScrollDelta, widget::tree}, use cosmic::iced::alignment::Vertical;
iced::{ use cosmic::iced::clipboard::dnd::DndAction;
use cosmic::iced::core::mouse::ScrollDelta;
use cosmic::iced::core::widget::tree;
use cosmic::iced::futures::{self, SinkExt};
use cosmic::iced::keyboard::Modifiers;
use cosmic::iced::widget::scrollable::{self, AbsoluteOffset, Viewport};
use cosmic::iced::widget::{rule, stack};
use cosmic::iced::{
Alignment, Border, Color, ContentFit, Length, Point, Rectangle, Size, Subscription, Vector, Alignment, Border, Color, ContentFit, Length, Point, Rectangle, Size, Subscription, Vector,
advanced::{ padding, stream, window,
graphics,
text::{self, Paragraph},
},
alignment::Vertical,
clipboard::dnd::DndAction,
futures::{self, SinkExt},
keyboard::Modifiers,
padding, stream,
widget::{
rule,
scrollable::{self, AbsoluteOffset, Viewport},
stack,
},
window,
},
theme,
widget::{
self, DndDestination, DndSource, Id, RcElementWrapper, Widget,
menu::{action::MenuAction, key_bind::KeyBind},
space,
},
}; };
use cosmic::widget::menu::action::MenuAction;
use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::{self, DndDestination, DndSource, Id, RcElementWrapper, Widget, space};
use cosmic::{Apply, Element, cosmic_theme, font, theme};
use i18n_embed::LanguageLoader; use i18n_embed::LanguageLoader;
use icu::{ use icu::datetime::input::DateTime;
datetime::{ use icu::datetime::options::TimePrecision;
DateTimeFormatter, DateTimeFormatterPreferences, fieldsets, input::DateTime, use icu::datetime::{DateTimeFormatter, DateTimeFormatterPreferences, fieldsets};
options::TimePrecision, use icu::locale::preferences::extensions::unicode::keywords::HourCycle;
},
locale::preferences::extensions::unicode::keywords::HourCycle,
};
use image::{DynamicImage, ImageReader}; use image::{DynamicImage, ImageReader};
use jiff_icu::ConvertFrom; use jiff_icu::ConvertFrom;
use mime_guess::{Mime, mime}; use mime_guess::{Mime, mime};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::cell::Cell;
use std::cmp::{Ordering, Reverse};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::error::Error;
use std::fmt::{self, Display};
use std::fs::{self, File, Metadata};
use std::hash::Hash;
use std::io::{BufRead, BufReader};
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::{ use std::path::{self, Path, PathBuf};
borrow::Cow, use std::sync::{Arc, LazyLock, RwLock, atomic};
cell::Cell, use std::time::{Duration, Instant, SystemTime};
cmp::{Ordering, Reverse},
collections::{BTreeMap, BTreeSet, HashMap},
error::Error,
fmt::{self, Display},
fs::{self, File, Metadata},
hash::Hash,
io::{BufRead, BufReader},
path::{self, Path, PathBuf},
sync::{Arc, LazyLock, RwLock, atomic},
time::{Duration, Instant, SystemTime},
};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use trash::{TrashItem, TrashItemMetadata, TrashItemSize}; use trash::{TrashItem, TrashItemMetadata, TrashItemSize};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::{ use crate::app::{Action, PreviewItem, PreviewKind};
FxOrderMap, use crate::clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste};
app::{Action, PreviewItem, PreviewKind}, use crate::config::{
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
config::{
ContextActionPreset, DesktopConfig, ICON_SCALE_MAX, ICON_SIZE_GRID, IconSizes, TabConfig, ContextActionPreset, DesktopConfig, ICON_SCALE_MAX, ICON_SIZE_GRID, IconSizes, TabConfig,
ThumbCfg, ThumbCfg,
}, };
dialog::DialogKind, use crate::dialog::DialogKind;
fl, use crate::large_image::{
large_image::{
LargeImageManager, decode_large_image, exceeds_memory_limit, should_use_dedicated_worker, LargeImageManager, decode_large_image, exceeds_memory_limit, should_use_dedicated_worker,
should_use_tiling, should_use_tiling,
},
localize::{LANGUAGE_SORTER, LOCALE},
menu, mime_app,
mime_icon::{mime_for_path, mime_icon},
mounter::MOUNTERS,
mouse_area,
operation::{Controller, OperationError},
thumbnail_cacher::{CachedThumbnail, ThumbnailCacher, ThumbnailSize},
thumbnailer::thumbnailer,
trash::{Trash, TrashExt},
}; };
use crate::localize::{LANGUAGE_SORTER, LOCALE};
use crate::mime_icon::{mime_for_path, mime_icon};
use crate::mounter::MOUNTERS;
use crate::operation::{Controller, OperationError};
use crate::thumbnail_cacher::{CachedThumbnail, ThumbnailCacher, ThumbnailSize};
use crate::thumbnailer::thumbnailer;
use crate::trash::{Trash, TrashExt};
use crate::{FxOrderMap, fl, menu, mime_app, mouse_area};
pub const DOUBLE_CLICK_DURATION: Duration = Duration::from_millis(500); pub const DOUBLE_CLICK_DURATION: Duration = Duration::from_millis(500);
pub const HOVER_DURATION: Duration = Duration::from_millis(1600); pub const HOVER_DURATION: Duration = Duration::from_millis(1600);
@ -7040,21 +7020,22 @@ fn text_editor_class(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{fs, io, path::PathBuf}; use std::path::PathBuf;
use std::{fs, io};
use cosmic::{iced::mouse::ScrollDelta, iced::runtime::keyboard::Modifiers, widget}; use cosmic::iced::mouse::ScrollDelta;
use cosmic::iced::runtime::keyboard::Modifiers;
use cosmic::widget;
use log::{debug, trace}; use log::{debug, trace};
use tempfile::TempDir; use tempfile::TempDir;
use test_log::test; use test_log::test;
use super::{Location, Message, Tab, respond_to_scroll_direction, scan_path}; use super::{Location, Message, Tab, respond_to_scroll_direction, scan_path};
use crate::{ use crate::app::test_utils::{
app::test_utils::{
NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, NUM_NESTED, assert_eq_tab_path, empty_fs, NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, NUM_NESTED, assert_eq_tab_path, empty_fs,
eq_path_item, filter_dirs, read_dir_sorted, simple_fs, tab_click_new, eq_path_item, filter_dirs, read_dir_sorted, simple_fs, tab_click_new,
},
config::{IconSizes, TabConfig, ThumbCfg},
}; };
use crate::config::{IconSizes, TabConfig, ThumbCfg};
// Boilerplate for tab tests. Checks if simulated clicks selected items. // Boilerplate for tab tests. Checks if simulated clicks selected items.
fn tab_selects_item( fn tab_selects_item(

View file

@ -1,16 +1,14 @@
use image::DynamicImage; use image::DynamicImage;
use md5::{Digest, Md5}; use md5::{Digest, Md5};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::error::Error;
use std::fs::{self, File};
use std::io::{self, BufReader, BufWriter};
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::{ use std::path::{Path, PathBuf};
error::Error, use std::sync::LazyLock;
fs::{self, File}, use std::time::UNIX_EPOCH;
io::{self, BufReader, BufWriter},
path::{Path, PathBuf},
sync::LazyLock,
time::UNIX_EPOCH,
};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use url::Url; use url::Url;

View file

@ -5,13 +5,10 @@
use cosmic::desktop::fde::GenericEntry; use cosmic::desktop::fde::GenericEntry;
use mime_guess::Mime; use mime_guess::Mime;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::{ use std::path::Path;
fs, use std::sync::{LazyLock, Mutex};
path::Path, use std::time::Instant;
process, use std::{fs, process};
sync::{LazyLock, Mutex},
time::Instant,
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Thumbnailer { pub struct Thumbnailer {

View file

@ -1,11 +1,10 @@
use cosmic::widget; use cosmic::widget;
use regex::Regex; use regex::Regex;
use std::{collections::HashSet, path::PathBuf}; use std::collections::HashSet;
use std::path::PathBuf;
use crate::{ use crate::config::IconSizes;
config::IconSizes, use crate::tab::{Item, SearchItem};
tab::{Item, SearchItem},
};
pub trait TrashExt { pub trait TrashExt {
fn is_empty() -> bool { fn is_empty() -> bool {
@ -81,7 +80,8 @@ impl TrashExt for Trash {
} }
fn scan(sizes: IconSizes) -> Vec<Item> { fn scan(sizes: IconSizes) -> Vec<Item> {
use crate::{localize::LANGUAGE_SORTER, tab::item_from_trash_entry}; use crate::localize::LANGUAGE_SORTER;
use crate::tab::item_from_trash_entry;
use std::cmp::Ordering; use std::cmp::Ordering;
let entries = match trash::os_limited::list() { let entries = match trash::os_limited::list() {

View file

@ -1,6 +1,7 @@
use std::num::NonZeroU16; use std::num::NonZeroU16;
use crate::{config::IconSizes, tab::View}; use crate::config::IconSizes;
use crate::tab::View;
static DEFAULT_ZOOM: NonZeroU16 = NonZeroU16::new(100).unwrap(); static DEFAULT_ZOOM: NonZeroU16 = NonZeroU16::new(100).unwrap();
static MIN_ZOOM: NonZeroU16 = NonZeroU16::new(50).unwrap(); static MIN_ZOOM: NonZeroU16 = NonZeroU16::new(50).unwrap();