2016-06-20 05:43:07 +02:00
|
|
|
/* Copyright 2016 Software Freedom Conservancy Inc.
|
|
|
|
|
*
|
|
|
|
|
* This software is licensed under the GNU Lesser General Public License
|
|
|
|
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
[GtkTemplate (ui = "/org/gnome/Geary/folder-popover.ui")]
|
|
|
|
|
public class FolderPopover : Gtk.Popover {
|
|
|
|
|
|
2021-02-07 10:18:46 +11:00
|
|
|
[GtkChild] private unowned Gtk.SearchEntry search_entry;
|
|
|
|
|
[GtkChild] private unowned Gtk.ListBox list_box;
|
2022-12-09 16:05:35 +01:00
|
|
|
[GtkChild] private unowned Gtk.Switch move_switch;
|
|
|
|
|
|
|
|
|
|
public Geary.Account account {get; set;}
|
2016-06-20 05:43:07 +02:00
|
|
|
|
|
|
|
|
private int filtered_folder_count = 0;
|
|
|
|
|
|
2022-12-09 16:05:35 +01:00
|
|
|
public signal void copy_conversation(Geary.Folder folder);
|
|
|
|
|
public signal void move_conversation(Geary.Folder folder);
|
2016-06-20 05:43:07 +02:00
|
|
|
|
2022-12-09 16:05:35 +01:00
|
|
|
public FolderPopover(Application.Configuration config) {
|
2016-06-20 05:43:07 +02:00
|
|
|
list_box.set_filter_func(row_filter);
|
|
|
|
|
list_box.set_sort_func(row_sort);
|
|
|
|
|
this.show.connect(() => search_entry.grab_focus());
|
|
|
|
|
this.hide.connect(() => {
|
|
|
|
|
search_entry.set_text("");
|
|
|
|
|
invalidate_filter();
|
|
|
|
|
});
|
2022-12-09 16:05:35 +01:00
|
|
|
config.bind("move-messages-on-tag", this.move_switch, "active");
|
2016-06-20 05:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-09 16:05:35 +01:00
|
|
|
private void add_folder(Application.FolderContext context, Gee.HashMap<string,string> map) {
|
2022-07-18 13:54:39 +02:00
|
|
|
Geary.Folder folder = context.folder;
|
2016-06-20 05:43:07 +02:00
|
|
|
// don't allow multiples and don't allow folders that can't be opened (that means they
|
|
|
|
|
// support almost no operations and have no content)
|
2022-12-09 16:05:35 +01:00
|
|
|
if (folder.properties.is_openable.is_impossible())
|
2016-06-20 05:43:07 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// also don't allow local-only or virtual folders, which also have a limited set of
|
|
|
|
|
// operations
|
|
|
|
|
if (folder.properties.is_local_only || folder.properties.is_virtual)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-07-18 13:54:39 +02:00
|
|
|
// Moving mails to Drafts folder not supported
|
|
|
|
|
switch (folder.account.information.service_provider) {
|
|
|
|
|
case Geary.ServiceProvider.GMAIL:
|
|
|
|
|
if (folder.used_as == Geary.Folder.SpecialUse.DRAFTS)
|
|
|
|
|
return;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore special directories already having a dedicated button
|
|
|
|
|
switch (folder.used_as) {
|
|
|
|
|
case Geary.Folder.SpecialUse.ARCHIVE:
|
|
|
|
|
case Geary.Folder.SpecialUse.TRASH:
|
|
|
|
|
case Geary.Folder.SpecialUse.JUNK:
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var row = new FolderPopoverRow(context, map);
|
|
|
|
|
row.show();
|
|
|
|
|
list_box.add(row);
|
2016-06-20 05:43:07 +02:00
|
|
|
list_box.invalidate_sort();
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 16:05:35 +01:00
|
|
|
[GtkCallback]
|
|
|
|
|
private void on_map(Gtk.Widget widget) {
|
|
|
|
|
var folders = this.account.list_folders();
|
|
|
|
|
// Build map between path and display name for
|
|
|
|
|
// special directories
|
|
|
|
|
var map = new Gee.HashMap<string,string>();
|
|
|
|
|
foreach (var folder in folders) {
|
|
|
|
|
var context = new Application.FolderContext(folder);
|
|
|
|
|
if (folder.used_as == Geary.Folder.SpecialUse.NONE)
|
|
|
|
|
continue;
|
|
|
|
|
map.set(
|
|
|
|
|
folder.path.to_string().substring(1),
|
|
|
|
|
context.display_name
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
foreach (var folder in folders) {
|
|
|
|
|
var context = new Application.FolderContext(folder);
|
|
|
|
|
this.add_folder(context, map);
|
|
|
|
|
}
|
2016-06-20 05:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-09 16:05:35 +01:00
|
|
|
[GtkCallback]
|
|
|
|
|
private void on_unmap(Gtk.Widget widget) {
|
2016-06-20 05:43:07 +02:00
|
|
|
list_box.foreach((row) => list_box.remove(row));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[GtkCallback]
|
|
|
|
|
private void on_row_activated(Gtk.ListBoxRow? row) {
|
|
|
|
|
if (row != null) {
|
|
|
|
|
Geary.Folder folder = row.get_data<Geary.Folder>("folder");
|
2022-12-09 16:05:35 +01:00
|
|
|
if (this.move_switch.active) {
|
|
|
|
|
move_conversation(folder);
|
|
|
|
|
} else {
|
|
|
|
|
copy_conversation(folder);
|
|
|
|
|
}
|
2016-06-20 05:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[GtkCallback]
|
|
|
|
|
private void on_search_entry_activate() {
|
|
|
|
|
if (filtered_folder_count == 1) {
|
|
|
|
|
// Don't use get_row_at_index(0), or you will get the first row of the unfiltered list.
|
|
|
|
|
Gtk.ListBoxRow? row = list_box.get_row_at_y(0);
|
|
|
|
|
if (row != null)
|
|
|
|
|
on_row_activated(row);
|
|
|
|
|
} else if (filtered_folder_count > 0) {
|
|
|
|
|
list_box.get_row_at_y(0).grab_focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[GtkCallback]
|
|
|
|
|
private void on_search_entry_search_changed() {
|
|
|
|
|
invalidate_filter();
|
2018-07-05 14:29:54 +10:00
|
|
|
if (this.search_entry.get_text() != "") {
|
|
|
|
|
this.list_box.unselect_all();
|
|
|
|
|
}
|
2016-06-20 05:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void invalidate_filter() {
|
|
|
|
|
filtered_folder_count = 0;
|
|
|
|
|
list_box.invalidate_filter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool row_filter(Gtk.ListBoxRow row) {
|
2022-07-18 13:54:39 +02:00
|
|
|
Geary.Folder folder = row.get_data<Geary.Folder>("folder");
|
|
|
|
|
if (folder.path.to_string().down().contains(search_entry.text.down())) {
|
2016-06-20 05:43:07 +02:00
|
|
|
filtered_folder_count++;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int row_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
|
|
|
|
|
Geary.Folder folder1 = row1.get_data<Geary.Folder>("folder");
|
|
|
|
|
Geary.Folder folder2 = row2.get_data<Geary.Folder>("folder");
|
2022-07-18 13:54:39 +02:00
|
|
|
if (folder1.used_as != Geary.Folder.SpecialUse.NONE &&
|
|
|
|
|
folder2.used_as == Geary.Folder.SpecialUse.NONE)
|
|
|
|
|
return -1;
|
|
|
|
|
else if (folder1.used_as == Geary.Folder.SpecialUse.NONE &&
|
|
|
|
|
folder2.used_as != Geary.Folder.SpecialUse.NONE)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return folder1.path.compare_to(folder2.path);
|
2016-06-20 05:43:07 +02:00
|
|
|
}
|
|
|
|
|
}
|