[gnome-usage] Add multiselect support in storage.
- From: Petr Štětka <pstetka src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-usage] Add multiselect support in storage.
- Date: Thu, 6 Apr 2017 12:03:28 +0000 (UTC)
commit e5919980f2d0edbf0e5902e125c6cc2ab418a365
Author: Petr Štětka <pstetka redhat com>
Date: Thu Apr 6 14:03:06 2017 +0200
Add multiselect support in storage.
README.md | 6 +-
po/POTFILES.in | 1 +
src/application.vala | 3 +-
src/gnome-usage.vala | 7 +
src/header-bar.vala | 126 ++++++++++++++++++++-
src/meson.build | 1 +
src/storage-actionbar.vala | 276 ++++++++++++++++++++++++++++++++++++++++++++
src/storage-analyzer.vala | 2 +-
src/storage-list-box.vala | 166 ++++++++++++++++++++++++++-
src/storage-row.vala | 140 ++++++++++++++--------
src/storage-view.vala | 25 ++++-
11 files changed, 690 insertions(+), 63 deletions(-)
---
diff --git a/README.md b/README.md
index da0f6d9..1c937d2 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,11 @@ New GNOME Usage!
- [x] Memory usage
- [x] Network usage
- [x] Search in processes
-- [ ] Multiselection in storage
- [ ] UI for file operations errors (as duplicate file, not enough space, permission...)
-- [ ] Notification for file operations and rollback
+- [ ] UI for show progress about file operations
+- [ ] Notification for file operations with undo action
- [ ] Storage support for more users (multiuser system)
-- [ ] Application section in storage
+- [ ] Application in storage
- [ ] Power view (Design?)
- [ ] Disk usage (What library we can use?)
- [ ] Data view - 0%
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 78ff036..25ba2da 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ src/network-sub-view.vala
src/performance-view.vala
src/power-view.vala
src/process-dialog.vala
+src/storage-actionbar.vala
src/storage-analyzer.vala
src/storage-item.vala
src/storage-row.vala
diff --git a/src/application.vala b/src/application.vala
index 672c5a8..3bba4d1 100644
--- a/src/application.vala
+++ b/src/application.vala
@@ -79,7 +79,8 @@ namespace Usage
translator_credits: _("translator-credits"),
website: "https://wiki.gnome.org/Apps/Usage",
website_label: _("Websites"),
- version: Config.VERSION,
+ version: Config.VERSION, //messon
+ //version: Constants.VERSION, //autovala
license_type: License.GPL_3_0);
}
diff --git a/src/gnome-usage.vala b/src/gnome-usage.vala
index 81381ff..373aaf5 100644
--- a/src/gnome-usage.vala
+++ b/src/gnome-usage.vala
@@ -1,10 +1,17 @@
public static int main (string[] args)
{
+ // messon
Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.GNOMELOCALEDIR);
Intl.setlocale(LocaleCategory.ALL, "");
Intl.textdomain(Config.GETTEXT_PACKAGE);
Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "utf-8");
+ //Autovala
+ /*Intl.bindtextdomain(Constants.GETTEXT_PACKAGE, Path.build_filename(Constants.DATADIR,"locale"));
+ Intl.setlocale(LocaleCategory.ALL, "");
+ Intl.textdomain(Constants.GETTEXT_PACKAGE);
+ Intl.bind_textdomain_codeset(Constants.GETTEXT_PACKAGE, "utf-8");*/
+
var application = new Usage.Application();
return application.run(args);
}
diff --git a/src/header-bar.vala b/src/header-bar.vala
index f1b6e71..0402a15 100644
--- a/src/header-bar.vala
+++ b/src/header-bar.vala
@@ -15,11 +15,20 @@ namespace Usage
private bool active_performance_search_btn = false;
private Gtk.Button? storage_back_button;
private Gtk.Button? storage_rescan_button;
+ private Gtk.Button? storage_select_button;
+ private Gtk.Button? storage_cancel_button;
+ private Gtk.MenuButton? storage_selection_menu;
private bool show_storage_back_btn = false;
private bool show_storage_rescan_btn = false;
+ private bool show_storage_select_btn = false;
private string title_text = "";
private HeaderBarMode mode;
+ const GLib.ActionEntry[] select_action_entries = {
+ { "select-all", select_all },
+ { "select-none", select_none },
+ };
+
public HeaderBar(Gtk.Stack stack)
{
mode = HeaderBarMode.PERFORMANCE;
@@ -45,8 +54,13 @@ namespace Usage
case HeaderBarMode.STORAGE:
remove_widget(storage_back_button);
remove_widget(storage_rescan_button);
+ remove_widget(storage_select_button);
+ remove_widget(storage_cancel_button);
storage_rescan_button = null;
storage_back_button = null;
+ storage_select_button = null;
+ storage_select_button = null;
+ storage_cancel_button = null;
break;
case HeaderBarMode.POWER:
break;
@@ -83,15 +97,29 @@ namespace Usage
storage_rescan_button = new Gtk.Button.from_icon_name("view-refresh-symbolic");
storage_rescan_button.clicked.connect(() => {
show_stack_switcher();
+ show_storage_select_button(false);
show_storage_rescan_button(false);
show_storage_back_button(false);
(GLib.Application.get_default() as
Application).get_storage_analyzer().create_cache.begin(true);
((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().reload();
});
+
+ storage_select_button = new Gtk.Button.from_icon_name("emblem-ok-symbolic");
+ storage_select_button.clicked.connect(() => {
+ show_storage_selection_mode(true);
+ });
+ show_storage_select_button(show_storage_select_btn);
show_storage_rescan_button(show_storage_rescan_btn);
+ storage_cancel_button = new Gtk.Button.with_label(_("Cancel"));
+ storage_cancel_button.clicked.connect(() => {
+ show_storage_selection_mode(false);
+ });
+
pack_start(storage_back_button);
+ pack_end(storage_select_button);
pack_end(storage_rescan_button);
+ pack_end(storage_cancel_button);
break;
case HeaderBarMode.POWER:
show_stack_switcher();
@@ -100,10 +128,15 @@ namespace Usage
this.mode = mode;
}
- private void remove_widget(Gtk.Widget? widget)
+ public void change_selected_items(uint count)
{
- if(widget != null)
- remove(widget);
+ if(storage_selection_menu != null)
+ {
+ if(count > 0)
+ storage_selection_menu.label = ngettext ("%u selected", "%u selected", count).printf
(count);
+ else
+ storage_selection_menu.label = _("Click on items to select them");
+ }
}
public HeaderBarMode get_mode()
@@ -159,6 +192,22 @@ namespace Usage
}
}
+ public void show_storage_select_button(bool show)
+ {
+ if(show)
+ {
+ if(storage_select_button != null)
+ storage_select_button.show();
+ show_storage_select_btn = true;
+ }
+ else
+ {
+ if(storage_select_button != null)
+ storage_select_button.hide();
+ show_storage_select_btn = false;
+ }
+ }
+
public void action_on_search()
{
switch(mode)
@@ -172,5 +221,76 @@ namespace Usage
break;
}
}
+
+ public void show_storage_selection_mode(bool show)
+ {
+ if(show)
+ {
+ show_storage_rescan_button(false);
+ show_storage_select_button(false);
+ storage_back_button.hide();
+ storage_cancel_button.show();
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).show_action_bar(true);
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().set_select_mode(true);
+
+ var menu = new GLib.Menu ();
+ var item = new GLib.MenuItem (_("Select all"), "headerbar.select-all");
+ item.set_attribute("accel", "s", "<Primary>a");
+ menu.append_item(item);
+
+ item = new GLib.MenuItem (_("Select None"), "headerbar.select-none");
+ menu.append_item(item);
+
+ storage_selection_menu = new Gtk.MenuButton();
+ storage_selection_menu.get_style_context().add_class("selection-menu");
+ storage_selection_menu.set_menu_model(menu);
+
+ var action_group = new GLib.SimpleActionGroup ();
+ action_group.add_action_entries (select_action_entries, this);
+ storage_selection_menu.get_popover().insert_action_group ("headerbar", action_group);
+
+ storage_selection_menu.show();
+ set_custom_title(storage_selection_menu);
+ change_selected_items(0);
+
+ this.get_style_context().add_class("selection-mode");
+ this.show_close_button = false;
+ }
+ else
+ {
+ if(show_storage_back_btn)
+ storage_back_button.show();
+
+ show_storage_rescan_button(true);
+ show_storage_select_button(true);
+ storage_cancel_button.hide();
+ storage_selection_menu = null;
+ if(title_text == "")
+ show_stack_switcher();
+ else
+ show_title();
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).show_action_bar(false);
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().set_select_mode(false);
+ this.get_style_context().remove_class("selection-mode");
+ this.show_close_button = true;
+ }
+ }
+
+ private void select_all()
+ {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().select_all_rows();
+
+ }
+
+ private void select_none()
+ {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().unselect_all_rows();
+ }
+
+ private void remove_widget(Gtk.Widget? widget)
+ {
+ if(widget != null)
+ remove(widget);
+ }
}
}
\ No newline at end of file
diff --git a/src/meson.build b/src/meson.build
index b1639bf..b09a7f5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -31,6 +31,7 @@ vala_sources = [
'process-row.vala',
'process.vala',
'settings.vala',
+ 'storage-actionbar.vala',
'storage-analyzer.vala',
'storage-graph.vala',
'storage-item.vala',
diff --git a/src/storage-actionbar.vala b/src/storage-actionbar.vala
new file mode 100644
index 0000000..a8594cf
--- /dev/null
+++ b/src/storage-actionbar.vala
@@ -0,0 +1,276 @@
+namespace Usage
+{
+ public class StorageActionBar : Gtk.ActionBar
+ {
+ private Gtk.Button move_to_button;
+ private Gtk.Button delete_button;
+ private Gtk.Button move_to_trash_button;
+ private Gtk.Button empty_folder_button;
+ private Gtk.Button restore_button;
+ private Gtk.Button delete_from_trash_button;
+
+ public StorageActionBar()
+ {
+ //common
+ move_to_button = new Gtk.Button.with_label(_("Move to"));
+ move_to_button.clicked.connect(move_to_clicked);
+ delete_button = new Gtk.Button.with_label(_("Delete"));
+ delete_button.clicked.connect(delete_clicked);
+ delete_button.get_style_context().add_class ("destructive-action");
+ move_to_trash_button = new Gtk.Button.with_label(_("Move to Trash"));
+ move_to_trash_button.clicked.connect(move_to_trash_clicked);
+ this.pack_start(move_to_button);
+ this.pack_end(delete_button);
+ this.pack_end(move_to_trash_button);
+
+ //root
+ empty_folder_button = new Gtk.Button.with_label(_("Empty folder"));
+ empty_folder_button.clicked.connect(empty_folder_clicked);
+ this.pack_end(empty_folder_button);
+
+ //trash
+ restore_button = new Gtk.Button.with_label(_("Restore"));
+ restore_button.clicked.connect(restore_clicked);
+ delete_from_trash_button = new Gtk.Button.with_label(_("Delete from Trash"));
+ delete_from_trash_button.clicked.connect(delete_from_trash_clicked);
+ delete_from_trash_button.get_style_context().add_class ("destructive-action");
+ this.pack_start(restore_button);
+ this.pack_end(delete_from_trash_button);
+
+ hide_all();
+ }
+
+ public void show_common()
+ {
+ hide_all();
+ move_to_button.visible = true;
+ delete_button.visible = true;
+ move_to_trash_button.visible = true;
+ }
+
+ public void show_root()
+ {
+ hide_all();
+ empty_folder_button.visible = true;
+ }
+
+ public void show_trash()
+ {
+ hide_all();
+ restore_button.visible = true;
+ delete_from_trash_button.visible = true;
+ }
+
+ public void hide_all()
+ {
+ move_to_button.set_visible(false);
+ delete_button.set_visible(false);
+ move_to_trash_button.set_visible(false);
+ empty_folder_button.set_visible(false);
+ restore_button.set_visible(false);
+ delete_from_trash_button.set_visible(false);
+ }
+
+ public void set_sensitive_all(bool sensitive)
+ {
+ move_to_button.set_sensitive(sensitive);
+ delete_button.set_sensitive(sensitive);
+ move_to_trash_button.set_sensitive(sensitive);
+ empty_folder_button.set_sensitive(sensitive);
+ restore_button.set_sensitive(sensitive);
+ delete_from_trash_button.set_sensitive(sensitive);
+ }
+
+ private void move_to_clicked()
+ {
+ Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog (
+ _("Select destination folder"), (GLib.Application.get_default() as
Application).get_window(), Gtk.FileChooserAction.SELECT_FOLDER,
+ _("Cancel"),
+ Gtk.ResponseType.CANCEL,
+ _("Select"),
+ Gtk.ResponseType.ACCEPT);
+ chooser.destroy_with_parent = true;
+ Gtk.FileFilter filter = new Gtk.FileFilter();
+ filter.add_custom(Gtk.FileFilterFlags.FILENAME, (filter_info) => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ if(filter_info.filename == storage_row.get_item_path())
+ return false;
+ }
+ return true;
+ });
+ chooser.set_filter(filter);
+ StorageRow storage_row = (StorageRow) ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_row();
+ chooser.set_filename(storage_row.get_item_path());
+ chooser.show();
+
+ if(chooser.run() == Gtk.ResponseType.ACCEPT)
+ {
+ Timeout.add(0, () => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow actual_storage_row = (StorageRow) row;
+ string destination = chooser.get_file().get_parse_name() + "/" +
Path.get_basename(actual_storage_row.get_item_path());
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+
storage_analyzer.move_file.begin(File.new_for_path(actual_storage_row.get_item_path()),
File.new_for_path(destination), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+ chooser.destroy();
+ }
+
+ private void delete_clicked()
+ {
+ string files = "";
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ if(files != "")
+ files += ", ";
+ files += storage_row.get_item_name();
+ }
+
+ var dialog = new Gtk.MessageDialog ((GLib.Application.get_default() as
Application).get_window(), Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING, Gtk.ButtonsType.OK_CANCEL, _("Are you sure you want to permanently
delete this items %s?").printf(files));
+ dialog.secondary_text = _("If you delete these items, they will be permanently lost.");
+
+ if(dialog.run() == Gtk.ResponseType.OK)
+ {
+ Timeout.add(0, () => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.delete_file.begin(storage_row.get_item_path(), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+ dialog.destroy();
+
+
+ }
+
+ private void move_to_trash_clicked()
+ {
+ Timeout.add(0, () => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.trash_file.begin(storage_row.get_item_path(), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+
+ private void empty_folder_clicked()
+ {
+ Timeout.add(0, () => {
+ string folders = "";
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ if(storage_row.get_item_type() == StorageItemType.TRASH)
+ {
+ var dialog = new Gtk.MessageDialog ((GLib.Application.get_default() as
Application).get_window(), Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING, Gtk.ButtonsType.OK_CANCEL, _("Empty all items from
Trash?"));
+ dialog.secondary_text = _("All items in the Trash will be permanently deleted.");
+
+ if(dialog.run() == Gtk.ResponseType.OK)
+ {
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.wipe_trash.begin(() => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ dialog.destroy();
+ }
+ else
+ {
+ if(folders != "")
+ folders += ", ";
+ folders += storage_row.get_item_name();
+ }
+ }
+
+ if(folders != "")
+ {
+ var dialog = new Gtk.MessageDialog ((GLib.Application.get_default() as
Application).get_window(), Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING, Gtk.ButtonsType.OK_CANCEL, _("Empty all items from
%s?").printf(folders));
+ dialog.secondary_text = _("All items in the %s will be moved to the
Trash.").printf(folders);
+
+ if(dialog.run() == Gtk.ResponseType.OK)
+ {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.wipe_folder.begin(storage_row.get_item_path(), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+
+ }
+ dialog.destroy();
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+
+ private void restore_clicked()
+ {
+ Timeout.add(0, () => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.restore_trash_file.begin(storage_row.get_item_path(), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+
+ private void delete_from_trash_clicked()
+ {
+ Timeout.add(0, () => {
+ foreach (Gtk.ListBoxRow row in ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().get_selected_rows())
+ {
+ StorageRow storage_row = (StorageRow) row;
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.delete_trash_file.begin(storage_row.get_item_path(), () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+ }
+ hide_selection_mode();
+
+ return false;
+ });
+ }
+
+ private void hide_selection_mode()
+ {
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_selection_mode(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/storage-analyzer.vala b/src/storage-analyzer.vala
index 2cbb58f..e81add7 100644
--- a/src/storage-analyzer.vala
+++ b/src/storage-analyzer.vala
@@ -760,7 +760,7 @@ namespace Usage
GTop.get_fsusage(out root, mountdir);
Storage storage = Storage();
- storage.free = root.bfree * root.block_size; //TODO bavail or bfree
+ storage.free = root.bfree * root.block_size;
storage.total = root.blocks * root.block_size;
storage.used = storage.total - storage.free;
storage.name = (string) entries[i].devname;
diff --git a/src/storage-list-box.vala b/src/storage-list-box.vala
index be13daf..a4e42a4 100644
--- a/src/storage-list-box.vala
+++ b/src/storage-list-box.vala
@@ -26,6 +26,7 @@ namespace Usage
bind_model(model, on_row_created);
row_activated.connect(on_row_activated);
+ selected_rows_changed.connect(on_selected_rows_changed);
path_history = new List<string>();
name_history = new List<string>();
@@ -75,6 +76,10 @@ namespace Usage
{
(GLib.Application.get_default() as
Application).get_window().get_header_bar().set_title_text(actual_name);
(GLib.Application.get_default() as Application).get_window().get_header_bar().show_title();
+ if(actual_parent_type == StorageItemType.TRASHFILE || actual_parent_type ==
StorageItemType.TRASHSUBFILE)
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_select_button(false);
+ else
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_select_button(true);
}
}
@@ -96,6 +101,9 @@ namespace Usage
}
header_bar.show_storage_rescan_button(true);
+ if(actual_parent_type != StorageItemType.TRASHFILE && actual_parent_type !=
StorageItemType.TRASHSUBFILE)
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_select_button(true);
+
loaded();
this.show();
model.remove_all();
@@ -114,6 +122,79 @@ namespace Usage
load(actual_path, actual_parent_type);
}
+ public void set_select_mode(bool select_mode)
+ {
+ if(select_mode)
+ {
+ set_selection_mode (Gtk.SelectionMode.MULTIPLE);
+ this.forall ((child) => {
+ var row = child as StorageRow;
+ if (row == null)
+ return;
+
+ row.set_show_check_button(true);
+ });
+
+ if(root)
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_action_bar().show_root();
+ else if(actual_parent_type == StorageItemType.TRASH)
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_action_bar().show_trash();
+ else if(actual_parent_type != StorageItemType.TRASHFILE && actual_parent_type !=
StorageItemType.TRASHSUBFILE)
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_action_bar().show_common();
+
+ on_selected_rows_changed();
+ }
+ else
+ {
+ set_selection_mode (Gtk.SelectionMode.NONE);
+ this.forall ((child) => {
+ var row = child as StorageRow;
+ if (row == null)
+ return;
+
+ row.set_show_check_button(false);
+ });
+ }
+ }
+
+ public bool get_select_mode()
+ {
+ if(get_selection_mode() == Gtk.SelectionMode.MULTIPLE)
+ return true;
+ else
+ return false;
+ }
+
+ public void select_all_rows()
+ {
+ if(get_select_mode())
+ {
+ this.forall ((child) => {
+ var row = child as StorageRow;
+ if (row == null)
+ return;
+
+ row.set_selected(true);
+ select_row((Gtk.ListBoxRow) row);
+ });
+ }
+ }
+
+ public void unselect_all_rows()
+ {
+ if(get_select_mode())
+ {
+ this.forall ((child) => {
+ var row = child as StorageRow;
+ if (row == null)
+ return;
+
+ row.set_selected(false);
+ unselect_row((Gtk.ListBoxRow) row);
+ });
+ }
+ }
+
private void load(string? path, StorageItemType? parent)
{
if(path == null)
@@ -140,10 +221,28 @@ namespace Usage
empty();
});
}
-
private void on_row_activated (Gtk.ListBoxRow row)
{
StorageRow storage_row = (StorageRow) row;
+ if(get_select_mode())
+ {
+ if(storage_row.get_selected())
+ {
+ storage_row.set_selected(false);
+ unselect_row(row);
+ }
+ else
+ {
+ storage_row.set_selected(true);
+ select_row(row);
+ }
+ }
+ else
+ action_primary(storage_row);
+ }
+
+ private void action_primary (StorageRow storage_row)
+ {
if(storage_row.get_item_type() != StorageItemType.STORAGE && storage_row.get_item_type() !=
StorageItemType.SYSTEM &&
storage_row.get_item_type() != StorageItemType.AVAILABLE && storage_row.get_item_type() !=
StorageItemType.FILE)
{
@@ -157,15 +256,78 @@ namespace Usage
(GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_back_button(true);
(GLib.Application.get_default() as
Application).get_window().get_header_bar().set_title_text(actual_name);
(GLib.Application.get_default() as Application).get_window().get_header_bar().show_title();
+ if(actual_parent_type == StorageItemType.TRASHFILE || actual_parent_type ==
StorageItemType.TRASHSUBFILE)
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().show_storage_select_button(false);
if(root)
color = storage_row.get_color();
load(actual_path, actual_parent_type);
}
+ else
+ storage_row.action_primary();
+ }
+
+ protected override bool button_release_event (Gdk.EventButton event)
+ {
+ switch (event.button)
+ {
+ case Gdk.BUTTON_PRIMARY:
+
+ // Necessary to avoid treating an event from a child widget which would mess with getting
the correct row.
+ if (event.window != this.get_window ())
+ return false;
+
+ var row = this.get_row_at_y ((int) event.y);
+ if (row == null)
+ return false;
+
+ StorageRow storage_row = (StorageRow) row;
+
+ if(get_select_mode())
+ {
+ if(storage_row.get_selected())
+ {
+ storage_row.set_selected(false);
+ unselect_row(row);
+ }
+ else
+ {
+ storage_row.set_selected(true);
+ select_row(row);
+ }
+ }
+ else
+ action_primary(storage_row);
+
+ return true;
+ case Gdk.BUTTON_SECONDARY:
+ // Necessary to avoid treating an event from a child widget which would mess with getting
the correct row.
+ if (event.window != this.get_window ())
+ return false;
+
+ var row = this.get_row_at_y ((int) event.y);
+ if (row == null)
+ return false;
+
+ StorageRow storage_row = (StorageRow) row;
+ storage_row.action_secondary();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void on_selected_rows_changed()
+ {
+ (GLib.Application.get_default() as
Application).get_window().get_header_bar().change_selected_items(get_selected_rows().length());
+ if(get_selected_rows().length() > 0)
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_action_bar().set_sensitive_all(true);
+ else
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_action_bar().set_sensitive_all(false);
}
- private Gtk.Widget on_row_created (Object item)
+ private Gtk.Widget on_row_created(Object item)
{
unowned StorageItem storage_item = (StorageItem) item;
var row = new StorageRow(storage_item);
diff --git a/src/storage-row.vala b/src/storage-row.vala
index 9e97770..112cadd 100644
--- a/src/storage-row.vala
+++ b/src/storage-row.vala
@@ -7,6 +7,7 @@ namespace Usage
private string item_path;
private string item_name;
private Gdk.RGBA color;
+ private Gtk.CheckButton? check_button;
const GLib.ActionEntry[] action_entries = {
{ "rename", action_rename },
@@ -33,27 +34,28 @@ namespace Usage
var title_label = new Gtk.Label(storage_item.get_name());
title_label.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
+ Gtk.Widget? icon = null;
switch(storage_item.get_item_type())
{
case StorageItemType.SYSTEM:
- var color_rectangle = new ColorRectangle.new_from_css("system");
- color = color_rectangle.get_color();
- box.pack_start(color_rectangle, false, false, 5);
+ icon = new ColorRectangle.new_from_css("system");
+ color = ((ColorRectangle) icon).get_color();
+ selectable = false;
break;
case StorageItemType.TRASH:
- var color_rectangle = new ColorRectangle.new_from_css("trash");
- color = color_rectangle.get_color();
- box.pack_start(color_rectangle, false, false, 5);
+ check_button = new Gtk.CheckButton();
+ icon = new ColorRectangle.new_from_css("trash");
+ color = ((ColorRectangle) icon).get_color();
break;
case StorageItemType.USER:
- var color_rectangle = new ColorRectangle.new_from_css("user");
- color = color_rectangle.get_color();
- box.pack_start(color_rectangle, false, false, 5);
+ check_button = new Gtk.CheckButton();
+ icon = new ColorRectangle.new_from_css("user");
+ color = ((ColorRectangle) icon).get_color();
break;
case StorageItemType.AVAILABLE:
- var color_rectangle = new ColorRectangle.new_from_css("available-storage");
- color = color_rectangle.get_color();
- box.pack_start(color_rectangle, false, false, 5);
+ icon = new ColorRectangle.new_from_css("available-storage");
+ color = ((ColorRectangle) icon).get_color();
+ selectable = false;
break;
case StorageItemType.STORAGE:
title_label.set_markup ("<b>" + storage_item.get_name() + "</b>");
@@ -67,33 +69,33 @@ namespace Usage
case StorageItemType.MUSIC:
case StorageItemType.PICTURES:
case StorageItemType.VIDEOS:
+ check_button = new Gtk.CheckButton();
get_style_context().add_class("folders");
color = get_style_context().get_color(get_style_context().get_state());
get_style_context().remove_class("folders");
- var color_rectangle = new ColorRectangle.new_from_rgba(storage_item.get_color());
- box.pack_start(color_rectangle, false, false, 5);
+ icon = new ColorRectangle.new_from_rgba(storage_item.get_color());
break;
case StorageItemType.DIRECTORY:
+ check_button = new Gtk.CheckButton();
color = storage_item.get_color();
var info = Gtk.IconTheme.get_default().lookup_icon("folder-symbolic", 15, 0);
try {
var pixbuf = info.load_symbolic (storage_item.get_color());
- var icon = new Gtk.Image.from_pixbuf (pixbuf);
- box.pack_start(icon, false, false, 5);
+ icon = new Gtk.Image.from_pixbuf (pixbuf);
}
catch(Error e) {
GLib.stderr.printf ("Could not load folder-symbolic icon: %s\n", e.message);
}
break;
case StorageItemType.FILE:
+ check_button = new Gtk.CheckButton();
color = storage_item.get_color();
var info = Gtk.IconTheme.get_default().lookup_icon("folder-documents-symbolic", 15, 0);
try {
var pixbuf = info.load_symbolic (storage_item.get_color());
- var icon = new Gtk.Image.from_pixbuf (pixbuf);
- box.pack_start(icon, false, false, 5);
+ icon = new Gtk.Image.from_pixbuf (pixbuf);
}
catch(Error e) {
GLib.stderr.printf ("Could not load folder-documents-symbolic icon: %s\n",
e.message);
@@ -101,14 +103,58 @@ namespace Usage
break;
}
+ if(check_button != null)
+ {
+ check_button.toggled.connect(() => {
+ if(check_button.get_active())
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().select_row(this);
+ else
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().unselect_row(this);
+ });
+ box.pack_start(check_button, false, false, 5);
+ }
+
+ if(icon != null)
+ box.pack_start(icon, false, false, 5);
+
box.pack_start(title_label, false, true, 5);
box.pack_end(size_label, false, true, 10);
- var event_box = new Gtk.EventBox();
- event_box.add(box);
- event_box.button_press_event.connect(row_press_event);
- add(event_box);
+ add(box);
show_all();
+ set_show_check_button(false);
+ }
+
+ public void set_show_check_button(bool show)
+ {
+ if(check_button != null)
+ {
+ check_button.set_visible(show);
+ if(show == false)
+ check_button.set_active(false);
+ }
+ }
+
+ public bool get_show_check_button()
+ {
+ if(check_button != null)
+ return check_button.get_visible();
+ else
+ return false;
+ }
+
+ public void set_selected(bool selected)
+ {
+ if(check_button != null)
+ check_button.set_active(selected);
+ }
+
+ public bool get_selected()
+ {
+ if(check_button == null)
+ return false;
+ else
+ return check_button.get_active();
}
public Gdk.RGBA get_color()
@@ -136,25 +182,7 @@ namespace Usage
return parent_type;
}
- private bool row_press_event (Gdk.EventButton event)
- {
- if(event.type == Gdk.EventType.BUTTON_PRESS)
- {
- switch (event.button)
- {
- case Gdk.BUTTON_PRIMARY:
- action_primary();
- return false;
- case Gdk.BUTTON_SECONDARY:
- action_secondary();
- return true;
- }
- }
-
- return true;
- }
-
- private void action_primary()
+ public void action_primary()
{
if(type == StorageItemType.FILE)
{
@@ -172,7 +200,7 @@ namespace Usage
}
}
- private void action_secondary()
+ public void action_secondary()
{
bool show_popover = false;
@@ -285,7 +313,7 @@ namespace Usage
return false;
});
}
- dialog.close();
+ dialog.destroy();
}
private void action_wipe_trash()
@@ -305,7 +333,7 @@ namespace Usage
return false;
});
}
- dialog.close();
+ dialog.destroy();
}
private void action_rename()
@@ -370,7 +398,7 @@ namespace Usage
return false;
});
}
- chooser.close ();
+ chooser.destroy ();
}
private void action_move_to_trash()
@@ -387,14 +415,22 @@ namespace Usage
private void action_delete()
{
- Timeout.add(0, () => {
- var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
- storage_analyzer.delete_file.begin(item_path, () => {
- ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
- });
+ var dialog = new Gtk.MessageDialog ((GLib.Application.get_default() as
Application).get_window(), Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING, Gtk.ButtonsType.OK_CANCEL, _("Are you sure you want to permanently
delete %s?").printf(item_name));
+ dialog.secondary_text = _("If you delete an item, it will be permanently lost.");
- return false;
- });
+ if(dialog.run() == Gtk.ResponseType.OK)
+ {
+ Timeout.add(0, () => {
+ var storage_analyzer = (GLib.Application.get_default() as
Application).get_storage_analyzer();
+ storage_analyzer.delete_file.begin(item_path, () => {
+ ((StorageView) (GLib.Application.get_default() as
Application).get_window().get_views()[2]).get_storage_list_box().refresh();
+ });
+
+ return false;
+ });
+ }
+ dialog.destroy();
}
}
}
diff --git a/src/storage-view.vala b/src/storage-view.vala
index 4e984c5..e13d15d 100644
--- a/src/storage-view.vala
+++ b/src/storage-view.vala
@@ -3,6 +3,8 @@ namespace Usage
public class StorageView : View
{
private StorageListBox storage_list_box;
+ private Gtk.Revealer revealer;
+ private StorageActionBar action_bar;
public StorageView ()
{
@@ -64,12 +66,33 @@ namespace Usage
empty_label.show();
});
- add(paned);
+ action_bar = new StorageActionBar();
+
+ revealer = new Gtk.Revealer();
+ revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_UP;
+ revealer.transition_duration = 400;
+ revealer.add(action_bar);
+
+ var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
+ box.pack_start(paned, true);
+ box.pack_end(revealer, false);
+ add(box);
}
public StorageListBox get_storage_list_box()
{
return storage_list_box;
}
+
+ public StorageActionBar get_action_bar()
+ {
+ return action_bar;
+ }
+
+ public void show_action_bar(bool show)
+ {
+ revealer.set_reveal_child(show);
+ action_bar.hide_all();
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]