2021-11-28 08:49:20 +13:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
|
|
|
|
use gtk::prelude::*;
|
2021-12-22 06:23:17 +13:00
|
|
|
use gtk::{ListStore, TextView, TreeView, Widget};
|
2021-11-28 08:49:20 +13:00
|
|
|
|
2020-11-01 02:23:31 +13:00
|
|
|
use czkawka_core::big_file::BigFile;
|
2021-01-13 08:06:12 +13:00
|
|
|
use czkawka_core::broken_files::BrokenFiles;
|
2020-09-30 05:44:20 +13:00
|
|
|
use czkawka_core::common_messages::Messages;
|
2020-11-01 02:23:31 +13:00
|
|
|
use czkawka_core::duplicate::DuplicateFinder;
|
|
|
|
use czkawka_core::empty_files::EmptyFiles;
|
|
|
|
use czkawka_core::empty_folder::EmptyFolder;
|
2020-12-22 04:09:39 +13:00
|
|
|
use czkawka_core::invalid_symlinks::InvalidSymlinks;
|
2020-11-03 09:56:07 +13:00
|
|
|
use czkawka_core::same_music::SameMusic;
|
2021-07-25 08:00:39 +12:00
|
|
|
use czkawka_core::similar_images::SimilarImages;
|
2021-11-23 23:10:24 +13:00
|
|
|
use czkawka_core::similar_videos::SimilarVideos;
|
2020-11-01 02:23:31 +13:00
|
|
|
use czkawka_core::temporary::Temporary;
|
2022-01-02 09:07:20 +13:00
|
|
|
use czkawka_core::{common_dir_traversal, fl};
|
2021-11-28 08:49:20 +13:00
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
use crate::notebook_enums::{NotebookMainEnum, NotebookUpperEnum, NUMBER_OF_NOTEBOOK_MAIN_TABS};
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-12-22 06:23:17 +13:00
|
|
|
#[cfg(not(target_family = "windows"))]
|
|
|
|
pub const CHARACTER: char = '/';
|
|
|
|
#[cfg(target_family = "windows")]
|
|
|
|
pub const CHARACTER: char = '\\';
|
|
|
|
|
2021-11-29 23:38:38 +13:00
|
|
|
pub const KEY_DELETE: u32 = 119;
|
|
|
|
pub const KEY_ENTER: u32 = 36;
|
|
|
|
pub const KEY_SPACE: u32 = 65;
|
|
|
|
|
2021-12-04 03:17:59 +13:00
|
|
|
// pub const KEY_DOWN: u32 = 116;
|
|
|
|
// pub const KEY_UP: u32 = 111;
|
|
|
|
// pub const KEY_PG_DOWN: u32 = 117;
|
|
|
|
// pub const KEY_PG_UP: u32 = 112;
|
|
|
|
// pub const KEY_HOME: u32 = 115;
|
|
|
|
// pub const KEY_END: u32 = 110;
|
2021-11-29 23:38:38 +13:00
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
#[derive(Eq, PartialEq)]
|
|
|
|
pub enum PopoverTypes {
|
|
|
|
All,
|
2021-12-02 08:09:04 +13:00
|
|
|
Size,
|
2021-11-25 20:36:49 +13:00
|
|
|
Reverse,
|
|
|
|
Custom,
|
|
|
|
Date,
|
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct NotebookObject {
|
|
|
|
pub notebook_type: NotebookMainEnum,
|
2021-12-06 09:01:16 +13:00
|
|
|
pub available_modes: [PopoverTypes; 5],
|
2021-11-25 20:36:49 +13:00
|
|
|
pub column_activatable_button: Option<i32>,
|
|
|
|
pub column_path: i32,
|
|
|
|
pub column_name: i32,
|
|
|
|
pub column_selection: i32,
|
|
|
|
pub column_color: Option<i32>,
|
|
|
|
pub column_dimensions: Option<i32>,
|
|
|
|
pub column_size: Option<i32>,
|
|
|
|
pub column_size_as_bytes: Option<i32>,
|
|
|
|
pub column_modification_as_secs: Option<i32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub static NOTEBOOKS_INFOS: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::Duplicate,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::Date, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: Some(ColumnsDuplicates::ActivatableSelectButton as i32),
|
|
|
|
column_path: ColumnsDuplicates::Path as i32,
|
|
|
|
column_name: ColumnsDuplicates::Name as i32,
|
|
|
|
column_selection: ColumnsDuplicates::SelectionButton as i32,
|
|
|
|
column_color: Some(ColumnsDuplicates::Color as i32),
|
|
|
|
column_dimensions: None,
|
2021-12-24 21:18:55 +13:00
|
|
|
column_size: None, // Do not add, useless in hash and size mode
|
|
|
|
column_size_as_bytes: None, // Do not add, useless in hash and size mode
|
2021-11-25 20:36:49 +13:00
|
|
|
column_modification_as_secs: Some(ColumnsDuplicates::ModificationAsSecs as i32),
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::EmptyDirectories,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsEmptyFolders::Path as i32,
|
|
|
|
column_name: ColumnsEmptyFolders::Name as i32,
|
|
|
|
column_selection: ColumnsEmptyFolders::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::BigFiles,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsBigFiles::Path as i32,
|
|
|
|
column_name: ColumnsBigFiles::Name as i32,
|
|
|
|
column_selection: ColumnsBigFiles::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::EmptyFiles,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsEmptyFiles::Path as i32,
|
|
|
|
column_name: ColumnsEmptyFiles::Name as i32,
|
|
|
|
column_selection: ColumnsEmptyFiles::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::Temporary,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsTemporaryFiles::Path as i32,
|
|
|
|
column_name: ColumnsTemporaryFiles::Name as i32,
|
|
|
|
column_selection: ColumnsTemporaryFiles::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::SimilarImages,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::Date, PopoverTypes::Size],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: Some(ColumnsSimilarImages::ActivatableSelectButton as i32),
|
|
|
|
column_path: ColumnsSimilarImages::Path as i32,
|
|
|
|
column_name: ColumnsSimilarImages::Name as i32,
|
|
|
|
column_selection: ColumnsSimilarImages::SelectionButton as i32,
|
|
|
|
column_color: Some(ColumnsSimilarImages::Color as i32),
|
|
|
|
column_dimensions: Some(ColumnsSimilarImages::Dimensions as i32),
|
|
|
|
column_size: Some(ColumnsSimilarImages::Size as i32),
|
|
|
|
column_size_as_bytes: Some(ColumnsSimilarImages::SizeAsBytes as i32),
|
|
|
|
column_modification_as_secs: Some(ColumnsSimilarImages::ModificationAsSecs as i32),
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::SimilarVideos,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::Date, PopoverTypes::Size],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: Some(ColumnsSimilarVideos::ActivatableSelectButton as i32),
|
|
|
|
column_path: ColumnsSimilarVideos::Path as i32,
|
|
|
|
column_name: ColumnsSimilarVideos::Name as i32,
|
|
|
|
column_selection: ColumnsSimilarVideos::SelectionButton as i32,
|
|
|
|
column_color: Some(ColumnsSimilarVideos::Color as i32),
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: Some(ColumnsSimilarVideos::Size as i32),
|
|
|
|
column_size_as_bytes: Some(ColumnsSimilarVideos::SizeAsBytes as i32),
|
|
|
|
column_modification_as_secs: Some(ColumnsSimilarVideos::ModificationAsSecs as i32),
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::SameMusic,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::Date, PopoverTypes::Size],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: Some(ColumnsSameMusic::ActivatableSelectButton as i32),
|
|
|
|
column_path: ColumnsSameMusic::Path as i32,
|
|
|
|
column_name: ColumnsSameMusic::Name as i32,
|
|
|
|
column_selection: ColumnsSameMusic::SelectionButton as i32,
|
|
|
|
column_color: Some(ColumnsSameMusic::Color as i32),
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: Some(ColumnsSameMusic::SizeAsBytes as i32),
|
|
|
|
column_modification_as_secs: Some(ColumnsSameMusic::ModificationAsSecs as i32),
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::Symlinks,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsInvalidSymlinks::Path as i32,
|
|
|
|
column_name: ColumnsInvalidSymlinks::Name as i32,
|
|
|
|
column_selection: ColumnsInvalidSymlinks::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
NotebookObject {
|
|
|
|
notebook_type: NotebookMainEnum::BrokenFiles,
|
2021-12-06 09:01:16 +13:00
|
|
|
available_modes: [PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::None, PopoverTypes::None],
|
2021-11-25 20:36:49 +13:00
|
|
|
column_activatable_button: None,
|
|
|
|
column_path: ColumnsBrokenFiles::Path as i32,
|
|
|
|
column_name: ColumnsBrokenFiles::Name as i32,
|
|
|
|
column_selection: ColumnsBrokenFiles::SelectionButton as i32,
|
|
|
|
column_color: None,
|
|
|
|
column_dimensions: None,
|
|
|
|
column_size: None,
|
|
|
|
column_size_as_bytes: None,
|
|
|
|
column_modification_as_secs: None,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2020-11-01 02:23:31 +13:00
|
|
|
pub enum Message {
|
|
|
|
Duplicates(DuplicateFinder),
|
|
|
|
EmptyFolders(EmptyFolder),
|
|
|
|
EmptyFiles(EmptyFiles),
|
|
|
|
BigFiles(BigFile),
|
|
|
|
Temporary(Temporary),
|
|
|
|
SimilarImages(SimilarImages),
|
2021-11-23 23:10:24 +13:00
|
|
|
SimilarVideos(SimilarVideos),
|
2020-11-03 09:56:07 +13:00
|
|
|
SameMusic(SameMusic),
|
2020-12-22 04:09:39 +13:00
|
|
|
InvalidSymlinks(InvalidSymlinks),
|
2021-01-13 08:06:12 +13:00
|
|
|
BrokenFiles(BrokenFiles),
|
2020-11-01 02:23:31 +13:00
|
|
|
}
|
2020-09-30 05:44:20 +13:00
|
|
|
|
2020-10-01 19:53:17 +13:00
|
|
|
pub enum ColumnsDuplicates {
|
2020-10-02 02:55:45 +13:00
|
|
|
// Columns for duplicate treeview
|
2021-11-20 21:43:24 +13:00
|
|
|
ActivatableSelectButton = 0,
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton,
|
2021-12-24 21:18:55 +13:00
|
|
|
Size,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2020-10-01 19:53:17 +13:00
|
|
|
Path,
|
|
|
|
Modification,
|
|
|
|
ModificationAsSecs,
|
|
|
|
Color,
|
2020-10-02 02:25:58 +13:00
|
|
|
TextColor,
|
2020-10-01 19:53:17 +13:00
|
|
|
}
|
2020-10-02 02:25:58 +13:00
|
|
|
|
2020-10-02 06:26:25 +13:00
|
|
|
pub enum ColumnsEmptyFolders {
|
2020-10-02 02:55:45 +13:00
|
|
|
// Columns for empty folder treeview
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2020-09-30 05:44:20 +13:00
|
|
|
Path,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
ModificationAsSecs,
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
pub enum ColumnsIncludedDirectory {
|
|
|
|
// Columns for Included Directories in upper Notebook
|
|
|
|
Path = 0,
|
|
|
|
ReferenceButton,
|
|
|
|
}
|
|
|
|
pub enum ColumnsExcludedDirectory {
|
|
|
|
// Columns for Excluded Directories in upper Notebook
|
2020-09-30 05:44:20 +13:00
|
|
|
Path = 0,
|
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-10-02 06:26:25 +13:00
|
|
|
pub enum ColumnsBigFiles {
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Size,
|
2020-10-02 06:26:25 +13:00
|
|
|
Name,
|
|
|
|
Path,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
SizeAsBytes,
|
|
|
|
ModificationAsSecs,
|
2020-10-02 06:26:25 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-10-02 06:26:25 +13:00
|
|
|
pub enum ColumnsEmptyFiles {
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2020-10-02 06:26:25 +13:00
|
|
|
Path,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
ModificationAsSecs,
|
2020-10-02 06:26:25 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-10-02 06:26:25 +13:00
|
|
|
pub enum ColumnsTemporaryFiles {
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2020-10-02 06:26:25 +13:00
|
|
|
Path,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
ModificationAsSecs,
|
2020-10-02 06:26:25 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-10-15 20:04:02 +13:00
|
|
|
pub enum ColumnsSimilarImages {
|
2021-11-20 21:43:24 +13:00
|
|
|
ActivatableSelectButton = 0,
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton,
|
2021-07-16 16:51:54 +12:00
|
|
|
Similarity,
|
2020-10-16 04:51:47 +13:00
|
|
|
Size,
|
2020-12-26 22:35:43 +13:00
|
|
|
SizeAsBytes,
|
2020-10-16 04:51:47 +13:00
|
|
|
Dimensions,
|
2020-10-15 20:04:02 +13:00
|
|
|
Name,
|
|
|
|
Path,
|
|
|
|
Modification,
|
2020-11-09 22:09:22 +13:00
|
|
|
ModificationAsSecs,
|
2020-10-16 04:51:47 +13:00
|
|
|
Color,
|
|
|
|
TextColor,
|
2020-10-15 20:04:02 +13:00
|
|
|
}
|
2021-11-23 23:10:24 +13:00
|
|
|
|
|
|
|
pub enum ColumnsSimilarVideos {
|
|
|
|
ActivatableSelectButton = 0,
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton,
|
2021-11-23 23:10:24 +13:00
|
|
|
Size,
|
|
|
|
SizeAsBytes,
|
|
|
|
Name,
|
|
|
|
Path,
|
|
|
|
Modification,
|
|
|
|
ModificationAsSecs,
|
|
|
|
Color,
|
|
|
|
TextColor,
|
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-11-03 09:56:07 +13:00
|
|
|
pub enum ColumnsSameMusic {
|
2021-11-20 21:43:24 +13:00
|
|
|
ActivatableSelectButton = 0,
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton,
|
2021-07-16 16:51:54 +12:00
|
|
|
Size,
|
2020-12-26 22:35:43 +13:00
|
|
|
SizeAsBytes,
|
2020-11-03 09:56:07 +13:00
|
|
|
Name,
|
|
|
|
Path,
|
|
|
|
Title,
|
|
|
|
Artist,
|
|
|
|
AlbumTitle,
|
|
|
|
AlbumArtist,
|
|
|
|
Year,
|
|
|
|
Modification,
|
2020-11-09 22:09:22 +13:00
|
|
|
ModificationAsSecs,
|
2020-11-03 09:56:07 +13:00
|
|
|
Color,
|
|
|
|
TextColor,
|
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2020-12-22 04:09:39 +13:00
|
|
|
pub enum ColumnsInvalidSymlinks {
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2020-12-22 09:19:59 +13:00
|
|
|
Path,
|
2020-12-22 04:09:39 +13:00
|
|
|
DestinationPath,
|
|
|
|
TypeOfError,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
ModificationAsSecs,
|
2020-12-22 04:09:39 +13:00
|
|
|
}
|
2020-09-30 05:44:20 +13:00
|
|
|
|
2021-01-13 08:06:12 +13:00
|
|
|
pub enum ColumnsBrokenFiles {
|
2021-11-25 20:36:49 +13:00
|
|
|
SelectionButton = 0,
|
2021-07-16 16:51:54 +12:00
|
|
|
Name,
|
2021-01-13 08:06:12 +13:00
|
|
|
Path,
|
|
|
|
ErrorType,
|
|
|
|
Modification,
|
2021-12-05 08:41:02 +13:00
|
|
|
ModificationAsSecs,
|
2021-01-13 08:06:12 +13:00
|
|
|
}
|
|
|
|
|
2020-10-02 02:25:58 +13:00
|
|
|
pub const TEXT_COLOR: &str = "#ffffff";
|
2020-09-30 05:44:20 +13:00
|
|
|
pub const MAIN_ROW_COLOR: &str = "#343434";
|
|
|
|
pub const HEADER_ROW_COLOR: &str = "#272727";
|
|
|
|
//pub const MAIN_ROW_COLOR: &str = "#f4f434"; // TEST
|
|
|
|
//pub const HEADER_ROW_COLOR: &str = "#010101"; // TEST
|
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
pub fn get_string_from_list_store(tree_view: >k::TreeView, column_full_path: i32, column_selection: Option<i32>) -> Vec<String> {
|
2021-07-30 17:16:35 +12:00
|
|
|
let list_store: gtk::ListStore = get_list_store(tree_view);
|
2020-09-30 05:44:20 +13:00
|
|
|
|
2021-01-11 08:44:10 +13:00
|
|
|
let mut string_vector: Vec<String> = Vec::new();
|
|
|
|
|
2021-06-26 04:07:13 +12:00
|
|
|
let tree_iter = match list_store.iter_first() {
|
2020-09-30 05:44:20 +13:00
|
|
|
Some(t) => t,
|
2021-01-11 08:44:10 +13:00
|
|
|
None => {
|
|
|
|
return string_vector;
|
|
|
|
}
|
2020-09-30 05:44:20 +13:00
|
|
|
};
|
2021-12-24 21:18:55 +13:00
|
|
|
match column_selection {
|
|
|
|
Some(column_selection) => loop {
|
|
|
|
if list_store.value(&tree_iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
string_vector.push(list_store.value(&tree_iter, column_full_path).get::<String>().unwrap());
|
|
|
|
}
|
|
|
|
if !list_store.iter_next(&tree_iter) {
|
|
|
|
return string_vector;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
None => loop {
|
|
|
|
string_vector.push(list_store.value(&tree_iter, column_full_path).get::<String>().unwrap());
|
|
|
|
if !list_store.iter_next(&tree_iter) {
|
|
|
|
return string_vector;
|
|
|
|
}
|
|
|
|
},
|
2020-09-30 07:19:36 +13:00
|
|
|
}
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2021-01-11 08:44:10 +13:00
|
|
|
pub fn get_path_buf_from_vector_of_strings(vec_string: Vec<String>) -> Vec<PathBuf> {
|
|
|
|
vec_string.iter().map(PathBuf::from).collect()
|
|
|
|
}
|
|
|
|
|
2020-11-01 02:23:31 +13:00
|
|
|
pub fn split_path(path: &Path) -> (String, String) {
|
|
|
|
match (path.parent(), path.file_name()) {
|
|
|
|
(Some(dir), Some(file)) => (dir.display().to_string(), file.to_string_lossy().into_owned()),
|
|
|
|
(Some(dir), None) => (dir.display().to_string(), String::new()),
|
|
|
|
(None, _) => (String::new(), String::new()),
|
|
|
|
}
|
|
|
|
}
|
2020-10-02 06:26:25 +13:00
|
|
|
|
2020-09-30 05:44:20 +13:00
|
|
|
pub fn print_text_messages_to_text_view(text_messages: &Messages, text_view: >k::TextView) {
|
|
|
|
let mut messages: String = String::from("");
|
|
|
|
if !text_messages.messages.is_empty() {
|
2021-12-13 00:02:53 +13:00
|
|
|
messages += format!("############### {}({}) ###############\n", fl!("text_view_messages"), text_messages.messages.len()).as_str();
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
|
|
|
for text in &text_messages.messages {
|
|
|
|
messages += text.as_str();
|
|
|
|
messages += "\n";
|
|
|
|
}
|
2021-12-06 09:01:16 +13:00
|
|
|
// if !text_messages.messages.is_empty() {
|
|
|
|
// messages += "\n";
|
|
|
|
// }
|
2020-09-30 05:44:20 +13:00
|
|
|
if !text_messages.warnings.is_empty() {
|
2021-12-13 00:02:53 +13:00
|
|
|
messages += format!("############### {}({}) ###############\n", fl!("text_view_warnings"), text_messages.warnings.len()).as_str();
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
|
|
|
for text in &text_messages.warnings {
|
|
|
|
messages += text.as_str();
|
|
|
|
messages += "\n";
|
|
|
|
}
|
2021-12-06 09:01:16 +13:00
|
|
|
// if !text_messages.warnings.is_empty() {
|
|
|
|
// messages += "\n";
|
|
|
|
// }
|
2020-09-30 05:44:20 +13:00
|
|
|
if !text_messages.errors.is_empty() {
|
2021-12-13 00:02:53 +13:00
|
|
|
messages += format!("############### {}({}) ###############\n", fl!("text_view_errors"), text_messages.errors.len()).as_str();
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
|
|
|
for text in &text_messages.errors {
|
|
|
|
messages += text.as_str();
|
|
|
|
messages += "\n";
|
|
|
|
}
|
2021-12-06 09:01:16 +13:00
|
|
|
// if !text_messages.errors.is_empty() {
|
|
|
|
// messages += "\n";
|
|
|
|
// }
|
|
|
|
|
|
|
|
if !text_messages.messages.is_empty() || !text_messages.warnings.is_empty() || !text_messages.errors.is_empty() {
|
2020-09-30 05:44:20 +13:00
|
|
|
messages += "\n";
|
|
|
|
}
|
|
|
|
|
2021-06-26 04:07:13 +12:00
|
|
|
text_view.buffer().unwrap().set_text(messages.as_str());
|
2020-09-30 05:44:20 +13:00
|
|
|
}
|
|
|
|
|
2020-12-19 22:03:04 +13:00
|
|
|
pub fn reset_text_view(text_view: &TextView) {
|
2021-06-26 04:07:13 +12:00
|
|
|
text_view.buffer().unwrap().set_text("");
|
2020-12-19 22:03:04 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_text_to_text_view(text_view: &TextView, string_to_append: &str) {
|
2021-06-26 04:07:13 +12:00
|
|
|
let buffer = text_view.buffer().unwrap();
|
|
|
|
let current_text = match buffer.text(&buffer.start_iter(), &buffer.end_iter(), true) {
|
2020-12-19 22:03:04 +13:00
|
|
|
Some(t) => t.to_string(),
|
|
|
|
None => "".to_string(),
|
|
|
|
};
|
2021-12-27 00:08:37 +13:00
|
|
|
if current_text.is_empty() {
|
|
|
|
buffer.set_text(string_to_append);
|
|
|
|
} else {
|
|
|
|
buffer.set_text(format!("{}\n{}", current_text, string_to_append).as_str());
|
|
|
|
}
|
2020-12-19 22:03:04 +13:00
|
|
|
}
|
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
pub fn set_buttons(hashmap: &mut HashMap<String, bool>, buttons_array: &[gtk::Widget], button_names: &[String]) {
|
2020-10-08 09:22:39 +13:00
|
|
|
for (index, button) in buttons_array.iter().enumerate() {
|
2020-11-01 02:23:31 +13:00
|
|
|
if *hashmap.get_mut(button_names[index].as_str()).unwrap() {
|
2021-01-11 00:06:25 +13:00
|
|
|
button.show();
|
2020-10-08 09:22:39 +13:00
|
|
|
} else {
|
|
|
|
button.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
pub fn hide_all_buttons(buttons_array: &[Widget]) {
|
2020-12-02 22:58:31 +13:00
|
|
|
for button in buttons_array {
|
|
|
|
button.hide();
|
2020-10-08 09:22:39 +13:00
|
|
|
}
|
|
|
|
}
|
2020-10-15 20:04:02 +13:00
|
|
|
|
2022-01-02 09:07:20 +13:00
|
|
|
pub fn get_text_from_invalid_symlink_cause(error: &common_dir_traversal::ErrorType) -> String {
|
2020-12-22 04:09:39 +13:00
|
|
|
match error {
|
2022-01-02 09:07:20 +13:00
|
|
|
common_dir_traversal::ErrorType::InfiniteRecursion => fl!("invalid_symlink_infinite_recursion"),
|
|
|
|
common_dir_traversal::ErrorType::NonExistentFile => fl!("invalid_symlink_non_existent_destination"),
|
2020-12-22 04:09:39 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 01:45:05 +13:00
|
|
|
pub fn get_list_store(tree_view: >k::TreeView) -> ListStore {
|
2021-06-26 04:07:13 +12:00
|
|
|
tree_view.model().unwrap().downcast::<gtk::ListStore>().unwrap()
|
2020-11-08 04:26:40 +13:00
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2021-01-08 10:10:11 +13:00
|
|
|
pub fn get_dialog_box_child(dialog: >k::Dialog) -> gtk::Box {
|
2021-11-28 04:44:30 +13:00
|
|
|
dialog.child().unwrap().downcast::<gtk::Box>().unwrap()
|
2021-01-08 10:10:11 +13:00
|
|
|
}
|
2020-12-27 00:53:40 +13:00
|
|
|
|
|
|
|
pub fn change_dimension_to_krotka(dimensions: String) -> (u64, u64) {
|
|
|
|
#[allow(clippy::single_char_pattern)]
|
|
|
|
let vec = dimensions.split::<&str>("x").collect::<Vec<_>>();
|
2021-01-11 00:06:25 +13:00
|
|
|
assert_eq!(vec.len(), 2); // 400x400 - should only have two elements, if have more, then something is not good
|
2020-12-27 00:53:40 +13:00
|
|
|
let number1 = vec[0].parse::<u64>().expect("Invalid data in image dimension in position 0");
|
|
|
|
let number2 = vec[1].parse::<u64>().expect("Invalid data in image dimension in position 1");
|
|
|
|
(number1, number2)
|
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
|
|
|
|
pub fn get_notebook_enum_from_tree_view(tree_view: >k::TreeView) -> NotebookMainEnum {
|
|
|
|
match (*tree_view).widget_name().to_string().as_str() {
|
|
|
|
"tree_view_duplicate_finder" => NotebookMainEnum::Duplicate,
|
|
|
|
"tree_view_empty_folder_finder" => NotebookMainEnum::EmptyDirectories,
|
|
|
|
"tree_view_empty_files_finder" => NotebookMainEnum::EmptyFiles,
|
|
|
|
"tree_view_temporary_files_finder" => NotebookMainEnum::Temporary,
|
|
|
|
"tree_view_big_files_finder" => NotebookMainEnum::BigFiles,
|
|
|
|
"tree_view_similar_images_finder" => NotebookMainEnum::SimilarImages,
|
|
|
|
"tree_view_similar_videos_finder" => NotebookMainEnum::SimilarVideos,
|
|
|
|
"tree_view_same_music_finder" => NotebookMainEnum::SameMusic,
|
|
|
|
"tree_view_invalid_symlinks" => NotebookMainEnum::Symlinks,
|
|
|
|
"tree_view_broken_files" => NotebookMainEnum::BrokenFiles,
|
2021-11-29 23:38:38 +13:00
|
|
|
e => {
|
2021-12-01 23:09:47 +13:00
|
|
|
panic!("{}", e)
|
2021-11-29 23:38:38 +13:00
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
pub fn get_notebook_upper_enum_from_tree_view(tree_view: >k::TreeView) -> NotebookUpperEnum {
|
|
|
|
match (*tree_view).widget_name().to_string().as_str() {
|
|
|
|
"tree_view_upper_included_directories" => NotebookUpperEnum::IncludedDirectories,
|
|
|
|
"tree_view_upper_excluded_directories" => NotebookUpperEnum::ExcludedDirectories,
|
|
|
|
e => {
|
|
|
|
panic!("{}", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
pub fn get_notebook_object_from_tree_view(tree_view: >k::TreeView) -> &NotebookObject {
|
|
|
|
let nb_enum = get_notebook_enum_from_tree_view(tree_view);
|
|
|
|
&NOTEBOOKS_INFOS[nb_enum as usize]
|
|
|
|
}
|
|
|
|
|
2021-12-22 06:23:17 +13:00
|
|
|
pub fn get_full_name_from_path_name(path: &str, name: &str) -> String {
|
|
|
|
let mut string = String::with_capacity(path.len() + name.len() + 1);
|
|
|
|
string.push_str(path);
|
|
|
|
string.push(CHARACTER);
|
|
|
|
string.push_str(name);
|
|
|
|
string
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
// After e.g. deleting files, header may become orphan or have one child, so should be deleted in this case
|
2021-12-24 21:18:55 +13:00
|
|
|
pub fn clean_invalid_headers(model: >k::ListStore, column_color: i32, column_path: i32) {
|
2021-11-25 20:36:49 +13:00
|
|
|
// Remove only child from header
|
|
|
|
if let Some(first_iter) = model.iter_first() {
|
|
|
|
let mut vec_tree_path_to_delete: Vec<gtk::TreePath> = Vec::new();
|
|
|
|
let mut current_iter = first_iter;
|
|
|
|
if model.value(¤t_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
|
|
|
|
panic!("First deleted element, should be a header"); // First element should be header
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut next_iter;
|
|
|
|
let mut next_next_iter;
|
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
// Empty means default check type
|
|
|
|
if model.value(¤t_iter, column_path).get::<String>().unwrap().is_empty() {
|
|
|
|
'main: loop {
|
|
|
|
if model.value(¤t_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
|
|
|
|
panic!("First deleted element, should be a header"); // First element should be header
|
|
|
|
};
|
|
|
|
|
|
|
|
next_iter = current_iter.clone();
|
|
|
|
if !model.iter_next(&next_iter) {
|
|
|
|
// There is only single header left (H1 -> END) -> (NOTHING)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
break 'main;
|
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
if model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
// There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
current_iter = next_iter.clone();
|
|
|
|
continue 'main;
|
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
|
2021-12-24 21:18:55 +13:00
|
|
|
next_next_iter = next_iter.clone();
|
2021-11-25 20:36:49 +13:00
|
|
|
if !model.iter_next(&next_next_iter) {
|
2021-12-24 21:18:55 +13:00
|
|
|
// There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
|
2021-11-25 20:36:49 +13:00
|
|
|
break 'main;
|
|
|
|
}
|
2021-12-24 21:18:55 +13:00
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
2021-12-24 21:18:55 +13:00
|
|
|
// One child between two headers, we can remove them (H1 -> C1 -> H2) -> (H2)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
|
2021-11-25 20:36:49 +13:00
|
|
|
current_iter = next_next_iter.clone();
|
|
|
|
continue 'main;
|
|
|
|
}
|
2021-12-24 21:18:55 +13:00
|
|
|
|
|
|
|
loop {
|
|
|
|
// (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD)
|
|
|
|
if !model.iter_next(&next_next_iter) {
|
|
|
|
break 'main;
|
|
|
|
}
|
|
|
|
// Move to next header
|
|
|
|
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
current_iter = next_next_iter.clone();
|
|
|
|
continue 'main;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for tree_path in vec_tree_path_to_delete.iter().rev() {
|
|
|
|
model.remove(&model.iter(tree_path).unwrap());
|
2021-11-25 20:36:49 +13:00
|
|
|
}
|
|
|
|
}
|
2021-12-24 21:18:55 +13:00
|
|
|
// Non empty means that header points at reference folder
|
|
|
|
else {
|
|
|
|
'reference: loop {
|
|
|
|
if model.value(¤t_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
|
|
|
|
panic!("First deleted element, should be a header"); // First element should be header
|
|
|
|
};
|
|
|
|
|
|
|
|
next_iter = current_iter.clone();
|
|
|
|
if !model.iter_next(&next_iter) {
|
|
|
|
// There is only single header left (H1 -> END) -> (NOTHING)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
break 'reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
// There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2)
|
|
|
|
vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap());
|
|
|
|
current_iter = next_iter.clone();
|
|
|
|
continue 'reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
next_next_iter = next_iter.clone();
|
|
|
|
if !model.iter_next(&next_next_iter) {
|
|
|
|
// There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING)
|
|
|
|
break 'reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
// One child between two headers, we can remove them (H1 -> C1 -> H2) -> (H2)
|
|
|
|
current_iter = next_next_iter.clone();
|
|
|
|
continue 'reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
loop {
|
|
|
|
// (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD)
|
|
|
|
if !model.iter_next(&next_next_iter) {
|
|
|
|
break 'reference;
|
|
|
|
}
|
|
|
|
// Move to next header
|
|
|
|
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
current_iter = next_next_iter.clone();
|
|
|
|
continue 'reference;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for tree_path in vec_tree_path_to_delete.iter().rev() {
|
|
|
|
model.remove(&model.iter(tree_path).unwrap());
|
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Last step, remove orphan header if exists
|
|
|
|
if let Some(iter) = model.iter_first() {
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
model.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-22 06:23:17 +13:00
|
|
|
pub fn check_how_much_elements_is_selected(tree_view: &TreeView, column_color: Option<i32>, column_selection: i32) -> (u64, u64) {
|
|
|
|
let mut number_of_selected_items: u64 = 0;
|
|
|
|
let mut number_of_selected_groups: u64 = 0;
|
|
|
|
|
|
|
|
let model = get_list_store(tree_view);
|
|
|
|
|
|
|
|
let mut is_item_currently_selected_in_group: bool = false;
|
|
|
|
|
|
|
|
// First iter
|
|
|
|
if let Some(iter) = model.iter_first() {
|
|
|
|
if let Some(column_color) = column_color {
|
|
|
|
assert_eq!(model.value(&iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR); // First element should be header
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
|
|
|
is_item_currently_selected_in_group = false;
|
|
|
|
} else {
|
|
|
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
number_of_selected_items += 1;
|
|
|
|
|
|
|
|
if !is_item_currently_selected_in_group {
|
|
|
|
number_of_selected_groups += 1;
|
|
|
|
}
|
|
|
|
is_item_currently_selected_in_group = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop {
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
number_of_selected_items += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(number_of_selected_items, number_of_selected_groups)
|
|
|
|
}
|
2021-12-12 04:16:14 +13:00
|
|
|
|
2021-12-19 04:48:30 +13:00
|
|
|
pub fn get_custom_label_from_button_with_image(button: >k::Bin) -> gtk::Label {
|
2021-12-12 04:16:14 +13:00
|
|
|
let internal_box = button.child().unwrap().downcast::<gtk::Box>().unwrap();
|
|
|
|
for child in internal_box.children() {
|
|
|
|
if let Ok(t) = child.downcast::<gtk::Label>() {
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic!("Button doesn't have proper custom label child");
|
|
|
|
}
|
2021-12-19 04:48:30 +13:00
|
|
|
|
|
|
|
// GTK 4
|
|
|
|
// pub fn get_custom_label_from_button_with_image<P: IsA<gtk4::Widget>>(button: &P) -> gtk4::Label {
|
|
|
|
// let internal_box = button.first_child().unwrap().downcast::<gtk4::Box>().unwrap();
|
|
|
|
// for child in get_all_children(&internal_box) {
|
|
|
|
// if let Ok(t) = child.downcast::<gtk4::Label>() {
|
2021-12-18 07:44:29 +13:00
|
|
|
// return t;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// panic!("Button doesn't have proper custom label child");
|
|
|
|
// }
|
2021-12-19 04:48:30 +13:00
|
|
|
// TODO needs GTK 4.6 to be able to set as child of menu button a box
|
|
|
|
// pub fn get_custom_label_from_menubutton_with_image<P: IsA<gtk4::Widget>>(button: &P) -> gtk4::Label {
|
|
|
|
// println!("{:?}", get_all_children(button));
|
|
|
|
// for c1 in get_all_children(button) {
|
|
|
|
// if let Ok(internal_box) = c1.downcast::<gtk4::Box>() {
|
|
|
|
// for child in get_all_children(&internal_box) {
|
|
|
|
// if let Ok(t) = child.downcast::<gtk4::Label>() {
|
|
|
|
// return t;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// panic!("Menu Button doesn't have proper custom label child");
|
|
|
|
// }
|
2021-12-18 07:44:29 +13:00
|
|
|
|
|
|
|
// GTK 4
|
|
|
|
// pub fn get_all_children<P: IsA<gtk::Widget>>(wid: &P) -> Vec<gtk::Widget> {
|
|
|
|
// let mut vector = vec![];
|
|
|
|
// if let Some(mut child) = wid.first_child() {
|
|
|
|
// vector.push(child.clone());
|
|
|
|
// loop {
|
|
|
|
// child = match child.next_sibling() {
|
|
|
|
// Some(t) => t,
|
|
|
|
// None => break,
|
|
|
|
// };
|
|
|
|
// vector.push(child.clone());
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// return vector;
|
|
|
|
// }
|