diff --git a/data/io.elementary.mail.gschema.xml b/data/io.elementary.mail.gschema.xml
index d80f94910..0b95b45b4 100644
--- a/data/io.elementary.mail.gschema.xml
+++ b/data/io.elementary.mail.gschema.xml
@@ -7,10 +7,15 @@
Whether the window was maximized on last run
Whether the window was maximized on last run
-
- (1024, 750)
- Most recent window size
- Most recent window size (width, height)
+
+ 750
+ Most recent window height
+ Most recent window height
+
+
+ 1024
+ Most recent window width
+ Most recent window width
190
diff --git a/meson.build b/meson.build
index 76f0c7afd..5b2541235 100644
--- a/meson.build
+++ b/meson.build
@@ -12,33 +12,35 @@ add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi
glib_dep = dependency('glib-2.0')
gobject_dep = dependency('gobject-2.0')
-granite_dep = dependency('granite', version: '>= 6.0.0')
+granite_dep = dependency('granite-7', version: '>= 7.1.0')
+gtk_dep = dependency('gtk4')
gee_dep = dependency('gee-0.8')
-handy_dep = dependency('libhandy-1', version: '>=1.1.90')
+adw_dep = dependency('libadwaita-1', version: '>=1.0.0')
camel_dep = dependency('camel-1.2', version: '>= 3.28')
-libedataserver_dep = dependency('libedataserver-1.2', version: '>= 3.28')
-libedataserverui_dep = dependency('libedataserverui-1.2', version: '>=3.45.1')
-webkit2_dep = dependency('webkit2gtk-4.1')
-webkit2_web_extension_dep = dependency('webkit2gtk-web-extension-4.1')
+libedataserver_dep = dependency('libedataserver-1.2', version: '>=3.45.1')
+libedataserverui_dep = dependency('libedataserverui4-1.0', version: '>= 3.46.4')
+webkit_dep = dependency('webkitgtk-6.0')
+webkit_web_extension_dep = dependency('webkitgtk-web-process-extension-6.0')
libportal_dep = dependency('libportal')
-libportal_gtk_dep = dependency('libportal-gtk3')
+libportal_gtk_dep = dependency('libportal-gtk4')
folks_dep = dependency('folks')
m_dep = meson.get_compiler('c').find_library('m')
-webkit2_extension_path = join_paths(get_option('prefix'), get_option('libdir'), meson.project_name(), 'webkit2')
+webkit_extension_path = join_paths(get_option('prefix'), get_option('libdir'), meson.project_name(), 'webkit2')
dependencies = [
glib_dep,
gobject_dep,
granite_dep,
+ gtk_dep,
gee_dep,
- handy_dep,
+ adw_dep,
camel_dep,
libedataserver_dep,
libedataserverui_dep,
libportal_dep,
libportal_gtk_dep,
- webkit2_dep,
+ webkit_dep,
folks_dep,
m_dep
]
@@ -53,12 +55,11 @@ extension_dependencies = [
glib_dep,
gobject_dep,
gee_dep,
- webkit2_web_extension_dep
+ webkit_web_extension_dep
]
add_global_arguments([
- '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
- '-DHANDY_USE_UNSTABLE_API'
+ '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name())
],
language:'c'
)
diff --git a/po/POTFILES b/po/POTFILES
index 956524c49..674387a6d 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -33,5 +33,3 @@ src/MessageList/FolderPopover/FolderPopover.vala
src/SourceList/CellRendererBadge.vala
src/SourceList/CellRendererExpander.vala
src/SourceList/SourceList.vala
-src/VirtualizingListBox/VirtualizingListBoxRow.vala
-src/VirtualizingListBox/VirtualizingListBox.vala
diff --git a/src/Application.vala b/src/Application.vala
index bf4b2e2dc..655829603 100644
--- a/src/Application.vala
+++ b/src/Application.vala
@@ -98,25 +98,12 @@ public class Mail.Application : Gtk.Application {
protected override void startup () {
base.startup ();
- Hdy.init ();
+ Granite.init ();
+ Adw.init ();
- var granite_settings = Granite.Settings.get_default ();
gtk_settings = Gtk.Settings.get_default ();
gtk_settings.gtk_icon_theme_name = "elementary";
- check_theme ();
- gtk_settings.notify["gtk-theme-name"].connect (check_theme);
-
- gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;
-
- granite_settings.notify["prefers-color-scheme"].connect (() => {
- gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;
- });
-
- var css_provider = new Gtk.CssProvider ();
- css_provider.load_from_resource ("io/elementary/mail/Application.css");
- Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-
var quit_action = new SimpleAction ("quit", null);
quit_action.activate.connect (() => {
foreach (unowned var window in get_windows ()) {
@@ -138,21 +125,25 @@ public class Mail.Application : Gtk.Application {
var account_settings_action = new SimpleAction (ACTION_ACCOUNT_SETTINGS, null);
account_settings_action.activate.connect (() => {
- try {
- Gtk.show_uri_on_window (active_window, "settings://accounts/online", Gtk.get_current_event_time ());
- } catch (Error e) {
- var dialog = new Granite.MessageDialog (
- _("Unable to open System Settings"),
- _("Open System Settings manually or install Evolution to set up online accounts."),
- new ThemedIcon ("preferences-system")
- ) {
- badge_icon = new ThemedIcon ("dialog-warning"),
- modal = true,
- transient_for = active_window,
- };
- dialog.response.connect (dialog.destroy);
- dialog.present ();
- }
+ var uri_launcher = new Gtk.UriLauncher ("settings://accounts/online");
+ uri_launcher.launch.begin (active_window, null, (obj, res) => {
+ try {
+ uri_launcher.launch.end (res);
+ } catch (Error e){
+ var dialog = new Granite.MessageDialog (
+ _("Unable to open System Settings"),
+ _("Open System Settings manually or install Evolution to set up online accounts."),
+ new ThemedIcon ("preferences-system")
+ ) {
+ badge_icon = new ThemedIcon ("dialog-warning"),
+ modal = true,
+ transient_for = active_window,
+ };
+ dialog.show_error_details (e.message);
+ dialog.response.connect (dialog.destroy);
+ dialog.present ();
+ }
+ });
});
var load_images_action = settings.create_action (ACTION_LOAD_IMAGES);
@@ -188,15 +179,19 @@ public class Mail.Application : Gtk.Application {
main_window = new MainWindow (this);
add_window (main_window);
- var rect = Gtk.Allocation ();
- settings.get ("window-size", "(ii)", out rect.width, out rect.height);
- main_window.set_allocation (rect);
+ /*
+ * This is very finicky. Bind size after present else set_titlebar gives us bad sizes
+ * Set maximize after height/width else window is min size on unmaximize
+ * Bind maximize as SET else get get bad sizes
+ */
+ settings.bind ("window-height", main_window, "default-height", SettingsBindFlags.DEFAULT);
+ settings.bind ("window-width", main_window, "default-width", SettingsBindFlags.DEFAULT);
if (settings.get_boolean ("window-maximized")) {
main_window.maximize ();
}
- main_window.show_all ();
+ settings.bind ("window-maximized", main_window, "maximized", SettingsBindFlags.SET);
}
main_window.present ();
@@ -230,12 +225,6 @@ public class Mail.Application : Gtk.Application {
}
}
}
-
- private void check_theme () {
- if (!gtk_settings.gtk_theme_name.has_prefix ("io.elementary")) {
- gtk_settings.gtk_theme_name = "io.elementary.stylesheet.blueberry";
- }
- }
}
public static int main (string[] args) {
diff --git a/src/Composer.vala b/src/Composer.vala
index 01ab6f31c..4d9f0e53b 100644
--- a/src/Composer.vala
+++ b/src/Composer.vala
@@ -5,7 +5,7 @@
* Authored by: David Hewitt
*/
-public class Mail.Composer : Hdy.ApplicationWindow {
+public class Mail.Composer : Adw.ApplicationWindow {
public signal void finished ();
private const string ACTION_GROUP_PREFIX = "win";
@@ -32,7 +32,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
private Gtk.Revealer cc_revealer;
private Gtk.Revealer bcc_revealer;
private Gtk.ToggleButton cc_button;
- private Granite.Widgets.OverlayBar message_url_overlay;
+ private Granite.OverlayBar message_url_overlay;
private Gtk.ComboBoxText from_combo;
private Gtk.Entry subject_val;
@@ -80,12 +80,12 @@ public class Mail.Composer : Hdy.ApplicationWindow {
}
}
- var headerbar = new Hdy.HeaderBar () {
- has_subtitle = false,
- show_close_button = true
+ var headerbar = new Adw.HeaderBar () {
+ // has_subtitle = false,
+ // show_close_button = true
};
- headerbar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
- headerbar.get_style_context ().add_class ("default-decoration");
+ headerbar.add_css_class (Granite.STYLE_CLASS_FLAT);
+ headerbar.add_css_class ("default-decoration");
from_combo = new Gtk.ComboBoxText () {
hexpand = true
@@ -95,13 +95,13 @@ public class Mail.Composer : Hdy.ApplicationWindow {
mnemonic_widget = from_combo,
xalign = 1
};
- from_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ from_label.add_css_class (Granite.CssClass.DIM);
var from_box = new Gtk.Box (HORIZONTAL, 6) {
margin_bottom = 6
};
- from_box.add (from_label);
- from_box.add (from_combo);
+ from_box.append (from_label);
+ from_box.append (from_combo);
var from_revealer = new Gtk.Revealer () {
child = from_box
@@ -115,16 +115,13 @@ public class Mail.Composer : Hdy.ApplicationWindow {
mnemonic_widget = to_val,
xalign = 1
};
- to_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ to_label.add_css_class (Granite.CssClass.DIM);
cc_button = new Gtk.ToggleButton.with_label (_("Cc"));
+ cc_button.insert_after (to_val, to_val.get_last_child ());
var bcc_button = new Gtk.ToggleButton.with_label (_("Bcc"));
-
- var to_grid = new EntryGrid ();
- to_grid.add (to_val);
- to_grid.add (cc_button);
- to_grid.add (bcc_button);
+ bcc_button.insert_after (to_val, cc_button);
cc_val = new Gtk.Entry () {
hexpand = true
@@ -134,16 +131,17 @@ public class Mail.Composer : Hdy.ApplicationWindow {
mnemonic_widget = cc_val,
xalign = 1
};
- cc_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ cc_label.add_css_class (Granite.CssClass.DIM);
var cc_box = new Gtk.Box (HORIZONTAL, 6) {
margin_top = 6
};
- cc_box.add (cc_label);
- cc_box.add (cc_val);
+ cc_box.append (cc_label);
+ cc_box.append (cc_val);
- cc_revealer = new Gtk.Revealer ();
- cc_revealer.add (cc_box);
+ cc_revealer = new Gtk.Revealer () {
+ child = cc_box
+ };
bcc_val = new Gtk.Entry () {
hexpand = true
@@ -153,16 +151,17 @@ public class Mail.Composer : Hdy.ApplicationWindow {
mnemonic_widget = bcc_val,
xalign = 1
};
- bcc_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ bcc_label.add_css_class (Granite.CssClass.DIM);
var bcc_box = new Gtk.Box (HORIZONTAL, 6) {
margin_top = 6
};
- bcc_box.add (bcc_label);
- bcc_box.add (bcc_val);
+ bcc_box.append (bcc_label);
+ bcc_box.append (bcc_val);
- bcc_revealer = new Gtk.Revealer ();
- bcc_revealer.add (bcc_box);
+ bcc_revealer = new Gtk.Revealer () {
+ child = bcc_box
+ };
subject_val = new Gtk.Entry () {
margin_top = 6
@@ -172,7 +171,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
mnemonic_widget = subject_val,
xalign = 1
};
- subject_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ subject_label.add_css_class (Granite.CssClass.DIM);
subject_val.changed.connect (() => {
title = subject_val.text;
@@ -194,13 +193,13 @@ public class Mail.Composer : Hdy.ApplicationWindow {
};
recipient_grid.attach (from_revealer, 0, 0, 2);
recipient_grid.attach (to_label, 0, 1);
- recipient_grid.attach (to_grid, 1, 1);
+ recipient_grid.attach (to_val, 1, 1);
recipient_grid.attach (cc_revealer, 0, 2, 2);
recipient_grid.attach (bcc_revealer, 0, 3, 2);
recipient_grid.attach (subject_label, 0, 4);
recipient_grid.attach (subject_val, 1, 4);
- var image = new Gtk.Button.from_icon_name ("insert-image-symbolic", Gtk.IconSize.MENU) {
+ var image = new Gtk.Button.from_icon_name ("insert-image-symbolic") {
action_name = ACTION_PREFIX + ACTION_INSERT_IMAGE,
tooltip_text = _("Insert Image")
};
@@ -216,16 +215,16 @@ public class Mail.Composer : Hdy.ApplicationWindow {
web_view.mouse_target_changed.connect (on_mouse_target_changed);
var editor_toolbar = new EditorToolbar (web_view);
- editor_toolbar.add (image);
+ editor_toolbar.append (image);
var attachment_box = new Gtk.FlowBox () {
homogeneous = true,
selection_mode = Gtk.SelectionMode.NONE
};
attachment_box.bind_model (attachment_list, (obj) => (Attachment) obj);
- attachment_box.get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW);
+ attachment_box.add_css_class (Granite.STYLE_CLASS_VIEW);
- var discard = new Gtk.Button.from_icon_name ("edit-delete-symbolic", Gtk.IconSize.MENU) {
+ var discard = new Gtk.Button.from_icon_name ("edit-delete-symbolic") {
action_name = ACTION_PREFIX + ACTION_DISCARD,
tooltip_markup = Granite.markup_accel_tooltip (
application.get_accels_for_action (ACTION_PREFIX + ACTION_DISCARD),
@@ -233,7 +232,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
)
};
- var attach = new Gtk.Button.from_icon_name ("mail-attachment-symbolic", Gtk.IconSize.MENU) {
+ var attach = new Gtk.Button.from_icon_name ("mail-attachment-symbolic") {
action_name = ACTION_PREFIX + ACTION_ADD_ATTACHMENT,
tooltip_markup = Granite.markup_accel_tooltip (
application.get_accels_for_action (ACTION_PREFIX + ACTION_ADD_ATTACHMENT),
@@ -244,16 +243,16 @@ public class Mail.Composer : Hdy.ApplicationWindow {
var signature_menu = new Menu ();
var signature_button = new Gtk.MenuButton () {
- image = new Gtk.Image.from_icon_name ("document-edit-symbolic", Gtk.IconSize.MENU),
+ icon_name = "document-edit-symbolic",
menu_model = signature_menu,
- use_popover = false,
+ // use_popover = false,
direction = UP,
tooltip_text = _("Insert Signature…")
};
var send_buttonbox = new Gtk.Box (HORIZONTAL, 0);
- send_buttonbox.add (new Gtk.Image.from_icon_name ("mail-send-symbolic", MENU));
- send_buttonbox.add (new Gtk.Label (_("Send")));
+ send_buttonbox.append (new Gtk.Image.from_icon_name ("mail-send-symbolic"));
+ send_buttonbox.append (new Gtk.Label (_("Send")));
var send = new Gtk.Button () {
action_name = ACTION_PREFIX + ACTION_SEND,
@@ -266,13 +265,13 @@ public class Mail.Composer : Hdy.ApplicationWindow {
application.get_accels_for_action (ACTION_PREFIX + ACTION_SEND)
)
};
- send.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
+ send.add_css_class (Granite.CssClass.SUGGESTED);
var action_bar = new Gtk.ActionBar () {
// Workaround styling issue
margin_top = 1
};
- action_bar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ action_bar.add_css_class (Granite.STYLE_CLASS_FLAT);
action_bar.pack_start (discard);
action_bar.pack_start (attach);
action_bar.pack_start (signature_button);
@@ -282,25 +281,25 @@ public class Mail.Composer : Hdy.ApplicationWindow {
child = web_view
};
- message_url_overlay = new Granite.Widgets.OverlayBar (view_overlay);
- message_url_overlay.no_show_all = true;
+ message_url_overlay = new Granite.OverlayBar (view_overlay) {
+ visible = false
+ };
var main_box = new Gtk.Box (VERTICAL, 0);
- main_box.add (headerbar);
- main_box.add (recipient_grid);
- main_box.add (editor_toolbar);
- main_box.add (new Gtk.Separator (HORIZONTAL));
- main_box.add (view_overlay);
- main_box.add (attachment_box);
- main_box.add (action_bar);
+ main_box.append (headerbar);
+ main_box.append (recipient_grid);
+ main_box.append (editor_toolbar);
+ main_box.append (new Gtk.Separator (HORIZONTAL));
+ main_box.append (view_overlay);
+ main_box.append (attachment_box);
+ main_box.append (action_bar);
default_height = 500;
default_width = 680;
title = _("New Message");
- add (main_box);
- show_all ();
+ content = main_box;
- delete_event.connect (() => {
+ close_request.connect (() => {
save_draft.begin ((obj, res) => {
if (!save_draft.end (res)) {
finished ();
@@ -356,18 +355,6 @@ public class Mail.Composer : Hdy.ApplicationWindow {
has_recipients = to_val.text != "";
});
- to_val.get_style_context ().changed.connect (() => {
- unowned Gtk.StyleContext to_grid_style_context = to_grid.get_style_context ();
- var state = to_grid_style_context.get_state ();
- if (to_val.has_focus) {
- state |= Gtk.StateFlags.FOCUSED;
- } else {
- state ^= Gtk.StateFlags.FOCUSED;
- }
-
- to_grid_style_context.set_state (state);
- });
-
if (to != null) {
to_val.text = to;
}
@@ -419,7 +406,6 @@ public class Mail.Composer : Hdy.ApplicationWindow {
if ("attachment" in result) {
foreach (var path in result["attachment"]) {
var file = path.has_prefix ("file://") ? File.new_for_uri (path) : File.new_for_path (path);
-
attachment_list.append (new Attachment (file, Attachment.DISPOSITION_ATTACHMENT));
}
}
@@ -443,20 +429,24 @@ public class Mail.Composer : Hdy.ApplicationWindow {
private void on_add_attachment () {
var filechooser = new Gtk.FileChooserNative (
_("Choose a file"),
- (Gtk.Window) get_toplevel (),
+ (Gtk.Window) get_root (),
Gtk.FileChooserAction.OPEN,
_("Attach"),
_("Cancel")
);
- if (filechooser.run () == Gtk.ResponseType.ACCEPT) {
+ filechooser.response.connect ((response) => {
filechooser.hide ();
- foreach (unowned File file in filechooser.get_files ()) {
- attachment_list.append (new Attachment (file, Attachment.DISPOSITION_ATTACHMENT));
+ if (response == Gtk.ResponseType.ACCEPT) {
+ var files = filechooser.get_files ();
+ for (int i = 0; files.get_item (i) != null; i++) {
+ attachment_list.append (new Attachment ((File) files.get_item (i), Attachment.DISPOSITION_ATTACHMENT));
+ }
}
- }
+ filechooser.destroy ();
+ });
- filechooser.destroy ();
+ filechooser.show ();
}
private void on_insert_image () {
@@ -466,7 +456,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
var filechooser = new Gtk.FileChooserNative (
_("Choose an image"),
- (Gtk.Window) get_toplevel (),
+ (Gtk.Window) get_root (),
Gtk.FileChooserAction.OPEN,
_("Insert"),
_("Cancel")
@@ -525,8 +515,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
message_url_overlay.hide ();
} else {
message_url_overlay.label = hover_url;
- message_url_overlay.no_show_all = false;
- message_url_overlay.show_all ();
+ message_url_overlay.visible = true;
}
} else {
message_url_overlay.hide ();
@@ -763,7 +752,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
discard_dialog.add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
var discard_anyway = discard_dialog.add_button (_("Delete Draft"), Gtk.ResponseType.ACCEPT);
- discard_anyway.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ discard_anyway.add_css_class (Granite.CssClass.DESTRUCTIVE);
discard_dialog.present ();
discard_dialog.response.connect ((response) => {
@@ -797,7 +786,7 @@ public class Mail.Composer : Hdy.ApplicationWindow {
no_subject_dialog.add_button (_("Don't Send"), Gtk.ResponseType.CANCEL);
var send_anyway = no_subject_dialog.add_button (_("Send Anyway"), Gtk.ResponseType.ACCEPT);
- send_anyway.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ send_anyway.add_css_class (Granite.CssClass.DESTRUCTIVE);
no_subject_dialog.present ();
no_subject_dialog.response.connect ((response) => {
@@ -1027,13 +1016,12 @@ public class Mail.Composer : Hdy.ApplicationWindow {
};
var size_label = new Gtk.Label ("(%s)".printf (GLib.format_size (info.get_size ())));
- size_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ size_label.add_css_class (Granite.CssClass.DIM);
- var remove_button = new Gtk.Button.from_icon_name ("process-stop-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
-
- unowned Gtk.StyleContext remove_button_context = remove_button.get_style_context ();
- remove_button_context.add_class (Gtk.STYLE_CLASS_FLAT);
- remove_button_context.add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ var remove_button = new Gtk.Button.from_icon_name ("process-stop-symbolic") {
+ has_frame = false
+ };
+ remove_button.add_css_class (Granite.CssClass.DESTRUCTIVE);
var box = new Gtk.Box (HORIZONTAL, 3) {
margin_top = 3,
@@ -1041,13 +1029,13 @@ public class Mail.Composer : Hdy.ApplicationWindow {
margin_start = 3,
margin_end = 3
};
- box.add (image);
- box.add (name_label);
- box.add (size_label);
- box.add (remove_button);
+ box.append (image);
+ box.append (name_label);
+ box.append (size_label);
+ box.append (remove_button);
if (disposition == DISPOSITION_INLINE) {
- no_show_all = true;
+ visible = false;
}
margin_top = 3;
@@ -1056,7 +1044,6 @@ public class Mail.Composer : Hdy.ApplicationWindow {
margin_end = 3;
child = box;
- show_all ();
remove_button.clicked.connect (() => {
destroy ();
@@ -1113,12 +1100,6 @@ public class Mail.Composer : Hdy.ApplicationWindow {
}
}
- private class EntryGrid : Gtk.Grid {
- static construct {
- set_css_name (Gtk.STYLE_CLASS_ENTRY);
- }
- }
-
public async bool save_draft () {
if (discard_draft || !web_view.body_html_changed) {
return false;
diff --git a/src/ConversationList/ConversationItemModel.vala b/src/ConversationList/ConversationItemModel.vala
index 406a7dbf7..654dabf49 100644
--- a/src/ConversationList/ConversationItemModel.vala
+++ b/src/ConversationList/ConversationItemModel.vala
@@ -249,6 +249,10 @@ public class Mail.ConversationItemModel : GLib.Object {
return has_flag;
}
+ public static bool equal_func (ConversationItemModel a, ConversationItemModel b) {
+ return (a.service_uid == b.service_uid);
+ }
+
public static int compare_func (Object a, Object b) {
var item1 = (ConversationItemModel) a;
var item2 = (ConversationItemModel) b;
diff --git a/src/ConversationList/ConversationList.vala b/src/ConversationList/ConversationList.vala
index 4e1fba5b0..6b3f74b79 100644
--- a/src/ConversationList/ConversationList.vala
+++ b/src/ConversationList/ConversationList.vala
@@ -20,7 +20,7 @@
* Authored by: Corentin Noël
*/
-public class Mail.ConversationList : Gtk.Box {
+public class Mail.ConversationList : Granite.Bin {
public signal void conversation_selected (Camel.FolderThreadNode? node);
private const int MARK_READ_TIMEOUT_SECONDS = 5;
@@ -28,14 +28,14 @@ public class Mail.ConversationList : Gtk.Box {
public Gee.Map folder_info_per_account { get; private set; }
public Gee.HashMap folders { get; private set; }
public Gee.HashMap folder_info_flags { get; private set; }
- public Hdy.HeaderBar search_header { get; private set; }
+ public Granite.Box search_header { get; private set; }
private GLib.Cancellable? cancellable = null;
private Gee.HashMap threads;
- private Gee.HashMap conversations;
- private ConversationListStore list_store;
- private VirtualizingListBox list_box;
+ private ListStore list_store;
+ private Gtk.ListView list_view;
private Gtk.SearchEntry search_entry;
+ private Gtk.SingleSelection selection_model;
private Granite.SwitchModelButton hide_read_switch;
private Granite.SwitchModelButton hide_unstarred_switch;
private Gtk.MenuButton filter_button;
@@ -44,37 +44,33 @@ public class Mail.ConversationList : Gtk.Box {
private uint mark_read_timeout_id = 0;
construct {
- orientation = VERTICAL;
- get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW);
+ add_css_class (Granite.STYLE_CLASS_VIEW);
- conversations = new Gee.HashMap ();
folders = new Gee.HashMap ();
folder_info_flags = new Gee.HashMap ();
threads = new Gee.HashMap ();
- list_store = new ConversationListStore ();
- list_store.set_filter_func (filter_function);
+ list_store = new ListStore (typeof (ConversationItemModel));
- list_box = new VirtualizingListBox () {
- activate_on_single_click = true,
- model = list_store,
- selection_mode = SINGLE
- };
- list_box.factory_func = (item, old_widget) => {
- ConversationListItem? row = null;
- if (old_widget != null) {
- row = old_widget as ConversationListItem;
- } else {
- row = new ConversationListItem ();
- row.select.connect (() => {
- if (list_box.selected_row_widget != row) {
- list_box.select_row (row);
- }
- });
- }
+ var filter_model = new Gtk.FilterListModel (list_store, new Gtk.CustomFilter (deleted_filter_func));
+
+ selection_model = new Gtk.SingleSelection (filter_model);
+
+ var factory = new Gtk.SignalListItemFactory ();
+ factory.setup.connect ((obj) => {
+ var conversation_list_item = new ConversationListItem ();
- row.bind_model ((ConversationItemModel)item);
- row.show_all ();
- return row;
+ var list_item = (Gtk.ListItem) obj;
+ list_item.child = conversation_list_item;
+ });
+
+ factory.bind.connect ((obj) => {
+ var list_item = (Gtk.ListItem) obj;
+ var conversation_list_item = (ConversationListItem) list_item.child;
+ conversation_list_item.bind_model ((ConversationItemModel) list_item.get_item ());
+ });
+
+ list_view = new Gtk.ListView (selection_model, factory) {
+ vexpand = true
};
var application_instance = (Gtk.Application) GLib.Application.get_default ();
@@ -82,7 +78,7 @@ public class Mail.ConversationList : Gtk.Box {
search_entry = new Gtk.SearchEntry () {
hexpand = true,
placeholder_text = _("Search Mail"),
- valign = Gtk.Align.CENTER
+ valign = CENTER
};
hide_read_switch = new Granite.SwitchModelButton (_("Hide read conversations"));
@@ -92,35 +88,31 @@ public class Mail.ConversationList : Gtk.Box {
margin_bottom = 3,
margin_top = 3
};
- filter_menu_popover_box.add (hide_read_switch);
- filter_menu_popover_box.add (hide_unstarred_switch);
- filter_menu_popover_box.show_all ();
+ filter_menu_popover_box.append (hide_read_switch);
+ filter_menu_popover_box.append (hide_unstarred_switch);
- var filter_popover = new Gtk.Popover (null) {
+ var filter_popover = new Gtk.Popover () {
child = filter_menu_popover_box
};
filter_button = new Gtk.MenuButton () {
- image = new Gtk.Image.from_icon_name ("mail-filter-symbolic", Gtk.IconSize.SMALL_TOOLBAR),
+ icon_name = "mail-filter-symbolic",
popover = filter_popover,
tooltip_text = _("Filter Conversations"),
- valign = Gtk.Align.CENTER
+ valign = CENTER
};
- search_header = new Hdy.HeaderBar () {
- custom_title = search_entry
- };
- search_header.pack_end (filter_button);
- search_header.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ search_header = new Granite.Box (HORIZONTAL);
+ search_header.append (search_entry);
+ search_header.append (filter_button);
- var scrolled_window = new Gtk.ScrolledWindow (null, null) {
+ var scrolled_window = new Gtk.ScrolledWindow () {
hscrollbar_policy = Gtk.PolicyType.NEVER,
width_request = 158,
- expand = true,
- child = list_box
+ child = list_view
};
- var refresh_button = new Gtk.Button.from_icon_name ("view-refresh-symbolic", Gtk.IconSize.SMALL_TOOLBAR) {
+ var refresh_button = new Gtk.Button.from_icon_name ("view-refresh-symbolic") {
action_name = MainWindow.ACTION_PREFIX + MainWindow.ACTION_REFRESH
};
@@ -130,9 +122,9 @@ public class Mail.ConversationList : Gtk.Box {
);
var refresh_spinner = new Gtk.Spinner () {
- active = true,
- halign = Gtk.Align.CENTER,
- valign = Gtk.Align.CENTER,
+ spinning = true,
+ halign = CENTER,
+ valign = CENTER,
tooltip_text = _("Fetching new messages…")
};
@@ -144,33 +136,52 @@ public class Mail.ConversationList : Gtk.Box {
refresh_stack.visible_child = refresh_button;
var move_spinner = new Gtk.Spinner () {
- active = true,
- halign = Gtk.Align.CENTER,
- valign = Gtk.Align.CENTER,
- no_show_all = true
+ spinning = true,
+ halign =CENTER,
+ valign = CENTER,
+ visible = false
};
MoveOperation.bind_spinner (move_spinner);
var conversation_action_bar = new Gtk.ActionBar ();
conversation_action_bar.pack_start (refresh_stack);
conversation_action_bar.pack_end (move_spinner);
- conversation_action_bar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
- add (search_header);
- add (scrolled_window);
- add (conversation_action_bar);
+ var toolbar_view = new Adw.ToolbarView () {
+ content = scrolled_window
+ };
+ toolbar_view.add_top_bar (search_header);
+ toolbar_view.add_bottom_bar (conversation_action_bar);
+
+ child = toolbar_view;
search_entry.search_changed.connect (() => load_folder.begin (folder_info_per_account));
- list_box.row_activated.connect ((row) => {
+ selection_model.selection_changed.connect (() => {
if (mark_read_timeout_id != 0) {
GLib.Source.remove (mark_read_timeout_id);
mark_read_timeout_id = 0;
}
- if (row != null && ((ConversationItemModel) row).unread) {
+ uint pos;
+ var bitset_iter = Gtk.BitsetIter ();
+ bitset_iter.init_first (selection_model.get_selection (), out pos);
+ if (!bitset_iter.is_valid ()) {
+ conversation_selected (null);
+ return;
+ }
+
+ var row = (ConversationItemModel) selection_model.get_item (pos);
+ action_set_enabled (MainWindow.ACTION_PREFIX + MainWindow.ACTION_MARK_READ, row.unread);
+ action_set_enabled (MainWindow.ACTION_PREFIX + MainWindow.ACTION_MARK_UNREAD, !row.unread);
+ action_set_enabled (MainWindow.ACTION_PREFIX + MainWindow.ACTION_MARK_STAR, !row.flagged);
+ action_set_enabled (MainWindow.ACTION_PREFIX + MainWindow.ACTION_MARK_UNSTAR, row.flagged);
+
+ conversation_selected (row.node);
+
+ if (row.unread) {
mark_read_timeout_id = GLib.Timeout.add_seconds (MARK_READ_TIMEOUT_SECONDS, () => {
- set_thread_flag (((ConversationItemModel) row).node, Camel.MessageFlags.SEEN);
+ set_thread_flag (row.node, Camel.MessageFlags.SEEN);
mark_read_timeout_id = 0;
return Source.REMOVE;
@@ -178,22 +189,6 @@ public class Mail.ConversationList : Gtk.Box {
}
});
- list_box.row_selected.connect ((row) => {
- if (row == null) {
- conversation_selected (null);
- } else {
- // We call get_action_group() on the parent window, instead of on `this` directly, due to a
- // bug with Gtk.Widget.get_action_group(). See https://gitlab.gnome.org/GNOME/gtk/issues/1396
- var window = (Gtk.ApplicationWindow) get_toplevel ();
- weak GLib.ActionMap win_action_map = (GLib.ActionMap) window.get_action_group (MainWindow.ACTION_GROUP_PREFIX);
- ((SimpleAction) win_action_map.lookup_action (MainWindow.ACTION_MARK_READ)).set_enabled (((ConversationItemModel) row).unread);
- ((SimpleAction) win_action_map.lookup_action (MainWindow.ACTION_MARK_UNREAD)).set_enabled (!((ConversationItemModel) row).unread);
- ((SimpleAction) win_action_map.lookup_action (MainWindow.ACTION_MARK_STAR)).set_enabled (!((ConversationItemModel) row).flagged);
- ((SimpleAction) win_action_map.lookup_action (MainWindow.ACTION_MARK_UNSTAR)).set_enabled (((ConversationItemModel) row).flagged);
- conversation_selected (((ConversationItemModel) row).node);
- }
- });
-
var settings = new GLib.Settings ("io.elementary.mail");
settings.bind ("hide-read-conversations", hide_read_switch, "active", DEFAULT);
settings.bind ("hide-unstarred-conversations", hide_unstarred_switch, "active", DEFAULT);
@@ -228,66 +223,60 @@ public class Mail.ConversationList : Gtk.Box {
conversation_selected (null);
uint previous_items = list_store.get_n_items ();
- lock (conversations) {
- lock (folders) {
- lock (threads) {
- conversations.clear ();
- folders.clear ();
- threads.clear ();
-
- list_store.remove_all ();
- list_store.items_changed (0, previous_items, 0);
+ lock (folders) {
+ lock (threads) {
+ folders.clear ();
+ threads.clear ();
- cancellable = new GLib.Cancellable ();
+ list_store.remove_all ();
- lock (this.folder_info_per_account) {
- foreach (var folder_info_entry in this.folder_info_per_account) {
- var current_account = folder_info_entry.key;
- var current_folder_info = folder_info_entry.value;
+ cancellable = new GLib.Cancellable ();
- if (current_folder_info == null) {
- continue;
- }
+ lock (this.folder_info_per_account) {
+ foreach (var folder_info_entry in this.folder_info_per_account) {
+ var current_account = folder_info_entry.key;
+ var current_folder_info = folder_info_entry.value;
- try {
- var camel_store = (Camel.Store) current_account.service;
+ if (current_folder_info == null) {
+ continue;
+ }
- var folder = yield camel_store.get_folder (current_folder_info.full_name, 0, GLib.Priority.DEFAULT, cancellable);
- folders[current_account.service.uid] = folder;
+ try {
+ var camel_store = (Camel.Store) current_account.service;
- var info_flags = Utils.get_full_folder_info_flags (current_account.service, current_folder_info);
- folder_info_flags[current_account.service.uid] = info_flags;
+ var folder = yield camel_store.get_folder (current_folder_info.full_name, 0, GLib.Priority.DEFAULT, cancellable);
+ folders[current_account.service.uid] = folder;
- folder.changed.connect ((change_info) => folder_changed (change_info, current_account.service.uid, cancellable));
+ var info_flags = Utils.get_full_folder_info_flags (current_account.service, current_folder_info);
+ folder_info_flags[current_account.service.uid] = info_flags;
- var search_result_uids = get_search_result_uids (current_account.service.uid);
- if (search_result_uids != null) {
- var thread = new Camel.FolderThread (folder, search_result_uids, false);
- threads[current_account.service.uid] = thread;
+ folder.changed.connect ((change_info) => folder_changed (change_info, current_account.service.uid, cancellable));
- weak Camel.FolderThreadNode? child = thread.tree;
- while (child != null) {
- if (cancellable.is_cancelled ()) {
- break;
- }
+ var search_result_uids = get_search_result_uids (current_account.service.uid);
+ if (search_result_uids != null) {
+ var thread = new Camel.FolderThread (folder, search_result_uids, false);
+ threads[current_account.service.uid] = thread;
- add_conversation_item (folder_info_flags[current_account.service.uid], child, thread, current_account.service.uid);
- child = child.next;
+ weak Camel.FolderThreadNode? child = thread.tree;
+ while (child != null) {
+ if (cancellable.is_cancelled ()) {
+ break;
}
+
+ add_conversation_item (folder_info_flags[current_account.service.uid], child, thread, current_account.service.uid);
+ child = child.next;
}
- } catch (Error e) {
- // We can cancel the operation
- if (!(e is GLib.IOError.CANCELLED)) {
- critical (e.message);
- }
+ }
+ } catch (Error e) {
+ // We can cancel the operation
+ if (!(e is GLib.IOError.CANCELLED)) {
+ critical (e.message);
}
}
}
}
}
}
-
- list_store.items_changed (0, 0, list_store.get_n_items ());
}
public async void refresh_folder (GLib.Cancellable? cancellable = null) {
@@ -312,59 +301,66 @@ public class Mail.ConversationList : Gtk.Box {
return;
}
- lock (conversations) {
- lock (threads) {
- var search_result_uids = get_search_result_uids (service_uid);
- if (search_result_uids == null) {
- return;
- }
-
- threads[service_uid] = new Camel.FolderThread (folders[service_uid], search_result_uids, false);
+ lock (threads) {
+ var search_result_uids = get_search_result_uids (service_uid);
+ if (search_result_uids == null) {
+ return;
+ }
- var removed = 0;
- change_info.get_removed_uids ().foreach ((uid) => {
- var item = conversations[uid];
- if (item != null) {
- conversations.unset (uid);
- list_store.remove (item);
- removed++;
- }
- });
+ threads[service_uid] = new Camel.FolderThread (folders[service_uid], search_result_uids, false);
+ unowned Camel.FolderThreadNode? child = threads[service_uid].tree;
+
+ var previous_items = list_store.get_n_items ();
+ change_info.get_removed_uids ().foreach ((uid) => {
+ var temp_item = new ConversationItemModel (folder_info_flags[service_uid], child, threads[service_uid], uid);
+
+ uint pos = -1;
+ if (
+ list_store.find_with_equal_func (
+ temp_item,
+ (EqualFunc)ConversationItemModel.equal_func,
+ out pos
+ )
+ ) {
+ list_store.remove (pos);
+ }
+ });
- unowned Camel.FolderThreadNode? child = threads[service_uid].tree;
- while (child != null) {
- if (cancellable.is_cancelled ()) {
- return;
- }
+ while (child != null) {
+ if (cancellable.is_cancelled ()) {
+ return;
+ }
- var item = conversations[child.message.uid];
- if (item == null) {
+ var temp_item = new ConversationItemModel (folder_info_flags[service_uid], child, threads[service_uid], service_uid);
+ uint pos = -1;
+ if (
+ list_store.find_with_equal_func (
+ temp_item,
+ (EqualFunc)ConversationItemModel.equal_func,
+ out pos
+ )
+ ) {
+ var item = (ConversationItemModel) list_store.get_item (pos);
+ if (item.is_older_than (child)) {
+ list_store.remove (pos);
add_conversation_item (folder_info_flags[service_uid], child, threads[service_uid], service_uid);
- } else {
- if (item.is_older_than (child)) {
- conversations.unset (child.message.uid);
- list_store.remove (item);
- removed++;
- add_conversation_item (folder_info_flags[service_uid], child, threads[service_uid], service_uid);
- };
- }
-
- child = child.next;
+ };
+ } else {
+ add_conversation_item (folder_info_flags[service_uid], child, threads[service_uid], service_uid);
}
- list_store.items_changed (0, removed, list_store.get_n_items ());
+ child = child.next;
}
}
}
private GenericArray? get_search_result_uids (string service_uid) {
- var style_context = filter_button.get_style_context ();
if (hide_read_switch.active || hide_unstarred_switch.active) {
- if (!style_context.has_class (Granite.STYLE_CLASS_ACCENT)) {
- style_context.add_class (Granite.STYLE_CLASS_ACCENT);
+ if (!filter_button.has_css_class (Granite.CssClass.ACCENT)) {
+ filter_button.add_css_class (Granite.CssClass.ACCENT);
}
- } else if (style_context.has_class (Granite.STYLE_CLASS_ACCENT)) {
- style_context.remove_class (Granite.STYLE_CLASS_ACCENT);
+ } else if (filter_button.has_css_class (Granite.CssClass.ACCENT)) {
+ filter_button.remove_css_class (Granite.CssClass.ACCENT);
}
lock (folders) {
@@ -412,11 +408,10 @@ public class Mail.ConversationList : Gtk.Box {
private void add_conversation_item (Camel.FolderInfoFlags folder_info_flags, Camel.FolderThreadNode child, Camel.FolderThread thread, string service_uid) {
var item = new ConversationItemModel (folder_info_flags, child, thread, service_uid);
- conversations[child.message.uid] = item;
list_store.insert_sorted (item, ConversationItemModel.compare_func);
}
- private static bool filter_function (GLib.Object obj) {
+ private static bool deleted_filter_func (GLib.Object obj) {
if (obj is ConversationItemModel) {
var conversation_item = (ConversationItemModel)obj;
return !conversation_item.deleted && !conversation_item.hidden;
@@ -426,30 +421,38 @@ public class Mail.ConversationList : Gtk.Box {
}
public void mark_read_selected_messages () {
- var selected_rows = list_box.get_selected_rows ();
- foreach (var row in selected_rows) {
- (((ConversationItemModel)row).node).message.set_flags (Camel.MessageFlags.SEEN, ~0);
+ uint current_item_position;
+ var bitset_iter = Gtk.BitsetIter ();
+ bitset_iter.init_first (selection_model.get_selection (), out current_item_position);
+ while (bitset_iter.is_valid ()) {
+ ((ConversationItemModel) selection_model.get_item (current_item_position)).node.message.set_flags (Camel.MessageFlags.SEEN, ~0);
}
}
public void mark_star_selected_messages () {
- var selected_rows = list_box.get_selected_rows ();
- foreach (var row in selected_rows) {
- (((ConversationItemModel)row).node).message.set_flags (Camel.MessageFlags.FLAGGED, ~0);
+ uint current_item_position;
+ var bitset_iter = Gtk.BitsetIter ();
+ bitset_iter.init_first (selection_model.get_selection (), out current_item_position);
+ while (bitset_iter.is_valid ()) {
+ ((ConversationItemModel) selection_model.get_item (current_item_position)).node.message.set_flags (Camel.MessageFlags.FLAGGED, ~0);
}
}
public void mark_unread_selected_messages () {
- var selected_rows = list_box.get_selected_rows ();
- foreach (var row in selected_rows) {
- (((ConversationItemModel)row).node).message.set_flags (Camel.MessageFlags.SEEN, 0);
+ uint current_item_position;
+ var bitset_iter = Gtk.BitsetIter ();
+ bitset_iter.init_first (selection_model.get_selection (), out current_item_position);
+ while (bitset_iter.is_valid ()) {
+ ((ConversationItemModel) selection_model.get_item (current_item_position)).node.message.set_flags (Camel.MessageFlags.SEEN, 0);
}
}
public void mark_unstar_selected_messages () {
- var selected_rows = list_box.get_selected_rows ();
- foreach (var row in selected_rows) {
- (((ConversationItemModel)row).node).message.set_flags (Camel.MessageFlags.FLAGGED, 0);
+ uint current_item_position;
+ var bitset_iter = Gtk.BitsetIter ();
+ bitset_iter.init_first (selection_model.get_selection (), out current_item_position);
+ while (bitset_iter.is_valid ()) {
+ ((ConversationItemModel) selection_model.get_item (current_item_position)).node.message.set_flags (Camel.MessageFlags.FLAGGED, 0);
}
}
@@ -458,23 +461,22 @@ public class Mail.ConversationList : Gtk.Box {
ConversationItemModel[] moved_conversation_items = {};
var move_threads = new Gee.HashMap> ();
- var selected_rows = list_box.get_selected_rows ();
- int selected_rows_start_index = list_store.get_index_of (selected_rows.to_array ()[0]);
+ // var selected_rows = list_view.get_selected_rows ();
+ // int selected_rows_start_index = list_store.get_index_of (selected_rows.to_array ()[0]);
- foreach (unowned var selected_row in selected_rows) {
- var selected_item_model = (ConversationItemModel) selected_row;
- selected_item_model.hidden = true;
- moved_conversation_items += selected_item_model;
+ // foreach (unowned var selected_row in selected_rows) {
+ // var selected_item_model = (ConversationItemModel) selected_row;
+ // selected_item_model.hidden = true;
+ // moved_conversation_items += selected_item_model;
- if (move_threads[selected_item_model.service_uid] == null) {
- move_threads[selected_item_model.service_uid] = new Gee.ArrayList ();
- }
+ // if (move_threads[selected_item_model.service_uid] == null) {
+ // move_threads[selected_item_model.service_uid] = new Gee.ArrayList ();
+ // }
- move_threads[selected_item_model.service_uid].add (selected_item_model.node);
- }
+ // move_threads[selected_item_model.service_uid].add (selected_item_model.node);
+ // }
- list_store.items_changed (0, list_store.get_n_items (), list_store.get_n_items ());
- list_box.select_row_at_index (selected_rows_start_index + 1);
+ // selection_model.select_item (selected_rows_start_index + 1, true);
uint moved = 0;
foreach (var service_uid in move_threads.keys) {
@@ -501,7 +503,5 @@ public class Mail.ConversationList : Gtk.Box {
foreach (var item in moved_conversation_items) {
item.hidden = false;
}
-
- list_store.items_changed (0, list_store.get_n_items (), list_store.get_n_items ());
}
}
diff --git a/src/ConversationList/ConversationListItem.vala b/src/ConversationList/ConversationListItem.vala
index 7ab41ac5c..390382c22 100644
--- a/src/ConversationList/ConversationListItem.vala
+++ b/src/ConversationList/ConversationListItem.vala
@@ -5,9 +5,7 @@
* Authored by: Corentin Noël
*/
-public class Mail.ConversationListItem : VirtualizingListBoxRow {
- public signal void select ();
-
+public class Mail.ConversationListItem : Granite.Bin {
private Gtk.Image status_icon;
private Gtk.Label date;
private Gtk.Label messages;
@@ -17,36 +15,34 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
private Gtk.Revealer flagged_icon_revealer;
private Gtk.Revealer status_revealer;
private Gtk.Grid grid;
- private Hdy.Carousel carousel;
- private Gtk.GestureMultiPress gesture_controller;
- private Gtk.EventControllerKey key_controller;
- private Gtk.Menu menu;
+ private Adw.Carousel carousel;
+ private Gtk.PopoverMenu menu;
construct {
- status_icon = new Gtk.Image.from_icon_name ("mail-unread-symbolic", Gtk.IconSize.MENU);
+ status_icon = new Gtk.Image.from_icon_name ("mail-unread-symbolic");
status_revealer = new Gtk.Revealer () {
child = status_icon
};
- var flagged_icon = new Gtk.Image.from_icon_name ("starred-symbolic", Gtk.IconSize.MENU);
+ var flagged_icon = new Gtk.Image.from_icon_name ("starred-symbolic");
flagged_icon_revealer = new Gtk.Revealer () {
child = flagged_icon
};
source = new Gtk.Label (null) {
hexpand = true,
- ellipsize = Pango.EllipsizeMode.END,
+ ellipsize = END,
use_markup = true,
xalign = 0
};
- source.get_style_context ().add_class (Granite.STYLE_CLASS_H3_LABEL);
+ source.add_css_class (Granite.STYLE_CLASS_H3_LABEL);
messages = new Gtk.Label (null) {
halign = Gtk.Align.END
};
- messages.get_style_context ().add_class (Granite.STYLE_CLASS_BADGE);
- messages.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ messages.add_css_class (Granite.STYLE_CLASS_BADGE);
+ messages.add_css_class (Granite.STYLE_CLASS_FLAT);
message_count_revealer = new Gtk.Revealer () {
child = messages
@@ -54,14 +50,14 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
topic = new Gtk.Label (null) {
hexpand = true,
- ellipsize = Pango.EllipsizeMode.END,
+ ellipsize = END,
xalign = 0
};
date = new Gtk.Label (null) {
halign = Gtk.Align.END
};
- date.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ date.add_css_class (Granite.CssClass.DIM);
grid = new Gtk.Grid () {
margin_top = 12,
@@ -74,73 +70,70 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
};
grid.attach (status_revealer, 0, 0);
- grid.attach (flagged_icon_revealer, 0, 1, 1, 1);
- grid.attach (source, 1, 0, 1, 1);
- grid.attach (date, 2, 0, 2, 1);
- grid.attach (topic, 1, 1, 2, 1);
+ grid.attach (flagged_icon_revealer, 0, 1);
+ grid.attach (source, 1, 0);
+ grid.attach (date, 2, 0, 2);
+ grid.attach (topic, 1, 1, 2);
grid.attach (message_count_revealer, 3, 1);
var archive_affordance = new SwipeAffordance (
_("Archive"), "mail-archive-symbolic", END
);
- archive_affordance.get_style_context ().add_class ("archive");
+ archive_affordance.add_css_class ("archive");
var trash_affordance = new SwipeAffordance (
_("Trash"), "edit-delete-symbolic", START
);
- trash_affordance.get_style_context ().add_class ("trash");
+ trash_affordance.add_css_class ("trash");
- carousel = new Hdy.Carousel () {
+ carousel = new Adw.Carousel () {
allow_scroll_wheel = false
};
- carousel.add (grid);
+ carousel.append (grid);
carousel.prepend (archive_affordance);
- carousel.add (trash_affordance);
- carousel.scroll_to (grid);
+ carousel.append (trash_affordance);
- get_style_context ().add_class ("conversation-list-item");
+ add_css_class ("conversation-list-item");
child = carousel;
- show_all ();
+ menu = new Gtk.PopoverMenu.from_model (null) {
+ has_arrow = false,
+ position = BOTTOM
+ };
+ menu.set_parent (this);
- gesture_controller = new Gtk.GestureMultiPress (this) {
+ var click_controller = new Gtk.GestureClick () {
button = Gdk.BUTTON_SECONDARY,
propagation_phase = BUBBLE
};
- gesture_controller.released.connect ((n_press, x, y) => {
- select ();
- menu.popup_at_pointer (null);
+ click_controller.released.connect ((n_press, x, y) => {
+ menu_popup_at_pointer (menu, x, y);
});
- key_controller = new Gtk.EventControllerKey (this);
+ var key_controller = new Gtk.EventControllerKey ();
key_controller.key_released.connect ((keyval) => {
if (keyval != Gdk.Key.Menu) {
return;
}
- menu.popup_at_widget (this, Gdk.Gravity.EAST, Gdk.Gravity.CENTER, null);
+ menu_popup_on_keypress (menu);
});
+ add_controller (click_controller);
+ add_controller (key_controller);
+
carousel.page_changed.connect ((index) => {
if (index == 1) {
return;
}
- select ();
-
- var main_window = (MainWindow)get_toplevel ();
if (index == 2) {
- main_window.activate_action (MainWindow.ACTION_MOVE_TO_TRASH, null);
+ activate_action (MainWindow.ACTION_PREFIX + MainWindow.ACTION_MOVE_TO_TRASH, null);
} else if (index == 0) {
- main_window.activate_action (MainWindow.ACTION_ARCHIVE, null);
+ activate_action (MainWindow.ACTION_PREFIX + MainWindow.ACTION_ARCHIVE, null);
}
-
- Idle.add (() => {
- carousel.scroll_to_full (grid, 0);
- return Source.REMOVE;
- });
});
}
@@ -162,19 +155,19 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
message_count_revealer.reveal_child = num_messages > 1;
if (item_model.unread) {
- grid.get_style_context ().add_class ("unread-message");
+ grid.add_css_class ("unread-message");
status_icon.icon_name = "mail-unread-symbolic";
status_icon.tooltip_text = _("Unread");
- status_icon.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT);
+ status_icon.add_css_class (Granite.CssClass.ACCENT);
status_revealer.reveal_child = true;
- source.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT);
+ source.add_css_class (Granite.CssClass.ACCENT);
} else {
- grid.get_style_context ().remove_class ("unread-message");
- status_icon.get_style_context ().remove_class (Granite.STYLE_CLASS_ACCENT);
- source.get_style_context ().remove_class (Granite.STYLE_CLASS_ACCENT);
+ grid.remove_css_class ("unread-message");
+ status_icon.remove_css_class (Granite.CssClass.ACCENT);
+ source.remove_css_class (Granite.CssClass.ACCENT);
if (item_model.replied_all || item_model.replied) {
status_icon.icon_name = "mail-replied-symbolic";
@@ -206,12 +199,28 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
menu_model.append (_("Unstar"), MainWindow.ACTION_PREFIX + MainWindow.ACTION_MARK_UNSTAR);
}
- menu = new Gtk.Menu.from_model (menu_model) {
- attach_widget = this
+ menu.menu_model = menu_model;
+ }
+
+ private void menu_popup_at_pointer (Gtk.PopoverMenu popover, double x, double y) {
+ var rect = Gdk.Rectangle () {
+ x = (int) x,
+ y = (int) y
};
+ popover.pointing_to = rect;
+ popover.popup ();
+ }
+
+ private void menu_popup_on_keypress (Gtk.PopoverMenu popover) {
+ popover.halign = END;
+ popover.set_pointing_to (Gdk.Rectangle () {
+ x = (int) get_width (),
+ y = (int) get_height () / 2
+ });
+ popover.popup ();
}
- private class SwipeAffordance : Gtk.Box {
+ private class SwipeAffordance : Granite.Bin {
public Gtk.Align alignment { get; construct; }
public string icon_name { get; construct; }
public string label { get; construct; }
@@ -229,10 +238,10 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
}
construct {
- var image = new Gtk.Image.from_icon_name (icon_name, MENU);
+ var image = new Gtk.Image.from_icon_name (icon_name);
var label = new Gtk.Label (label);
- label.get_style_context ().add_class (Granite.STYLE_CLASS_SMALL_LABEL);
+ label.add_css_class (Granite.CssClass.SMALL);
var box = new Gtk.Box (VERTICAL, 3) {
halign = alignment,
@@ -240,15 +249,15 @@ public class Mail.ConversationListItem : VirtualizingListBoxRow {
valign = CENTER,
vexpand = false
};
- box.add (image);
- box.add (label);
+ box.append (image);
+ box.append (label);
- add (box);
+ child = box;
if (alignment == Gtk.Align.START) {
- get_style_context ().add_class ("start");
+ add_css_class ("start");
} else if (alignment == Gtk.Align.END) {
- get_style_context ().add_class ("end");
+ add_css_class ("end");
}
}
}
diff --git a/src/ConversationList/ConversationListStore.vala b/src/ConversationList/ConversationListStore.vala
deleted file mode 100644
index 0ee613cd9..000000000
--- a/src/ConversationList/ConversationListStore.vala
+++ /dev/null
@@ -1,217 +0,0 @@
-// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
-/*-
- * Copyright (c) 2017 elementary LLC. (https://elementary.io)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authored by: David Hewitt
- */
-
-public class Mail.ConversationListStore : ListModel, Object {
- public delegate bool RowVisibilityFunc (GLib.Object row);
-
- private Gee.HashSet selected_rows = new Gee.HashSet ();
- private GLib.Sequence data = new GLib.Sequence ();
- private uint last_position = uint.MAX;
- private GLib.SequenceIter? last_iter;
- private unowned RowVisibilityFunc filter_func;
-
- private GLib.Type get_item_type () {
- return typeof (GLib.Object);
- }
-
- public uint get_n_items () {
- return data.get_length ();
- }
-
- private GLib.Object? get_item (uint index) {
- return get_item_internal (index);
- }
-
- private GLib.Object? get_item_internal (uint index, bool unfiltered = false) {
- GLib.SequenceIter? iter = null;
-
- if (last_position != uint.MAX) {
- if (last_position == index + 1) {
- iter = last_iter.prev ();
- } else if (last_position == index - 1) {
- iter = last_iter.next ();
- } else if (last_position == index) {
- iter = last_iter;
- }
- }
-
- if (iter == null) {
- iter = data.get_iter_at_pos ((int)index);
- }
-
- last_iter = iter;
- last_position = index;
-
- if (iter.is_end ()) {
- return null;
- }
-
- if (filter_func == null) {
- return iter.get ();
- } else if (filter_func (iter.get ())) {
- return iter.get ();
- } else if (unfiltered) {
- return iter.get ();
- } else {
- return null;
- }
- }
-
- public void insert_sorted (ConversationItemModel item, CompareDataFunc