Add a per Tab config
A tab config is useful for allowing users to show hidden files, sorting by different metrics such as size or MIME type, as well as providing a way to implement some of the todos such as configurable icon sizes for views.
This commit is contained in:
parent
75874caf9d
commit
073a9a95ab
4 changed files with 41 additions and 14 deletions
|
|
@ -26,7 +26,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{AppTheme, Config, CONFIG_VERSION},
|
config::{AppTheme, Config, Tab as TabConfig, CONFIG_VERSION},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::{key_binds, KeyBind},
|
key_bind::{key_binds, KeyBind},
|
||||||
menu, mouse_area,
|
menu, mouse_area,
|
||||||
|
|
@ -186,7 +186,7 @@ pub struct App {
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn open_tab(&mut self, location: Location) -> Command<Message> {
|
fn open_tab(&mut self, location: Location) -> Command<Message> {
|
||||||
let tab = Tab::new(location.clone());
|
let tab = Tab::new(location.clone(), TabConfig::default());
|
||||||
let entity = self
|
let entity = self
|
||||||
.tab_model
|
.tab_model
|
||||||
.insert()
|
.insert()
|
||||||
|
|
@ -1237,7 +1237,7 @@ pub(crate) mod test_utils {
|
||||||
// New tab with items
|
// New tab with items
|
||||||
let location = Location::Path(path.to_owned());
|
let location = Location::Path(path.to_owned());
|
||||||
let items = location.scan();
|
let items = location.scan();
|
||||||
let mut tab = Tab::new(location);
|
let mut tab = Tab::new(location, TabConfig::default());
|
||||||
tab.items_opt = Some(items);
|
tab.items_opt = Some(items);
|
||||||
|
|
||||||
// Ensure correct number of directories as a sanity check
|
// Ensure correct number of directories as a sanity check
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,33 @@ impl AppTheme {
|
||||||
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub app_theme: AppTheme,
|
pub app_theme: AppTheme,
|
||||||
|
pub tab: Tab,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
app_theme: AppTheme::System,
|
app_theme: AppTheme::System,
|
||||||
|
tab: Tab::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Per tab config
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
|
||||||
|
pub struct Tab {
|
||||||
|
/// Show hidden files
|
||||||
|
pub show_hidden: bool,
|
||||||
|
// TODO: Other possible options
|
||||||
|
// pub sort_by: fn(&PathBuf, &PathBuf) -> Ordering,
|
||||||
|
// Icon handle sizes
|
||||||
|
// icon_size_dialog: u16,
|
||||||
|
// icon_size_list: u16,
|
||||||
|
// icon_size_grid: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Tab {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { show_hidden: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config::Tab as TabConfig,
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
tab::{self, Location, Tab},
|
tab::{self, Location, Tab},
|
||||||
};
|
};
|
||||||
|
|
@ -78,7 +79,7 @@ pub struct App {
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn open_tab(&mut self, location: Location) -> Command<Message> {
|
fn open_tab(&mut self, location: Location) -> Command<Message> {
|
||||||
let mut tab = Tab::new(location.clone());
|
let mut tab = Tab::new(location.clone(), TabConfig::default());
|
||||||
tab.dialog = true;
|
tab.dialog = true;
|
||||||
let entity = self
|
let entity = self
|
||||||
.tab_model
|
.tab_model
|
||||||
|
|
|
||||||
25
src/tab.rs
25
src/tab.rs
|
|
@ -23,7 +23,7 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{fl, home_dir, mime_icon::mime_icon};
|
use crate::{config::Tab as TabConfig, fl, home_dir, mime_icon::mime_icon};
|
||||||
|
|
||||||
const DOUBLE_CLICK_DURATION: Duration = Duration::from_millis(500);
|
const DOUBLE_CLICK_DURATION: Duration = Duration::from_millis(500);
|
||||||
//TODO: configurable
|
//TODO: configurable
|
||||||
|
|
@ -524,10 +524,11 @@ pub struct Tab {
|
||||||
pub edit_location: Option<Location>,
|
pub edit_location: Option<Location>,
|
||||||
pub history_i: usize,
|
pub history_i: usize,
|
||||||
pub history: Vec<Location>,
|
pub history: Vec<Location>,
|
||||||
|
pub config: TabConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn new(location: Location) -> Self {
|
pub fn new(location: Location, config: TabConfig) -> Self {
|
||||||
let history = vec![location.clone()];
|
let history = vec![location.clone()];
|
||||||
Self {
|
Self {
|
||||||
location,
|
location,
|
||||||
|
|
@ -538,6 +539,7 @@ impl Tab {
|
||||||
edit_location: None,
|
edit_location: None,
|
||||||
history_i: 0,
|
history_i: 0,
|
||||||
history,
|
history,
|
||||||
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1054,10 +1056,13 @@ mod tests {
|
||||||
use test_log::test;
|
use test_log::test;
|
||||||
|
|
||||||
use super::{scan_path, Item, Location, Message, Tab};
|
use super::{scan_path, Item, Location, Message, Tab};
|
||||||
use crate::app::test_utils::{
|
use crate::{
|
||||||
assert_eq_tab_path, assert_eq_tab_path_contents, empty_fs, eq_path_item, filter_dirs,
|
app::test_utils::{
|
||||||
read_dir_sorted, simple_fs, sort_files, tab_click_new, NAME_LEN, NUM_DIRS, NUM_FILES,
|
assert_eq_tab_path, assert_eq_tab_path_contents, empty_fs, eq_path_item, filter_dirs,
|
||||||
NUM_HIDDEN, NUM_NESTED,
|
read_dir_sorted, simple_fs, sort_files, tab_click_new, NAME_LEN, NUM_DIRS, NUM_FILES,
|
||||||
|
NUM_HIDDEN, NUM_NESTED,
|
||||||
|
},
|
||||||
|
config::Tab as TabConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Boilerplate for tab tests. Checks if simulated clicks selected items.
|
// Boilerplate for tab tests. Checks if simulated clicks selected items.
|
||||||
|
|
@ -1098,7 +1103,7 @@ mod tests {
|
||||||
fn tab_history() -> io::Result<(TempDir, Tab, Vec<PathBuf>)> {
|
fn tab_history() -> io::Result<(TempDir, Tab, Vec<PathBuf>)> {
|
||||||
let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?;
|
let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?;
|
||||||
let path = fs.path();
|
let path = fs.path();
|
||||||
let mut tab = Tab::new(Location::Path(path.into()));
|
let mut tab = Tab::new(Location::Path(path.into()), TabConfig::default());
|
||||||
|
|
||||||
// All directories (simple_fs only produces one nested layer)
|
// All directories (simple_fs only produces one nested layer)
|
||||||
let dirs: Vec<PathBuf> = filter_dirs(path)?
|
let dirs: Vec<PathBuf> = filter_dirs(path)?
|
||||||
|
|
@ -1195,7 +1200,7 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("temp directory should have at least one directory");
|
.expect("temp directory should have at least one directory");
|
||||||
|
|
||||||
let mut tab = Tab::new(Location::Path(path.to_owned()));
|
let mut tab = Tab::new(Location::Path(path.to_owned()), TabConfig::default());
|
||||||
debug!(
|
debug!(
|
||||||
"Emitting Message::Location(Location::Path(\"{}\"))",
|
"Emitting Message::Location(Location::Path(\"{}\"))",
|
||||||
next_dir.display()
|
next_dir.display()
|
||||||
|
|
@ -1294,7 +1299,7 @@ mod tests {
|
||||||
fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> {
|
fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> {
|
||||||
let fs = simple_fs(0, NUM_NESTED, NUM_DIRS, 0, NAME_LEN)?;
|
let fs = simple_fs(0, NUM_NESTED, NUM_DIRS, 0, NAME_LEN)?;
|
||||||
let path = fs.path();
|
let path = fs.path();
|
||||||
let mut tab = Tab::new(Location::Path(path.into()));
|
let mut tab = Tab::new(Location::Path(path.into()), TabConfig::default());
|
||||||
|
|
||||||
// Tab's location shouldn't change if GoPrev or GoNext is triggered
|
// Tab's location shouldn't change if GoPrev or GoNext is triggered
|
||||||
debug!("Emitting Message::GoPrevious",);
|
debug!("Emitting Message::GoPrevious",);
|
||||||
|
|
@ -1316,7 +1321,7 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("should be at least one directory");
|
.expect("should be at least one directory");
|
||||||
|
|
||||||
let mut tab = Tab::new(Location::Path(next_dir.clone()));
|
let mut tab = Tab::new(Location::Path(next_dir.clone()), TabConfig::default());
|
||||||
// This will eventually yield false once root is hit
|
// This will eventually yield false once root is hit
|
||||||
while next_dir.pop() {
|
while next_dir.pop() {
|
||||||
debug!("Emitting Message::LocationUp",);
|
debug!("Emitting Message::LocationUp",);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue