Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visible columns #63

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions i18n/en/cosmic_files.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ replace-warning = Do you want to replace it with the one you are saving? Replaci
# List view
name = Name
modified = Modified
accessed = Accessed
created = Created
size = Size

# Context Pages
Expand Down Expand Up @@ -97,3 +99,8 @@ grid-view = Grid view
list-view = List view
menu-settings = Settings...
menu-about = About COSMIC Files...

## Visible columns
visible-columns = Visible columns
move-up = Move up
move-down = Move down
104 changes: 98 additions & 6 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

use cosmic::{
app::{message, Command, Core},
cosmic_config, cosmic_theme, executor,
cosmic_config,
cosmic_theme::{self, Spacing},
executor,
iced::{
event,
futures::{self, SinkExt},
Expand All @@ -12,6 +14,7 @@ use cosmic::{
widget::scrollable,
window, Alignment, Event, Length,
},
iced_widget::horizontal_rule,
style, theme,
widget::{self, segmented_button},
Application, ApplicationExt, Element,
Expand All @@ -27,12 +30,12 @@ use std::{
};

use crate::{
config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION},
config::{AppTheme, Config, IconSizes, TabConfig, VisibleColumns, CONFIG_VERSION},
fl, home_dir,
key_bind::{key_binds, KeyBind},
menu,
operation::Operation,
tab::{self, ItemMetadata, Location, Tab},
tab::{self, HeadingOptions, ItemMetadata, Location, Tab},
};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -74,6 +77,7 @@ pub enum Action {
ToggleShowHidden,
WindowClose,
WindowNew,
VisibleColumns,
}

impl Action {
Expand Down Expand Up @@ -114,6 +118,7 @@ impl Action {
Action::ToggleShowHidden => Message::TabMessage(None, tab::Message::ToggleShowHidden),
Action::WindowClose => Message::WindowClose,
Action::WindowNew => Message::WindowNew,
Action::VisibleColumns => Message::ToggleContextPage(ContextPage::VisibleColumns),
}
}
}
Expand All @@ -124,6 +129,7 @@ pub enum Message {
AppTheme(AppTheme),
Config(Config),
Copy(Option<segmented_button::Entity>),
ChangeVisibleColumnPopover(bool, HeadingOptions),
Cut(Option<segmented_button::Entity>),
DialogCancel,
DialogComplete,
Expand Down Expand Up @@ -162,6 +168,7 @@ pub enum ContextPage {
Operations,
Properties,
Settings,
VisibleColumns,
}

impl ContextPage {
Expand All @@ -171,6 +178,7 @@ impl ContextPage {
Self::Operations => fl!("operations"),
Self::Properties => fl!("properties"),
Self::Settings => fl!("settings"),
Self::VisibleColumns => fl!("visible-columns"),
}
}
}
Expand Down Expand Up @@ -226,6 +234,7 @@ pub struct App {
complete_operations: BTreeMap<u64, Operation>,
failed_operations: BTreeMap<u64, (Operation, String)>,
watcher_opt: Option<(notify::RecommendedWatcher, HashSet<PathBuf>)>,
visible_column_move_selected: Option<HeadingOptions>,
}

impl App {
Expand Down Expand Up @@ -477,7 +486,7 @@ impl App {
list: NonZeroU16::new(list).unwrap(),
..tab_config.icon_sizes
},
..tab_config
..tab_config.clone()
})
})
.step(25u16)
Expand All @@ -496,7 +505,7 @@ impl App {
grid: NonZeroU16::new(grid).unwrap(),
..tab_config.icon_sizes
},
..tab_config
..tab_config.clone()
})
})
.step(25u16)
Expand All @@ -512,7 +521,7 @@ impl App {
move |show_hidden| {
Message::TabConfig(TabConfig {
show_hidden,
..tab_config
..tab_config.clone()
})
},
)
Expand All @@ -521,6 +530,84 @@ impl App {
])
.into()
}
fn visible_columns(&self) -> Element<Message> {
let column_options = &self.config.tab.visible_columns;
let Spacing { space_xxs, .. } = self.core.system_theme().cosmic().spacing;
let column_item = |col: VisibleColumns, idx: usize| -> Element<Message> {
let is_selected = self
.visible_column_move_selected
.is_some_and(|c| c == col.heading);
let mut popover = widget::popover(
widget::button(widget::icon::from_name("open-menu-symbolic"))
.on_press(Message::ChangeVisibleColumnPopover(
!is_selected,
col.heading,
))
.style(cosmic::style::Button::Icon),
);

let move_item = |mut config: TabConfig, direction: bool| {
if direction && idx < config.visible_columns.len() - 1 {
config.visible_columns.swap(idx, idx + 1)
} else if !direction && idx != 0 {
config.visible_columns.swap(idx, idx - 1)
}
config
};

if is_selected {
popover = popover
.popup(
widget::container(
widget::column::with_children(vec![
widget::button(widget::text(fl!("move-up")))
.on_press(Message::TabConfig(move_item(
self.config.tab.clone(),
false,
)))
.padding(space_xxs)
.style(theme::Button::Text)
.into(),
horizontal_rule(1).into(),
widget::button(widget::text(fl!("move-down")))
.on_press(Message::TabConfig(move_item(
self.config.tab.clone(),
true,
)))
.padding(space_xxs)
.style(theme::Button::Text)
.into(),
])
.width(Length::Shrink),
)
.style(theme::Container::Background),
)
.position(widget::popover::Position::Bottom)
.into()
}

widget::settings::item::builder(col.heading.to_string())
.control(
widget::row::with_children(vec![
widget::toggler(None, col.active, move |t| {
let mut config = self.config.tab.clone();
config.visible_columns[idx].active = t;
Message::TabConfig(config)
})
.into(),
popover.into(),
])
.align_items(Alignment::Center),
)
.into()
};

let mut view_section = widget::settings::view_section("");
for (idx, col) in column_options.iter().enumerate() {
view_section = view_section.add(column_item(col.clone(), idx));
}
widget::settings::view_column(vec![view_section.into()]).into()
}
}

/// Implement [`Application`] to integrate with COSMIC.
Expand Down Expand Up @@ -601,6 +688,7 @@ impl Application for App {
complete_operations: BTreeMap::new(),
failed_operations: BTreeMap::new(),
watcher_opt: None,
visible_column_move_selected: None,
};

let mut commands = Vec::new();
Expand Down Expand Up @@ -735,6 +823,9 @@ impl Application for App {
Message::Copy(_entity_opt) => {
log::warn!("TODO: COPY");
}
Message::ChangeVisibleColumnPopover(active, column) => {
self.visible_column_move_selected = active.then_some(column);
}
Message::Cut(_entity_opt) => {
log::warn!("TODO: CUT");
}
Expand Down Expand Up @@ -1129,6 +1220,7 @@ impl Application for App {
ContextPage::Operations => self.operations(),
ContextPage::Properties => self.properties(),
ContextPage::Settings => self.settings(),
ContextPage::VisibleColumns => self.visible_columns(),
})
}

Expand Down
26 changes: 25 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use cosmic::{
};
use serde::{Deserialize, Serialize};

use crate::tab::HeadingOptions;

pub const CONFIG_VERSION: u64 = 1;

// Default icon sizes
Expand Down Expand Up @@ -54,21 +56,23 @@ impl Default for Config {
/// [`TabConfig`] contains options that are passed to each instance of [`crate::tab::Tab`].
/// These options are set globally through the main config, but each tab may change options
/// locally. Local changes aren't saved to the main config.
#[derive(Clone, Copy, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
pub struct TabConfig {
/// Show hidden files and folders
pub show_hidden: bool,
// TODO: Other possible options
// pub sort_by: fn(&PathBuf, &PathBuf) -> Ordering,
// Icon zoom
pub icon_sizes: IconSizes,
pub visible_columns: Vec<VisibleColumns>,
}

impl Default for TabConfig {
fn default() -> Self {
Self {
show_hidden: false,
icon_sizes: IconSizes::default(),
visible_columns: VisibleColumns::default(),
}
}
}
Expand All @@ -94,6 +98,26 @@ impl Default for IconSizes {
}
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct VisibleColumns {
pub active: bool,
pub heading: HeadingOptions,
}
impl VisibleColumns {
pub fn new(active: bool, heading: HeadingOptions) -> Self {
Self { active, heading }
}
fn default() -> Vec<Self> {
vec![
VisibleColumns::new(true, HeadingOptions::Name),
VisibleColumns::new(true, HeadingOptions::Modified),
VisibleColumns::new(false, HeadingOptions::Accessed),
VisibleColumns::new(false, HeadingOptions::Created),
VisibleColumns::new(true, HeadingOptions::Size),
]
}
}

impl IconSizes {
pub fn list(&self) -> u16 {
percent!(self.list, ICON_SIZE_LIST) as _
Expand Down
2 changes: 2 additions & 0 deletions src/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ pub fn menu_bar<'a>(key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message
MenuTree::new(horizontal_rule(1)),
menu_item(fl!("menu-settings"), Action::Settings),
MenuTree::new(horizontal_rule(1)),
menu_item(fl!("visible-columns"), Action::VisibleColumns),
MenuTree::new(horizontal_rule(1)),
menu_item(fl!("menu-about"), Action::About),
],
),
Expand Down
Loading