diff --git a/data/gresource.xml b/data/gresource.xml
index 353c87343..4d1403ca0 100644
--- a/data/gresource.xml
+++ b/data/gresource.xml
@@ -4,6 +4,6 @@
Application.css
- LocationMarker.svg
+ LocationMarker.svg
diff --git a/data/gschema.xml b/data/gschema.xml
index 8f5148c29..469694029 100644
--- a/data/gschema.xml
+++ b/data/gschema.xml
@@ -6,10 +6,15 @@
Whether the window was maximized on last run
Whether the window was maximized on last run
-
- (1000, 800)
- Most recent window size
- Most recent window size (width, height)
+
+ 1024
+ Most recent window width
+ Most recent window width
+
+
+ 750
+ Most recent window height
+ Most recent window height
256
diff --git a/io.elementary.tasks.json b/io.elementary.tasks.json
index 295dd9c9b..8096e4da8 100644
--- a/io.elementary.tasks.json
+++ b/io.elementary.tasks.json
@@ -95,87 +95,6 @@
}
]
},
- {
- "name": "clutter-gtk",
- "cleanup": [
- "/share/gtk-doc"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://download.gnome.org/sources/clutter-gtk/1.8/clutter-gtk-1.8.4.tar.xz",
- "sha256": "521493ec038973c77edcb8bc5eac23eed41645117894aaee7300b2487cb42b06"
- }
- ],
- "modules": [
- {
- "name": "cogl",
- "config-opts": [
- "--disable-cogl-gst",
- "--disable-gtk-doc",
- "--enable-xlib-egl-platform",
- "--enable-wayland-egl-platform"
- ],
- "cleanup": [
- "/share/gtk-doc",
- "/share/cogl/examples-data"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://download.gnome.org/sources/cogl/1.22/cogl-1.22.8.tar.xz",
- "sha256": "a805b2b019184710ff53d0496f9f0ce6dcca420c141a0f4f6fcc02131581d759"
- }
- ]
- },
- {
- "name": "clutter",
- "config-opts": [
- "--disable-gtk-doc",
- "--enable-egl-backend",
- "--enable-wayland-backend",
- "--enable-deprecated=no"
- ],
- "cleanup": [
- "/share/gtk-doc"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://download.gnome.org/sources/clutter/1.26/clutter-1.26.4.tar.xz",
- "sha256": "8b48fac159843f556d0a6be3dbfc6b083fc6d9c58a20a49a6b4919ab4263c4e6"
- }
- ]
- },
- {
- "name": "clutter-gst",
- "config-opts": [
- "--disable-gtk-doc"
- ],
- "cleanup": [
- "/share/gtk-doc"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://download.gnome.org/sources/clutter-gst/3.0/clutter-gst-3.0.27.tar.xz",
- "sha256": "fe69bd6c659d24ab30da3f091eb91cd1970026d431179b0724f13791e8ad9f9d"
- }
- ]
- }
- ]
- },
- {
- "name": "champlain",
- "buildsystem": "meson",
- "sources": [
- {
- "type": "archive",
- "url": "https://download.gnome.org/sources/libchamplain/0.12/libchamplain-0.12.21.tar.xz",
- "sha256": "a915cd172a0c52944c5579fcb4683f8a878c571bf5e928254b5dafefc727e5a7"
- }
- ]
- },
{
"name": "geocode-glib-2.0",
"buildsystem": "meson",
@@ -211,6 +130,27 @@
}
]
},
+ {
+ "name": "libshumate",
+ "buildsystem": "meson",
+ "config-opts": [
+ "-Ddemos=false",
+ "-Dgtk_doc=false",
+ "-Dvapi=false"
+ ],
+ "sources": [
+ {
+ "type": "archive",
+ "url": "https://download.gnome.org/sources/libshumate/1.2/libshumate-1.2.1.tar.xz",
+ "sha256": "1105ee077e2147f2a039cddfa616fa5cb9438883dd940427e11699dcd6549c11",
+ "x-checker-data": {
+ "type": "gnome",
+ "stable-only": false,
+ "name": "libshumate"
+ }
+ }
+ ]
+ },
{
"name": "tasks",
"buildsystem": "meson",
diff --git a/meson.build b/meson.build
index 4ee94be3b..b76277a5e 100644
--- a/meson.build
+++ b/meson.build
@@ -28,21 +28,17 @@ config_file = configure_file(
libecal_dep = dependency('libecal-2.0')
tasks_deps = [
- dependency('champlain-0.12'),
- dependency('champlain-gtk-0.12'),
- dependency('clutter-1.0'),
- dependency('clutter-gtk-1.0'),
dependency('glib-2.0'),
dependency('gobject-2.0'),
- dependency('granite', version: '>=6.2.0'),
- dependency('gtk+-3.0'),
+ dependency('granite-7', version: '>=7.0.0'),
+ dependency('gtk4', version: '>=4.12'),
libecal_dep,
dependency('libedataserver-1.2'),
dependency('libgeoclue-2.0'),
- dependency('libhandy-1', version: '>=0.90.0'),
+ dependency('shumate-1.0'),
dependency('libical-glib'),
dependency('libportal'),
- dependency('libportal-gtk3')
+ dependency('libportal-gtk4')
]
if libecal_dep.version().version_compare('>=3.46.0')
@@ -66,19 +62,20 @@ executable(
'src/Application.vala',
'src/Location.vala',
'src/MainWindow.vala',
+ 'src/TaskModel.vala',
'src/TodayTaskMonitor.vala',
'src/Util.vala',
- 'src/Widgets/EditableLabel.vala',
'src/Widgets/EntryPopover/DateTime.vala',
'src/Widgets/EntryPopover/Generic.vala',
'src/Widgets/EntryPopover/Location.vala',
+ 'src/Widgets/EditableLabel.vala',
+ 'src/Widgets/ListSettingsPopover.vala',
+ 'src/Widgets/PopoverButton.vala',
'src/Widgets/ScheduledRow.vala',
- 'src/Widgets/SourceRow.vala',
'src/Widgets/ScheduledTaskListBox.vala',
+ 'src/Widgets/SourceRow.vala',
'src/Widgets/TaskListGrid.vala',
'src/Widgets/TaskRow.vala',
- 'src/Widgets/ListSettingsPopover.vala',
- 'src/TaskModel.vala',
dependencies: tasks_deps,
install : true
)
diff --git a/src/Application.vala b/src/Application.vala
index 2a002daba..9a561683c 100644
--- a/src/Application.vala
+++ b/src/Application.vala
@@ -28,12 +28,7 @@ public class Tasks.Application : Gtk.Application {
public static Tasks.TaskModel model;
public static bool run_in_background = false;
- public const Gtk.TargetEntry[] DRAG_AND_DROP_TASK_DATA = {
- { "text/uri-list", Gtk.TargetFlags.SAME_APP | Gtk.TargetFlags.OTHER_WIDGET, 0 } // TODO: TEXT_URI
- };
-
private bool first_activation = true;
-
public Application () {
Object (
application_id: "io.elementary.tasks",
@@ -58,7 +53,7 @@ public class Tasks.Application : Gtk.Application {
protected override void startup () {
base.startup ();
- Hdy.init ();
+ Granite.init ();
unowned var granite_settings = Granite.Settings.get_default ();
unowned var gtk_settings = Gtk.Settings.get_default ();
@@ -69,11 +64,6 @@ public class Tasks.Application : Gtk.Application {
gtk_settings.gtk_application_prefer_dark_theme = ((Granite.Settings) obj).prefers_color_scheme == DARK;
});
- var css_provider = new Gtk.CssProvider ();
- css_provider.load_from_resource ("io/elementary/tasks/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 (() => {
if (active_window != null) {
@@ -105,15 +95,19 @@ public class Tasks.Application : Gtk.Application {
var 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", DEFAULT);
+ settings.bind ("window-width", main_window, "default-width", DEFAULT);
if (settings.get_boolean ("window-maximized")) {
main_window.maximize ();
}
- main_window.show_all ();
+ settings.bind ("window-maximized", main_window, "maximized", SET);
}
active_window.present ();
@@ -153,7 +147,7 @@ public class Tasks.Application : Gtk.Application {
if (providers == null) {
providers = new Gee.HashMap ();
}
- var task_list = (E.SourceTaskList?) source.get_extension (E.SOURCE_EXTENSION_TASK_LIST);
+ unowned var task_list = (E.SourceTaskList?) source.get_extension (E.SOURCE_EXTENSION_TASK_LIST);
// Ensure we get a valid CSS color, not including FF
var color = task_list.dup_color ().slice (0, 7);
if (!providers.has_key (color)) {
@@ -162,21 +156,16 @@ public class Tasks.Application : Gtk.Application {
@define-color accent_color %s;
""".printf (color, color);
- try {
- var style_provider = new Gtk.CssProvider ();
- style_provider.load_from_data (style, style.length);
+ var style_provider = new Gtk.CssProvider ();
+ style_provider.load_from_string (style);
- providers[color] = style_provider;
- } catch (Error e) {
- critical ("Unable to set color: %s", e.message);
- }
+ providers[color] = style_provider;
}
widget.get_style_context ().add_provider (providers[color], Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
}
public static int main (string[] args) {
- GtkClutter.init (ref args);
var app = new Application ();
int res = app.run (args);
ICal.Object.free_global_objects ();
diff --git a/src/MainWindow.vala b/src/MainWindow.vala
index a54f36dd5..4c7edcc77 100644
--- a/src/MainWindow.vala
+++ b/src/MainWindow.vala
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-public class Tasks.MainWindow : Hdy.ApplicationWindow {
+public class Tasks.MainWindow : Gtk.ApplicationWindow {
public const string ACTION_GROUP_PREFIX = "win";
public const string ACTION_PREFIX = ACTION_GROUP_PREFIX + ".";
public const string ACTION_DELETE_SELECTED_LIST = "action-delete-selected-list";
@@ -16,12 +16,12 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
private static Gee.MultiMap action_accelerators = new Gee.HashMultiMap ();
- private uint configure_id;
private Gtk.ListBox listbox;
private Gee.HashMap? source_rows;
private Gee.Collection? collection_sources;
private Gtk.Stack task_list_grid_stack;
private Gtk.Box add_tasklist_buttonbox;
+ private Gtk.Popover add_tasklist_popover;
public MainWindow (Gtk.Application application) {
Object (
@@ -45,33 +45,29 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
);
}
- var sidebar_header = new Hdy.HeaderBar () {
- has_subtitle = false,
- show_close_button = true
+ var sidebar_header = new Gtk.HeaderBar () {
+ title_widget = new Gtk.Label (null),
+ show_title_buttons = false
};
- sidebar_header.get_style_context ().add_class ("default-decoration");
- sidebar_header.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ sidebar_header.add_css_class (Granite.STYLE_CLASS_DEFAULT_DECORATION);
+ sidebar_header.add_css_class (Granite.STYLE_CLASS_FLAT);
+ sidebar_header.pack_start (new Gtk.WindowControls (Gtk.PackType.START));
- var main_header = new Hdy.HeaderBar () {
- has_subtitle = false,
- show_close_button = true
+ var main_header = new Gtk.HeaderBar () {
+ title_widget = new Gtk.Label (null),
+ show_title_buttons = false
};
- main_header.get_style_context ().add_class ("default-decoration");
- main_header.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
-
- // Create a header group that automatically assigns the right decoration controls to the
- // right headerbar automatically
- var header_group = new Hdy.HeaderGroup ();
- header_group.add_header_bar (sidebar_header);
- header_group.add_header_bar (main_header);
+ main_header.add_css_class (Granite.STYLE_CLASS_DEFAULT_DECORATION);
+ main_header.add_css_class (Granite.STYLE_CLASS_FLAT);
+ main_header.pack_end (new Gtk.WindowControls (Gtk.PackType.END));
listbox = new Gtk.ListBox ();
listbox.set_sort_func (sort_function);
var scheduled_row = new Tasks.Widgets.ScheduledRow ();
- listbox.add (scheduled_row);
+ listbox.append (scheduled_row);
- var scrolledwindow = new Gtk.ScrolledWindow (null, null) {
+ var scrolledwindow = new Gtk.ScrolledWindow () {
child = listbox,
hexpand = true,
vexpand = true,
@@ -80,66 +76,72 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
add_tasklist_buttonbox = new Gtk.Box (VERTICAL, 3);
- var online_accounts_button = new Gtk.ModelButton () {
- text = _("Online Accounts Settings…")
- };
+ var online_accounts_button = new Widgets.PopoverButton ();
+ online_accounts_button.append (new Gtk.Label (_("Online Accounts Settings…")));
- var add_tasklist_box = new Gtk.Box (VERTICAL, 3) {
- margin_top = 3,
- margin_bottom = 3
- };
- add_tasklist_box.add (add_tasklist_buttonbox);
- add_tasklist_box.add (new Gtk.Separator (HORIZONTAL));
- add_tasklist_box.add (online_accounts_button);
- add_tasklist_box.show_all ();
+ var add_tasklist_box = new Gtk.Box (VERTICAL, 0);
+ add_tasklist_box.append (add_tasklist_buttonbox);
+ add_tasklist_box.append (new Gtk.Separator (HORIZONTAL));
+ add_tasklist_box.append (online_accounts_button);
- var add_tasklist_popover = new Gtk.Popover (null) {
+ add_tasklist_popover = new Gtk.Popover () {
child = add_tasklist_box
};
+ add_tasklist_popover.add_css_class (Granite.STYLE_CLASS_MENU);
var add_list_label = new Gtk.Label (_("Add Task List…"));
var add_list_button_box = new Gtk.Box (HORIZONTAL, 0);
- add_list_button_box.add (new Gtk.Image.from_icon_name ("list-add-symbolic", SMALL_TOOLBAR));
- add_list_button_box.add (add_list_label);
+ add_list_button_box.append (new Gtk.Image.from_icon_name ("list-add-symbolic"));
+ add_list_button_box.append (add_list_label);
var add_tasklist_button = new Gtk.MenuButton () {
- child = add_list_button_box,
- popover = add_tasklist_popover
+ popover = add_tasklist_popover,
+ direction = UP,
+ child = add_list_button_box
};
add_list_label.mnemonic_widget = add_tasklist_button;
var actionbar = new Gtk.ActionBar ();
- actionbar.add (add_tasklist_button);
- actionbar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ actionbar.add_css_class (Granite.STYLE_CLASS_FLAT);
+ actionbar.pack_start (add_tasklist_button);
var sidebar = new Gtk.Box (VERTICAL, 0);
- sidebar.get_style_context ().add_class (Gtk.STYLE_CLASS_SIDEBAR);
- sidebar.add (sidebar_header);
- sidebar.add (scrolledwindow);
- sidebar.add (actionbar);
+ sidebar.add_css_class (Granite.STYLE_CLASS_SIDEBAR);
+ sidebar.append (sidebar_header);
+ sidebar.append (scrolledwindow);
+ sidebar.append (actionbar);
task_list_grid_stack = new Gtk.Stack ();
var main_box = new Gtk.Box (VERTICAL, 0);
- main_box.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND);
- main_box.add (main_header);
- main_box.add (task_list_grid_stack);
-
- var paned = new Gtk.Paned (HORIZONTAL);
- paned.pack1 (sidebar, false, false);
- paned.pack2 (main_box, true, false);
+ main_box.add_css_class (Granite.STYLE_CLASS_BACKGROUND);
+ main_box.append (main_header);
+ main_box.append (task_list_grid_stack);
+
+ var paned = new Gtk.Paned (HORIZONTAL) {
+ start_child = sidebar,
+ end_child = main_box,
+ resize_start_child = false,
+ shrink_end_child = false,
+ shrink_start_child = false
+ };
child = paned;
- delete_event.connect (() => {
+ // We need to hide the title area for the split headerbar
+ titlebar = new Gtk.Grid () { visible = false };
+
+ close_request.connect (() => {
((Application)application).request_background.begin (() => destroy ());
return Gdk.EVENT_STOP;
});
online_accounts_button.clicked.connect (() => {
+ add_tasklist_popover.popdown ();
+
try {
AppInfo.launch_default_for_uri ("settings://accounts/online", null);
} catch (Error e) {
@@ -189,9 +191,11 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
add_source (source);
if (last_selected_list == "" && default_task_list == source) {
+ assert (source_rows[source] != null);
listbox.select_row (source_rows[source]);
} else if (last_selected_list == source.uid) {
+ assert (source_rows[source] != null);
listbox.select_row (source_rows[source]);
}
}
@@ -313,7 +317,7 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
};
unowned var trash_button = message_dialog.add_button (_("Delete Anyway"), Gtk.ResponseType.YES);
- trash_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ trash_button.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION);
message_dialog.response.connect ((response) => {
if (response == Gtk.ResponseType.YES) {
@@ -335,9 +339,8 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
});
message_dialog.present ();
-
} else {
- Gdk.beep ();
+ Gdk.Display.get_default ().beep ();
}
}
@@ -355,7 +358,6 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
}
var header_label = new Granite.HeaderLabel (Util.get_esource_collection_display_name (row.source)) {
- ellipsize = Pango.EllipsizeMode.MIDDLE,
margin_start = 6
};
@@ -389,17 +391,18 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
}
collection_sources.add (collection_source);
- var source_button = new Gtk.ModelButton () {
- text = Util.get_esource_collection_display_name (collection_source),
+ var source_button = new Widgets.PopoverButton () {
sensitive = Application.model.is_add_task_list_supported (collection_source)
};
+ source_button.append (new Gtk.Label (Util.get_esource_collection_display_name (collection_source)));
source_button.clicked.connect (() => {
+ add_tasklist_popover.popdown ();
+
add_new_list (collection_source);
});
- add_tasklist_buttonbox.add (source_button);
- add_tasklist_buttonbox.show_all ();
+ add_tasklist_buttonbox.append (source_button);
}
private void add_source (E.Source source) {
@@ -411,11 +414,10 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
if (!source_rows.has_key (source)) {
source_rows[source] = new Tasks.Widgets.SourceRow (source);
- listbox.add (source_rows[source]);
+ listbox.append (source_rows[source]);
Idle.add (() => {
listbox.invalidate_sort ();
listbox.invalidate_headers ();
- listbox.show_all ();
return Source.REMOVE;
});
@@ -460,29 +462,4 @@ public class Tasks.MainWindow : Hdy.ApplicationWindow {
return Source.REMOVE;
});
}
-
- public override bool configure_event (Gdk.EventConfigure event) {
- if (configure_id != 0) {
- GLib.Source.remove (configure_id);
- }
-
- configure_id = Timeout.add (100, () => {
- configure_id = 0;
-
- if (is_maximized) {
- Tasks.Application.settings.set_boolean ("window-maximized", true);
- } else {
- Tasks.Application.settings.set_boolean ("window-maximized", false);
-
- Gdk.Rectangle rect;
- get_allocation (out rect);
- Tasks.Application.settings.set ("window-size", "(ii)", rect.width, rect.height);
-
- }
-
- return false;
- });
-
- return base.configure_event (event);
- }
}
diff --git a/src/TaskModel.vala b/src/TaskModel.vala
index f7aa339c3..d3a1477b0 100644
--- a/src/TaskModel.vala
+++ b/src/TaskModel.vala
@@ -36,7 +36,7 @@ public class Tasks.TaskModel : Object {
public delegate void TasksRemovedFunc (SList cids);
private Gee.Future registry;
- private NetworkMonitor network_monitor;
+ // private NetworkMonitor network_monitor;
private HashTable task_list_client;
private HashTable> task_list_client_views;
@@ -133,14 +133,15 @@ public class Tasks.TaskModel : Object {
construct {
task_list_client = new HashTable (str_hash, str_equal);
task_list_client_views = new HashTable> (direct_hash, direct_equal); // vala-lint=line-length
- network_monitor = NetworkMonitor.get_default ();
+ // Failed to initialize portal (GNetworkMonitorPortal) for gio-network-monitor: Not using portals
+ // network_monitor = NetworkMonitor.get_default ();
}
public async void start () {
var promise = new Gee.Promise ();
registry = promise.future;
yield init_registry (promise);
- network_monitor.network_changed.connect (network_changed);
+ // network_monitor.network_changed.connect (network_changed);
}
private async void init_registry (Gee.Promise promise) {
@@ -239,15 +240,18 @@ public class Tasks.TaskModel : Object {
}
private async bool refresh_collection (E.Source collection_source, Cancellable? cancellable = null) throws Error {
- if (network_monitor.network_available && registry.ready) {
+ // if (network_monitor.network_available && registry.ready) {
+ if (registry.ready) {
debug ("Scheduling collection refresh '%s'…", collection_source.dup_display_name ());
return yield registry.value.refresh_backend (collection_source.dup_uid (), cancellable);
}
+
return false;
}
public async bool refresh_task_list (E.Source task_list, Cancellable? cancellable = null) throws Error {
- if (network_monitor.network_available && task_list_client.contains (task_list.dup_uid ())) {
+ // if (network_monitor.network_available && task_list_client.contains (task_list.dup_uid ())) {
+ if (task_list_client.contains (task_list.dup_uid ())) {
var client = task_list_client.get (task_list.dup_uid ());
if (client.check_refresh_supported ()) {
diff --git a/src/Widgets/EditableLabel.vala b/src/Widgets/EditableLabel.vala
index 42cecb812..2af96b857 100644
--- a/src/Widgets/EditableLabel.vala
+++ b/src/Widgets/EditableLabel.vala
@@ -4,16 +4,13 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
-public class Tasks.Widgets.EditableLabel : Gtk.EventBox {
+public class Tasks.Widgets.EditableLabel : Gtk.Widget {
public signal void changed ();
private Gtk.Label title;
private Gtk.Entry entry;
private Gtk.Stack stack;
- private Gtk.EventControllerMotion motion_controller;
- private Gtk.GestureMultiPress click_gesture;
-
public string text { get; set; default = ""; }
public bool editing {
@@ -35,6 +32,7 @@ public class Tasks.Widgets.EditableLabel : Gtk.EventBox {
}
class construct {
+ set_layout_manager_type (typeof (Gtk.BinLayout));
set_css_name ("editable-label");
}
@@ -54,29 +52,27 @@ public class Tasks.Widgets.EditableLabel : Gtk.EventBox {
hhomogeneous = false,
transition_type = CROSSFADE
};
- stack.add (title);
- stack.add (entry);
-
- add (stack);
+ stack.add_child (title);
+ stack.add_child (entry);
+ stack.set_parent (this);
bind_property ("text", title, "label");
- motion_controller = new Gtk.EventControllerMotion (this) {
+ var motion_controller = new Gtk.EventControllerMotion () {
propagation_phase = CAPTURE
};
- click_gesture = new Gtk.GestureMultiPress (this);
+ var click_gesture = new Gtk.GestureClick ();
+
+ add_controller (click_gesture);
+ add_controller (motion_controller);
motion_controller.enter.connect (() => {
- get_window ().set_cursor (
- new Gdk.Cursor.from_name (Gdk.Display.get_default (), "text")
- );
+ set_cursor (new Gdk.Cursor.from_name ("text", null));
});
motion_controller.leave.connect (() => {
- get_window ().set_cursor (
- new Gdk.Cursor.from_name (Gdk.Display.get_default (), "default")
- );
+ set_cursor (new Gdk.Cursor.from_name ("default", null));
});
click_gesture.released.connect (() => {
@@ -89,16 +85,23 @@ public class Tasks.Widgets.EditableLabel : Gtk.EventBox {
}
});
- entry.focus_out_event.connect ((event) => {
+ var focus_controller = new Gtk.EventControllerFocus ();
+ entry.add_controller (focus_controller);
+
+ focus_controller.leave.connect (() => {
if (stack.visible_child == entry) {
editing = false;
}
-
- return Gdk.EVENT_PROPAGATE;
});
}
- public override void grab_focus () {
+ ~EditableLabel () {
+ get_first_child ().unparent ();
+ }
+
+ public override bool grab_focus () {
editing = true;
+
+ return Gdk.EVENT_STOP;
}
}
diff --git a/src/Widgets/EntryPopover/DateTime.vala b/src/Widgets/EntryPopover/DateTime.vala
index e74fb968c..d57c1638c 100644
--- a/src/Widgets/EntryPopover/DateTime.vala
+++ b/src/Widgets/EntryPopover/DateTime.vala
@@ -5,7 +5,7 @@
public class Tasks.Widgets.EntryPopover.DateTime : Generic {
private Gtk.Calendar calendar;
- private Granite.Widgets.TimePicker timepicker;
+ private Granite.TimePicker timepicker;
private Gtk.Revealer timepicker_revealer;
public DateTime () {
@@ -22,44 +22,40 @@ public class Tasks.Widgets.EntryPopover.DateTime : Generic {
margin_start = 6,
margin_end = 6
};
- calendar.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND);
- timepicker = new Granite.Widgets.TimePicker () {
- margin_top = 0,
+ timepicker = new Granite.TimePicker () {
+ margin_top = 12,
margin_bottom = 12,
margin_start = 12,
margin_end = 12
};
timepicker_revealer = new Gtk.Revealer () {
- reveal_child = true
+ reveal_child = true,
+ child = timepicker
};
- timepicker_revealer.add (timepicker);
-
var today_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL) {
margin_bottom = 3,
margin_top = 3
};
- var today_button = new Gtk.ModelButton () {
- text = _("Today")
- };
+ var today_box = new Widgets.PopoverButton ();
+ today_box.append (new Gtk.Label (_("Today")));
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) {
margin_top = 3
};
- box.add (today_button);
- box.add (today_separator);
- box.add (calendar);
- box.add (timepicker_revealer);
- box.show_all ();
+ box.append (today_box);
+ box.append (today_separator);
+ box.append (calendar);
+ box.append (timepicker_revealer);
- popover.add (box);
+ popover.child = box;
popover.show.connect (on_popover_show);
- today_button.button_release_event.connect (on_today_button_release_event);
+ today_box.clicked.connect (on_today_button_clicked);
calendar.day_selected.connect (on_calendar_day_selected);
timepicker.time_changed.connect (on_timepicker_time_changed);
}
@@ -77,18 +73,12 @@ public class Tasks.Widgets.EntryPopover.DateTime : Generic {
value = selected_datetime;
}
- calendar.select_month (selected_datetime.get_month () - 1, selected_datetime.get_year ());
- calendar.select_day (selected_datetime.get_day_of_month ());
+ calendar.select_day (selected_datetime);
timepicker.time = selected_datetime;
}
- private bool on_today_button_release_event () {
- var now_local = new GLib.DateTime.now_local ();
-
- calendar.select_month (now_local.get_month () - 1, now_local.get_year ());
- calendar.select_day (now_local.get_day_of_month ());
-
- return Gdk.EVENT_STOP;
+ private void on_today_button_clicked () {
+ calendar.select_day (new GLib.DateTime.now_local ());
}
private void on_calendar_day_selected () {
diff --git a/src/Widgets/EntryPopover/Generic.vala b/src/Widgets/EntryPopover/Generic.vala
index 9232417b3..7ba4097a4 100644
--- a/src/Widgets/EntryPopover/Generic.vala
+++ b/src/Widgets/EntryPopover/Generic.vala
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
+public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Widget {
public signal string? value_format (T value);
public signal void value_changed (T value);
@@ -14,8 +14,6 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
private T value_on_popover_show;
- private Gtk.EventControllerMotion motion_controller;
-
protected Generic (string placeholder, string? icon_name = null) {
Object (
icon_name: icon_name,
@@ -25,31 +23,34 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
class construct {
set_css_name ("entry-popover");
+ set_layout_manager_type (typeof (Gtk.BinLayout));
}
construct {
- popover = new Gtk.Popover (null);
+ popover = new Gtk.Popover () {
+ autohide = true
+ };
var label = new Gtk.Label (placeholder);
var popover_button_box = new Gtk.Box (HORIZONTAL, 0);
if (icon_name != null) {
- popover_button_box.add (new Gtk.Image.from_icon_name (icon_name, BUTTON));
+ popover_button_box.append (new Gtk.Image.from_icon_name (icon_name));
}
- popover_button_box.add (label);
+ popover_button_box.append (label);
var popover_button = new Gtk.MenuButton () {
child = popover_button_box,
+ has_frame = false,
popover = popover
};
- popover_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
label.mnemonic_widget = popover_button;
- var delete_button = new Gtk.Button.from_icon_name ("process-stop-symbolic", BUTTON) {
+ var delete_button = new Gtk.Button.from_icon_name ("process-stop-symbolic") {
tooltip_text = _("Remove")
};
- delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ delete_button.add_css_class ("delete-button");
var delete_button_revealer = new Gtk.Revealer () {
child = delete_button,
@@ -58,10 +59,9 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
};
var button_box = new Gtk.Box (HORIZONTAL, 0);
- button_box.add (popover_button);
- button_box.add (delete_button_revealer);
-
- add (button_box);
+ button_box.append (popover_button);
+ button_box.append (delete_button_revealer);
+ button_box.set_parent (this);
delete_button.clicked.connect (() => {
var value_has_changed = value != null;
@@ -71,7 +71,7 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
}
});
- popover_button.clicked.connect (() => {
+ popover_button.activate.connect (() => {
if (delete_button_revealer.reveal_child) {
delete_button_revealer.reveal_child = false;
}
@@ -91,9 +91,8 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
}
});
- motion_controller = new Gtk.EventControllerMotion (this) {
- propagation_phase = CAPTURE
- };
+ var motion_controller = new Gtk.EventControllerMotion ();
+ add_controller (motion_controller);
motion_controller.enter.connect (() => {
if (value_format (value) != null) {
@@ -123,4 +122,8 @@ public abstract class Tasks.Widgets.EntryPopover.Generic : Gtk.Box {
});
});
}
+
+ ~Generic () {
+ get_last_child ().unparent ();
+ }
}
diff --git a/src/Widgets/EntryPopover/Location.vala b/src/Widgets/EntryPopover/Location.vala
index bc2a2d210..a3d5ba8c1 100644
--- a/src/Widgets/EntryPopover/Location.vala
+++ b/src/Widgets/EntryPopover/Location.vala
@@ -1,5 +1,5 @@
/*
-* Copyright 2021 elementary, Inc. (https://elementary.io)
+* Copyright 2021-2023 elementary, Inc. (https://elementary.io)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
@@ -18,11 +18,11 @@
*/
public class Tasks.Widgets.EntryPopover.Location : Generic {
- private GtkChamplain.Embed map_embed;
+ // private GtkChamplain.Embed map_embed;
private Gtk.SearchEntry search_entry;
- private GLib.Cancellable search_cancellable;
- private Granite.Widgets.ModeButton location_mode;
- private Marker point;
+ // private GLib.Cancellable search_cancellable;
+ // private Granite.Widgets.ModeButton location_mode;
+ // private Marker point;
public Location () {
@@ -33,28 +33,28 @@ public class Tasks.Widgets.EntryPopover.Location : Generic {
}
construct {
- map_embed = new GtkChamplain.Embed () {
- height_request = 140,
- width_request = 260
- };
+ // map_embed = new GtkChamplain.Embed () {
+ // height_request = 140,
+ // width_request = 260
+ // };
- point = new Marker ();
+ // point = new Marker ();
- var marker_layer = new Champlain.MarkerLayer.full (Champlain.SelectionMode.SINGLE);
- marker_layer.add_marker (point);
+ // var marker_layer = new Champlain.MarkerLayer.full (Champlain.SelectionMode.SINGLE);
+ // marker_layer.add_marker (point);
- var map_view = map_embed.champlain_view;
- map_view.zoom_level = 10;
- map_view.goto_animation_duration = 500;
- map_view.add_layer (marker_layer);
- map_view.center_on (point.latitude, point.longitude);
+ // var map_view = map_embed.champlain_view;
+ // map_view.zoom_level = 10;
+ // map_view.goto_animation_duration = 500;
+ // map_view.add_layer (marker_layer);
+ // map_view.center_on (point.latitude, point.longitude);
- var map_frame = new Gtk.Frame (null);
- map_frame.add (map_embed);
+ // var map_frame = new Gtk.Frame (null);
+ // map_frame.add (map_embed);
- location_mode = new Granite.Widgets.ModeButton ();
- location_mode.append_text (_("Arriving"));
- location_mode.append_text (_("Leaving"));
+ // location_mode = new Granite.Widgets.ModeButton ();
+ // location_mode.append_text (_("Arriving"));
+ // location_mode.append_text (_("Leaving"));
search_entry = new Gtk.SearchEntry () {
placeholder_text = _("John Smith OR Example St."),
@@ -68,182 +68,181 @@ public class Tasks.Widgets.EntryPopover.Location : Generic {
margin_end = 12
};
- box.add (search_entry);
- box.add (location_mode);
- box.add (map_frame);
- box.show_all ();
-
- popover.add (box);
- popover.show.connect (on_popover_show);
+ box.append (search_entry);
+ // box.append (location_mode);
+ // box.append (map_frame);
- notify["value"].connect (on_value_changed);
+ popover.child = box;
+ // popover.show.connect (on_popover_show);
- search_entry.activate.connect (on_search_entry_activate);
- location_mode.mode_changed.connect (on_location_mode_changed);
- }
+ // notify["value"].connect (on_value_changed);
- private void on_popover_show () {
- search_entry.text = (value == null ? "" : value.postal_address);
-
- if (search_entry.text != null && search_entry.text.strip ().length > 0) {
- search_location.begin (search_entry.text);
- } else {
- // Use geoclue to find approximate location
- discover_current_location.begin ();
- }
- }
-
- private void on_value_changed () {
- if (value == null) {
- return;
- }
-
- var value_has_postal_address = value.postal_address != null && value.postal_address.strip ().length > 0;
- if (value_has_postal_address && search_entry.text != value.postal_address) {
- search_entry.text = value.postal_address;
- }
-
- switch (value.proximity) {
- case Tasks.LocationProximity.ARRIVE:
- if (location_mode.selected != 0) {
- location_mode.selected = 0;
- }
- break;
-
- default:
- if (location_mode.selected != 1) {
- location_mode.selected = 1;
- }
- break;
- }
-
- bool need_relocation = true;
- if (value.latitude >= Champlain.MIN_LATITUDE && value.longitude >= Champlain.MIN_LONGITUDE &&
- value.latitude <= Champlain.MAX_LATITUDE && value.longitude <= Champlain.MAX_LONGITUDE) {
-
- point.latitude = value.latitude;
- point.longitude = value.longitude;
-
- need_relocation = (value.latitude == 0 && value.longitude == 0);
- }
-
- if (need_relocation == true) {
- if (value_has_postal_address) {
- search_location.begin (value.postal_address);
- } else {
- // Use geoclue to find approximate location
- discover_current_location.begin ();
- }
- }
- }
-
- private void on_search_entry_activate () {
- value = Tasks.Location () {
- postal_address = search_entry.text,
- display_name = search_entry.text,
- longitude = 0,
- latitude = 0,
- accuracy = (value == null ? Geocode.LocationAccuracy.UNKNOWN : value.accuracy),
- proximity = (value == null ? Tasks.LocationProximity.DEPART : value.proximity)
- };
+ // search_entry.activate.connect (on_search_entry_activate);
+ // location_mode.mode_changed.connect (on_location_mode_changed);
}
- private void on_location_mode_changed () {
- var proximity = (value == null ? Tasks.LocationProximity.DEPART : value.proximity);
-
- switch (location_mode.selected) {
- case 0: proximity = Tasks.LocationProximity.ARRIVE; break;
- case 1: proximity = Tasks.LocationProximity.DEPART; break;
- default: break;
- }
-
- value = Tasks.Location () {
- postal_address = (value == null ? search_entry.text : value.postal_address),
- display_name = (value == null ? search_entry.text : value.display_name),
- longitude = (value == null ? 0 : value.longitude),
- latitude = (value == null ? 0 : value.latitude),
- accuracy = (value == null ? Geocode.LocationAccuracy.UNKNOWN : value.accuracy),
- proximity = proximity
- };
- }
-
- private async void search_location (string location) {
- if (search_cancellable != null) {
- search_cancellable.cancel ();
- }
- search_cancellable = new GLib.Cancellable ();
-
- var forward = new Geocode.Forward.for_string (location);
- try {
- forward.set_answer_count (1);
- var places = yield forward.search_async (search_cancellable);
- foreach (var place in places) {
- point.latitude = place.location.latitude;
- point.longitude = place.location.longitude;
-
- if (value != null) {
- value.latitude = place.location.latitude;
- value.longitude = place.location.longitude;
- }
-
- Idle.add (() => {
- if (search_cancellable.is_cancelled () == false) {
- map_embed.champlain_view.go_to (point.latitude, point.longitude);
- }
- return GLib.Source.REMOVE;
- });
- }
-
- search_entry.has_focus = true;
- } catch (Error error) {
- debug (error.message);
- }
- }
-
- private async void discover_current_location () {
- if (search_cancellable != null) {
- search_cancellable.cancel ();
- }
- search_cancellable = new GLib.Cancellable ();
-
- try {
- var simple = yield new GClue.Simple ("io.elementary.tasks", GClue.AccuracyLevel.CITY, null);
-
- point.latitude = simple.location.latitude;
- point.longitude = simple.location.longitude;
-
- Idle.add (() => {
- if (search_cancellable.is_cancelled () == false) {
- map_embed.champlain_view.go_to (point.latitude, point.longitude);
- }
- return GLib.Source.REMOVE;
- });
-
- } catch (Error e) {
- warning ("Failed to connect to GeoClue2 service: %s", e.message);
- // Fallback to timezone location
- search_location.begin (ECal.util_get_system_timezone_location ());
- }
- }
-
- private class Marker : Champlain.Marker {
- public Marker () {
- try {
- weak Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
- var pixbuf = icon_theme.load_icon ("location-marker", 32, Gtk.IconLookupFlags.GENERIC_FALLBACK);
- Clutter.Image image = new Clutter.Image ();
- image.set_data (pixbuf.get_pixels (),
- pixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
- pixbuf.width,
- pixbuf.height,
- pixbuf.rowstride);
- content = image;
- set_size (pixbuf.width, pixbuf.height);
- translation_x = -pixbuf.width / 2;
- translation_y = -pixbuf.height;
- } catch (Error e) {
- critical (e.message);
- }
- }
- }
+ // private void on_popover_show () {
+ // search_entry.text = (value == null ? "" : value.postal_address);
+
+ // if (search_entry.text != null && search_entry.text.strip ().length > 0) {
+ // search_location.begin (search_entry.text);
+ // } else {
+ // // Use geoclue to find approximate location
+ // discover_current_location.begin ();
+ // }
+ // }
+
+ // private void on_value_changed () {
+ // if (value == null) {
+ // return;
+ // }
+
+ // var value_has_postal_address = value.postal_address != null && value.postal_address.strip ().length > 0;
+ // if (value_has_postal_address && search_entry.text != value.postal_address) {
+ // search_entry.text = value.postal_address;
+ // }
+
+ // switch (value.proximity) {
+ // case Tasks.LocationProximity.ARRIVE:
+ // if (location_mode.selected != 0) {
+ // location_mode.selected = 0;
+ // }
+ // break;
+
+ // default:
+ // if (location_mode.selected != 1) {
+ // location_mode.selected = 1;
+ // }
+ // break;
+ // }
+
+ // bool need_relocation = true;
+ // if (value.latitude >= Champlain.MIN_LATITUDE && value.longitude >= Champlain.MIN_LONGITUDE &&
+ // value.latitude <= Champlain.MAX_LATITUDE && value.longitude <= Champlain.MAX_LONGITUDE) {
+
+ // point.latitude = value.latitude;
+ // point.longitude = value.longitude;
+
+ // need_relocation = (value.latitude == 0 && value.longitude == 0);
+ // }
+
+ // if (need_relocation == true) {
+ // if (value_has_postal_address) {
+ // search_location.begin (value.postal_address);
+ // } else {
+ // // Use geoclue to find approximate location
+ // discover_current_location.begin ();
+ // }
+ // }
+ // }
+
+ // private void on_search_entry_activate () {
+ // value = Tasks.Location () {
+ // postal_address = search_entry.text,
+ // display_name = search_entry.text,
+ // longitude = 0,
+ // latitude = 0,
+ // accuracy = (value == null ? Geocode.LocationAccuracy.UNKNOWN : value.accuracy),
+ // proximity = (value == null ? Tasks.LocationProximity.DEPART : value.proximity)
+ // };
+ // }
+
+ // private void on_location_mode_changed () {
+ // var proximity = (value == null ? Tasks.LocationProximity.DEPART : value.proximity);
+
+ // switch (location_mode.selected) {
+ // case 0: proximity = Tasks.LocationProximity.ARRIVE; break;
+ // case 1: proximity = Tasks.LocationProximity.DEPART; break;
+ // default: break;
+ // }
+
+ // value = Tasks.Location () {
+ // postal_address = (value == null ? search_entry.text : value.postal_address),
+ // display_name = (value == null ? search_entry.text : value.display_name),
+ // longitude = (value == null ? 0 : value.longitude),
+ // latitude = (value == null ? 0 : value.latitude),
+ // accuracy = (value == null ? Geocode.LocationAccuracy.UNKNOWN : value.accuracy),
+ // proximity = proximity
+ // };
+ // }
+
+ // private async void search_location (string location) {
+ // if (search_cancellable != null) {
+ // search_cancellable.cancel ();
+ // }
+ // search_cancellable = new GLib.Cancellable ();
+
+ // var forward = new Geocode.Forward.for_string (location);
+ // try {
+ // forward.set_answer_count (1);
+ // var places = yield forward.search_async (search_cancellable);
+ // foreach (var place in places) {
+ // point.latitude = place.location.latitude;
+ // point.longitude = place.location.longitude;
+
+ // if (value != null) {
+ // value.latitude = place.location.latitude;
+ // value.longitude = place.location.longitude;
+ // }
+
+ // Idle.add (() => {
+ // if (search_cancellable.is_cancelled () == false) {
+ // map_embed.champlain_view.go_to (point.latitude, point.longitude);
+ // }
+ // return GLib.Source.REMOVE;
+ // });
+ // }
+
+ // search_entry.has_focus = true;
+ // } catch (Error error) {
+ // debug (error.message);
+ // }
+ // }
+
+ // private async void discover_current_location () {
+ // if (search_cancellable != null) {
+ // search_cancellable.cancel ();
+ // }
+ // search_cancellable = new GLib.Cancellable ();
+
+ // try {
+ // var simple = yield new GClue.Simple ("io.elementary.tasks", GClue.AccuracyLevel.CITY, null);
+
+ // point.latitude = simple.location.latitude;
+ // point.longitude = simple.location.longitude;
+
+ // Idle.add (() => {
+ // if (search_cancellable.is_cancelled () == false) {
+ // map_embed.champlain_view.go_to (point.latitude, point.longitude);
+ // }
+ // return GLib.Source.REMOVE;
+ // });
+
+ // } catch (Error e) {
+ // warning ("Failed to connect to GeoClue2 service: %s", e.message);
+ // // Fallback to timezone location
+ // search_location.begin (ECal.util_get_system_timezone_location ());
+ // }
+ // }
+
+ // private class Marker : Champlain.Marker {
+ // public Marker () {
+ // try {
+ // weak Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
+ // var pixbuf = icon_theme.load_icon ("location-marker", 32, Gtk.IconLookupFlags.GENERIC_FALLBACK);
+ // Clutter.Image image = new Clutter.Image ();
+ // image.set_data (pixbuf.get_pixels (),
+ // pixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
+ // pixbuf.width,
+ // pixbuf.height,
+ // pixbuf.rowstride);
+ // content = image;
+ // set_size (pixbuf.width, pixbuf.height);
+ // translation_x = -pixbuf.width / 2;
+ // translation_y = -pixbuf.height;
+ // } catch (Error e) {
+ // critical (e.message);
+ // }
+ // }
+ // }
}
diff --git a/src/Widgets/ListSettingsPopover.vala b/src/Widgets/ListSettingsPopover.vala
index f7e62e894..5063e2532 100644
--- a/src/Widgets/ListSettingsPopover.vala
+++ b/src/Widgets/ListSettingsPopover.vala
@@ -4,79 +4,107 @@
*/
public class Tasks.Widgets.ListSettingsPopover : Gtk.Popover {
- public E.Source source { get; set; }
-
- private Gtk.RadioButton color_button_red;
- private Gtk.RadioButton color_button_orange;
- private Gtk.RadioButton color_button_yellow;
- private Gtk.RadioButton color_button_green;
- private Gtk.RadioButton color_button_mint;
- private Gtk.RadioButton color_button_blue;
- private Gtk.RadioButton color_button_purple;
- private Gtk.RadioButton color_button_pink;
- private Gtk.RadioButton color_button_brown;
- private Gtk.RadioButton color_button_slate;
- private Gtk.RadioButton color_button_none;
+ public E.Source source { get; construct set; }
+
+ private Gtk.CheckButton color_button_red;
+ private Gtk.CheckButton color_button_orange;
+ private Gtk.CheckButton color_button_yellow;
+ private Gtk.CheckButton color_button_green;
+ private Gtk.CheckButton color_button_mint;
+ private Gtk.CheckButton color_button_blue;
+ private Gtk.CheckButton color_button_purple;
+ private Gtk.CheckButton color_button_pink;
+ private Gtk.CheckButton color_button_brown;
+ private Gtk.CheckButton color_button_slate;
+ private Gtk.CheckButton color_button_none;
+
+ public ListSettingsPopover (E.Source source) {
+ Object (source: source);
+ }
construct {
- color_button_blue = new Gtk.RadioButton (null);
- color_button_blue.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_blue.get_style_context ().add_class ("blue");
+ autohide = true;
- color_button_mint = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_mint.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_mint.get_style_context ().add_class ("mint");
+ color_button_blue = new Gtk.CheckButton ();
+ color_button_blue.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_blue.add_css_class ("blue");
- color_button_green = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_green.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_green.get_style_context ().add_class ("green");
+ color_button_mint = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_mint.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_mint.add_css_class ("mint");
- color_button_yellow = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_yellow.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_yellow.get_style_context ().add_class ("yellow");
+ color_button_green = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_green.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_green.add_css_class ("green");
- color_button_orange = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_orange.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_orange.get_style_context ().add_class ("orange");
- color_button_red = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_red.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_red.get_style_context ().add_class ("red");
+ color_button_yellow = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_yellow.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_yellow.add_css_class ("yellow");
- color_button_pink = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_pink.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_pink.get_style_context ().add_class ("pink");
+ color_button_orange = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_orange.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_orange.add_css_class ("orange");
- color_button_purple = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_purple.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_purple.get_style_context ().add_class ("purple");
+ color_button_red = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_red.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_red.add_css_class ("red");
- color_button_brown = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_brown.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_brown.get_style_context ().add_class ("brown");
+ color_button_pink = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_pink.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_pink.add_css_class ("pink");
- color_button_slate = new Gtk.RadioButton.from_widget (color_button_blue);
- color_button_slate.get_style_context ().add_class (Granite.STYLE_CLASS_COLOR_BUTTON);
- color_button_slate.get_style_context ().add_class ("slate");
+ color_button_purple = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_purple.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_purple.add_css_class ("purple");
- color_button_none = new Gtk.RadioButton.from_widget (color_button_blue);
+ color_button_brown = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_brown.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_brown.add_css_class ("brown");
+
+ color_button_slate = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
+ color_button_slate.add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON);
+ color_button_slate.add_css_class ("slate");
+
+ // FIXME: this CheckButton is unused
+ color_button_none = new Gtk.CheckButton () {
+ group = color_button_blue
+ };
var color_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6) {
margin_top = 12,
margin_bottom = 12,
margin_start = 12,
- margin_end = 12
+ margin_end = 12,
};
- color_box.add (color_button_blue);
- color_box.add (color_button_mint);
- color_box.add (color_button_green);
- color_box.add (color_button_yellow);
- color_box.add (color_button_orange);
- color_box.add (color_button_red);
- color_box.add (color_button_pink);
- color_box.add (color_button_purple);
- color_box.add (color_button_brown);
- color_box.add (color_button_slate);
+ color_box.append (color_button_blue);
+ color_box.append (color_button_mint);
+ color_box.append (color_button_green);
+ color_box.append (color_button_yellow);
+ color_box.append (color_button_orange);
+ color_box.append (color_button_red);
+ color_box.append (color_button_pink);
+ color_box.append (color_button_purple);
+ color_box.append (color_button_brown);
+ color_box.append (color_button_slate);
var show_completed_button = new Granite.SwitchModelButton (_("Show Completed")) {
margin_top = 3
@@ -87,23 +115,20 @@ public class Tasks.Widgets.ListSettingsPopover : Gtk.Popover {
MainWindow.ACTION_PREFIX + MainWindow.ACTION_DELETE_SELECTED_LIST
);
- var delete_list_menuitem = new Gtk.ModelButton ();
- delete_list_menuitem.action_name = delete_list_accel_label.action_name;
- delete_list_menuitem.get_child ().destroy ();
- delete_list_menuitem.add (delete_list_accel_label);
- delete_list_menuitem.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ var delete_list_menuitem = new Widgets.PopoverButton ();
+ delete_list_menuitem.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ delete_list_menuitem.append (delete_list_accel_label);
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) {
margin_top = 3,
margin_bottom = 3
};
- box.add (color_box);
- box.add (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
- box.add (show_completed_button);
- box.add (delete_list_menuitem);
- box.show_all ();
+ box.append (color_box);
+ box.append (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
+ box.append (show_completed_button);
+ box.append (delete_list_menuitem);
- add (box);
+ child = box;
color_button_red.toggled.connect (() => {
if (color_button_red.active) {
@@ -165,6 +190,13 @@ public class Tasks.Widgets.ListSettingsPopover : Gtk.Popover {
}
});
+ delete_list_menuitem.clicked.connect (() => {
+ popdown ();
+
+ unowned var main_window = (Gtk.ApplicationWindow) get_root ();
+ ((SimpleAction) main_window.lookup_action (MainWindow.ACTION_DELETE_SELECTED_LIST)).activate (null);
+ });
+
notify["source"].connect (() => {
select_task_list_color (get_task_list_color (source));
});
@@ -214,7 +246,7 @@ public class Tasks.Widgets.ListSettingsPopover : Gtk.Popover {
private string get_task_list_color (E.Source source) {
if (source.has_extension (E.SOURCE_EXTENSION_TASK_LIST)) {
- var task_list = (E.SourceTaskList) source.get_extension (E.SOURCE_EXTENSION_TASK_LIST);
+ unowned var task_list = (E.SourceTaskList) source.get_extension (E.SOURCE_EXTENSION_TASK_LIST);
return task_list.dup_color ();
}
return "";
@@ -244,7 +276,9 @@ public class Tasks.Widgets.ListSettingsPopover : Gtk.Popover {
Gtk.ButtonsType.CLOSE
);
error_dialog.show_error_details (e.message);
- error_dialog.run ();
- error_dialog.destroy ();
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
+ error_dialog.destroy ();
+ });
}
}
diff --git a/src/Widgets/PopoverButton.vala b/src/Widgets/PopoverButton.vala
new file mode 100644
index 000000000..379bbcef2
--- /dev/null
+++ b/src/Widgets/PopoverButton.vala
@@ -0,0 +1,33 @@
+/*
+* Copyright 2023 elementary, Inc. (https://elementary.io)
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or (at your option) any later version.
+*
+* This program 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with this program; if not, write to the
+* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301 USA
+*
+*/
+
+class Tasks.Widgets.PopoverButton : Gtk.Box {
+ public signal void clicked ();
+
+ construct {
+ orientation = HORIZONTAL;
+ add_css_class (Granite.STYLE_CLASS_MENUITEM);
+
+ var gesture_click = new Gtk.GestureClick ();
+ add_controller (gesture_click);
+
+ gesture_click.released.connect (() => clicked ());
+ }
+}
diff --git a/src/Widgets/ScheduledRow.vala b/src/Widgets/ScheduledRow.vala
index c4059c707..645dc179f 100644
--- a/src/Widgets/ScheduledRow.vala
+++ b/src/Widgets/ScheduledRow.vala
@@ -6,7 +6,7 @@
public class Tasks.Widgets.ScheduledRow : Gtk.ListBoxRow {
construct {
- var icon = new Gtk.Image.from_icon_name ("appointment", Gtk.IconSize.MENU);
+ var icon = new Gtk.Image.from_icon_name ("appointment");
var display_name_label = new Gtk.Label (_("Scheduled")) {
ellipsize = Pango.EllipsizeMode.MIDDLE,
@@ -19,9 +19,9 @@ public class Tasks.Widgets.ScheduledRow : Gtk.ListBoxRow {
margin_start = 12,
margin_end = 6
};
- box.add (icon);
- box.add (display_name_label);
+ box.append (icon);
+ box.append (display_name_label);
- add (box);
+ child = box;
}
}
diff --git a/src/Widgets/ScheduledTaskListBox.vala b/src/Widgets/ScheduledTaskListBox.vala
index 634ed05f7..b2bd0d47e 100644
--- a/src/Widgets/ScheduledTaskListBox.vala
+++ b/src/Widgets/ScheduledTaskListBox.vala
@@ -33,10 +33,19 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
}
private void remove_view (E.Source source) {
- foreach (unowned Gtk.Widget child in task_list.get_children ()) {
+ Gtk.Widget[] children_for_removal = {};
+ unowned var child = get_first_child ();
+ while (child != null) {
if (child is Tasks.Widgets.TaskRow && ((Tasks.Widgets.TaskRow) child).source == source) {
- child.destroy ();
+ children_for_removal += child;
}
+
+ child = child.get_next_sibling ();
+ }
+
+ for (int i = 0; i < children_for_removal.length; i++) {
+ remove (children_for_removal[i]);
+ children_for_removal[i].destroy ();
}
lock (views) {
@@ -64,13 +73,13 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
margin_bottom = 24,
xalign = 0
};
- scheduled_title.get_style_context ().add_class (Granite.STYLE_CLASS_H1_LABEL);
- scheduled_title.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT);
+
+ scheduled_title.add_css_class (Granite.STYLE_CLASS_H1_LABEL);
+ scheduled_title.add_css_class (Granite.STYLE_CLASS_ACCENT);
var placeholder = new Gtk.Label (_("No Tasks"));
- placeholder.show ();
- placeholder.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
- placeholder.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL);
+ placeholder.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
+ placeholder.add_css_class (Granite.STYLE_CLASS_H2_LABEL);
task_list = new Gtk.ListBox () {
selection_mode = Gtk.SelectionMode.MULTIPLE,
@@ -79,19 +88,18 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
task_list.set_placeholder (placeholder);
task_list.set_sort_func (sort_function);
task_list.set_header_func (header_function);
- task_list.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND);
+ task_list.add_css_class (Granite.STYLE_CLASS_BACKGROUND);
- var scrolled_window = new Gtk.ScrolledWindow (null, null) {
+ var scrolled_window = new Gtk.ScrolledWindow () {
hexpand = true,
vexpand = true,
- hscrollbar_policy = Gtk.PolicyType.NEVER
+ hscrollbar_policy = Gtk.PolicyType.NEVER,
+ child = task_list
};
- scrolled_window.add (task_list);
orientation = Gtk.Orientation.VERTICAL;
- add (scheduled_title);
- add (scrolled_window);
- show_all ();
+ append (scheduled_title);
+ append (scrolled_window);
task_list.row_activated.connect (on_row_activated);
@@ -139,9 +147,9 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
var task_row = (Tasks.Widgets.TaskRow) row;
task_row.reveal_child_request (true);
- unowned GLib.ActionMap win_action_map = (GLib.ActionMap) get_action_group (MainWindow.ACTION_GROUP_PREFIX);
- if (win_action_map != null) {
- ((SimpleAction) win_action_map.lookup_action (MainWindow.ACTION_DELETE_SELECTED_LIST)).set_enabled (false);
+ unowned var main_window = (MainWindow) get_root ();
+ if (main_window != null) {
+ ((SimpleAction) main_window.lookup_action (MainWindow.ACTION_DELETE_SELECTED_LIST)).set_enabled (false);
}
}
@@ -179,10 +187,11 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
}
}
- var due_date_time = Util.ical_to_date_time_local (comp.get_due ());
- var header_label = new Granite.HeaderLabel (Tasks.Util.get_relative_date (due_date_time));
- header_label.ellipsize = Pango.EllipsizeMode.MIDDLE;
- header_label.margin_start = 6;
+ var due_date_time = Tasks.Util.ical_to_date_time_local (comp.get_due ());
+ var header_label = new Granite.HeaderLabel (Tasks.Util.get_relative_date (due_date_time)) {
+ margin_start = 6
+ // ellipsize = Pango.EllipsizeMode.MIDDLE
+ };
row.set_header (header_label);
}
@@ -194,77 +203,70 @@ public class Tasks.Widgets.ScheduledTaskListBox : Gtk.Box {
task_row.task_completed.connect ((task) => {
Tasks.Application.model.complete_task.begin (source, task, (obj, res) => {
- GLib.Idle.add (() => {
- try {
- Tasks.Application.model.complete_task.end (res);
- } catch (Error e) {
- var error_dialog = new Granite.MessageDialog (
- _("Completing task failed"),
- _("The task registry may be unavailable or unable to be written to."),
- new ThemedIcon ("dialog-error"),
- Gtk.ButtonsType.CLOSE
- );
- error_dialog.show_error_details (e.message);
- error_dialog.run ();
+ try {
+ Tasks.Application.model.complete_task.end (res);
+ } catch (Error e) {
+ var error_dialog = new Granite.MessageDialog (
+ _("Completing task failed"),
+ _("The task registry may be unavailable or unable to be written to."),
+ new ThemedIcon ("dialog-error"),
+ Gtk.ButtonsType.CLOSE
+ );
+ error_dialog.show_error_details (e.message);
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
error_dialog.destroy ();
- }
-
- return GLib.Source.REMOVE;
- });
+ });
+ }
});
});
task_row.task_changed.connect ((task) => {
Tasks.Application.model.update_task.begin (source, task, ECal.ObjModType.THIS_AND_FUTURE, (obj, res) => {
- GLib.Idle.add (() => {
- try {
- Tasks.Application.model.update_task.end (res);
- } catch (Error e) {
- var error_dialog = new Granite.MessageDialog (
- _("Updating task failed"),
- _("The task registry may be unavailable or unable to be written to."),
- new ThemedIcon ("dialog-error"),
- Gtk.ButtonsType.CLOSE
- );
- error_dialog.show_error_details (e.message);
- error_dialog.run ();
+ try {
+ Tasks.Application.model.update_task.end (res);
+ } catch (Error e) {
+ var error_dialog = new Granite.MessageDialog (
+ _("Updating task failed"),
+ _("The task registry may be unavailable or unable to be written to."),
+ new ThemedIcon ("dialog-error"),
+ Gtk.ButtonsType.CLOSE
+ );
+ error_dialog.show_error_details (e.message);
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
error_dialog.destroy ();
- }
-
- return GLib.Source.REMOVE;
- });
+ });
+ }
});
});
task_row.task_removed.connect ((task) => {
Tasks.Application.model.remove_task.begin (source, task, ECal.ObjModType.ALL, (obj, res) => {
- GLib.Idle.add (() => {
- try {
- Tasks.Application.model.remove_task.end (res);
- } catch (Error e) {
- var error_dialog = new Granite.MessageDialog (
- _("Removing task failed"),
- _("The task registry may be unavailable or unable to be written to."),
- new ThemedIcon ("dialog-error"),
- Gtk.ButtonsType.CLOSE
- );
- error_dialog.show_error_details (e.message);
- error_dialog.run ();
+ try {
+ Tasks.Application.model.remove_task.end (res);
+ } catch (Error e) {
+ var error_dialog = new Granite.MessageDialog (
+ _("Removing task failed"),
+ _("The task registry may be unavailable or unable to be written to."),
+ new ThemedIcon ("dialog-error"),
+ Gtk.ButtonsType.CLOSE
+ );
+ error_dialog.show_error_details (e.message);
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
error_dialog.destroy ();
- }
-
- return GLib.Source.REMOVE;
- });
+ });
+ }
});
});
- task_list.add (task_row);
+ task_list.append (task_row);
return true;
});
Idle.add (() => {
task_list.invalidate_sort ();
- task_list.show_all ();
return Source.REMOVE;
});
diff --git a/src/Widgets/SourceRow.vala b/src/Widgets/SourceRow.vala
index 4887447a1..fe3f276c4 100644
--- a/src/Widgets/SourceRow.vala
+++ b/src/Widgets/SourceRow.vala
@@ -20,7 +20,7 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
source_color = new Gtk.Grid () {
valign = Gtk.Align.CENTER
};
- source_color.get_style_context ().add_class ("source-color");
+ source_color.add_css_class ("source-color");
display_name_label = new Gtk.Label (source.display_name) {
halign = Gtk.Align.START,
@@ -33,7 +33,7 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
};
var spinner = new Gtk.Spinner () {
- active = true,
+ spinning = true,
tooltip_text = _("Connecting…")
};
@@ -45,16 +45,16 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
margin_start = 12,
margin_end = 6
};
- box.add (source_color);
- box.add (display_name_label);
- box.add (status_stack);
+ box.append (source_color);
+ box.append (display_name_label);
+ box.append (status_stack);
revealer = new Gtk.Revealer () {
- reveal_child = true
+ reveal_child = true,
+ child = box
};
- revealer.add (box);
- add (revealer);
+ child = revealer;
build_drag_and_drop ();
@@ -62,31 +62,36 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
}
private void build_drag_and_drop () {
- Gtk.drag_dest_set (this, Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.MOTION, Application.DRAG_AND_DROP_TASK_DATA, Gdk.DragAction.MOVE);
+ var drop_target = new Gtk.DropTarget (typeof (string), Gdk.DragAction.COPY);
+ add_controller (drop_target);
+
+ drop_target.accept.connect (on_drop_accept);
+ drop_target.drop.connect (on_drag_drop);
+ drop_target.enter.connect (on_drag_enter);
+ drop_target.leave.connect (on_drag_leave);
- drag_motion.connect (on_drag_motion);
- drag_drop.connect (on_drag_drop);
- drag_data_received.connect (on_drag_data_received);
- drag_leave.connect (on_drag_leave);
}
- private bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) {
- if (!get_style_context ().has_class ("drop-hover")) {
- get_style_context ().add_class ("drop-hover");
- }
+ private bool on_drop_accept (Gdk.Drop drop) {
return true;
}
- private void on_drag_leave (Gdk.DragContext context, uint time_) {
- get_style_context ().remove_class ("drop-hover");
+ private Gdk.DragAction on_drag_enter (double x, double y) {
+ if (!has_css_class ("drop-hover")) {
+ add_css_class ("drop-hover");
+ }
+
+ return Gdk.DragAction.COPY;
+ }
+
+ private void on_drag_leave () {
+ remove_css_class ("drop-hover");
}
private Gee.HashMultiMap received_drag_data;
- private async bool on_drag_drop_move_tasks () throws Error {
+ private async void on_drag_drop_move_tasks () throws Error {
E.SourceRegistry registry = yield Application.model.get_registry ();
- var move_successful = true;
-
var source_uids = received_drag_data.get_keys ();
foreach (var source_uid in source_uids) {
var src_source = registry.ref_source (source_uid);
@@ -94,28 +99,22 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
var component_uids = received_drag_data.get (source_uid);
foreach (var component_uid in component_uids) {
if (!yield Application.model.move_task (src_source, source, component_uid)) {
- move_successful = false;
+ warning ("Couldn't move task %s to %s", component_uid, source.uid);
}
}
}
- return move_successful;
}
- private bool on_drag_drop (Gdk.DragContext context, int x, int y, uint time) {
- var target = Gtk.drag_dest_find_target (this, context, null);
- if (target != Gdk.Atom.NONE) {
- Gtk.drag_get_data (this, context, target, time);
- }
+ private bool on_drag_drop (GLib.Value value, double x, double y) {
+ parse_data ((string) value);
var drop_successful = false;
- var move_successful = false;
if (received_drag_data != null && received_drag_data.size > 0) {
drop_successful = true;
on_drag_drop_move_tasks.begin ((obj, res) => {
try {
- move_successful = on_drag_drop_move_tasks.end (res);
-
+ on_drag_drop_move_tasks.end (res);
} catch (Error e) {
var error_dialog = new Granite.MessageDialog (
_("Moving task failed"),
@@ -124,11 +123,10 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
Gtk.ButtonsType.CLOSE
);
error_dialog.show_error_details (e.message);
- error_dialog.run ();
- error_dialog.destroy ();
-
- } finally {
- Gtk.drag_finish (context, drop_successful, move_successful, time);
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
+ error_dialog.destroy ();
+ });
}
});
}
@@ -136,34 +134,31 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
return drop_successful;
}
- private void on_drag_data_received (Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time) {
+ private void parse_data (string uri) {
received_drag_data = new Gee.HashMultiMap ();
var uri_scheme = "task://";
- var uris = selection_data.get_uris ();
- foreach (var uri in uris) {
- string? source_uid = null;
- string? component_uid = null;
+ string? source_uid = null;
+ string? component_uid = null;
- if (uri.has_prefix (uri_scheme)) {
- var uri_parts = uri.substring (uri_scheme.length).split ("/");
+ if (uri.has_prefix (uri_scheme)) {
+ var uri_parts = uri.substring (uri_scheme.length).split ("/");
- if (uri_parts.length == 2) {
- source_uid = uri_parts[0];
- component_uid = uri_parts[1];
- }
+ if (uri_parts.length == 2) {
+ source_uid = uri_parts[0];
+ component_uid = uri_parts[1];
}
+ }
- if (source_uid == null || component_uid == null) {
- warning ("Can't handle drop data: Unexpected uri format: %s", uri);
+ if (source_uid == null || component_uid == null) {
+ warning ("Can't handle drop data: Unexpected uri format: %s", uri);
- } else if (source_uid == source.uid) {
- debug ("Dropped task onto the same list, so we have nothing to do.");
+ } else if (source_uid == source.uid) {
+ debug ("Dropped task onto the same list, so we have nothing to do.");
- } else {
- received_drag_data.set (source_uid, component_uid);
- }
+ } else {
+ received_drag_data.set (source_uid, component_uid);
}
}
@@ -201,7 +196,9 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
public void remove_request () {
revealer.reveal_child = false;
GLib.Timeout.add (revealer.transition_duration, () => {
+ ((Gtk.ListBox) parent).remove (this);
destroy ();
+
return GLib.Source.REMOVE;
});
}
diff --git a/src/Widgets/TaskListGrid.vala b/src/Widgets/TaskListGrid.vala
index 22ec3ed10..522d7a6ac 100644
--- a/src/Widgets/TaskListGrid.vala
+++ b/src/Widgets/TaskListGrid.vala
@@ -28,27 +28,27 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
editable_title = new EditableLabel () {
margin_start = 24
};
- editable_title.get_style_context ().add_class (Granite.STYLE_CLASS_H1_LABEL);
- editable_title.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT);
+ editable_title.add_css_class (Granite.STYLE_CLASS_H1_LABEL);
+ editable_title.add_css_class (Granite.STYLE_CLASS_ACCENT);
- var list_settings_popover = new Tasks.Widgets.ListSettingsPopover ();
+ var list_settings_popover = new Tasks.Widgets.ListSettingsPopover (source);
var settings_button = new Gtk.MenuButton () {
halign = END,
- image = new Gtk.Image.from_icon_name ("view-more-symbolic", Gtk.IconSize.MENU),
+ icon_name = "view-more-symbolic",
margin_end = 24,
popover = list_settings_popover,
tooltip_text = _("Edit Name and Appearance"),
valign = CENTER
};
- settings_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ settings_button.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
add_task_list = new Gtk.ListBox () {
margin_top = 24,
selection_mode = SINGLE,
activate_on_single_click = true
};
- add_task_list.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND);
+ add_task_list.add_css_class (Granite.STYLE_CLASS_BACKGROUND);
var add_task_row = new Tasks.Widgets.TaskRow.for_source (source);
add_task_row.unselect.connect (on_row_unselect);
@@ -74,12 +74,11 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
});
});
});
- add_task_list.add (add_task_row);
+ add_task_list.append (add_task_row);
var placeholder = new Gtk.Label (_("No Tasks"));
- placeholder.show ();
- placeholder.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
- placeholder.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL);
+ placeholder.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
+ placeholder.add_css_class (Granite.STYLE_CLASS_H2_LABEL);
task_list = new Gtk.ListBox () {
selection_mode = MULTIPLE,
@@ -87,9 +86,9 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
};
task_list.set_placeholder (placeholder);
task_list.set_sort_func (sort_function);
- task_list.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND);
+ task_list.add_css_class (Granite.STYLE_CLASS_BACKGROUND);
- var scrolled_window = new Gtk.ScrolledWindow (null, null) {
+ var scrolled_window = new Gtk.ScrolledWindow () {
child = task_list,
hexpand = true,
vexpand = true,
@@ -117,7 +116,7 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
} else {
/*
* We can't immediate disable the action once the popover is closed,
- * because this would lead to the action not beeing executed in case
+ * because this would lead to the action not being executed in case
* the popover was closed because the user clicked on the action.
* Therefore we wait a tiny bit using GLib.Idle to allow the action to
* be executed if needed.
@@ -142,29 +141,25 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
editable_title.changed.connect (() => {
Application.model.update_task_list_display_name.begin (source, editable_title.text, (obj, res) => {
- GLib.Idle.add (() => {
- try {
- Application.model.update_task_list_display_name.end (res);
- } catch (Error e) {
- editable_title.text = source.display_name;
-
- var error_dialog = new Granite.MessageDialog (
- _("Renaming task list failed"),
- _("The task list registry may be unavailable or unable to be written to."),
- new ThemedIcon ("dialog-error"),
- Gtk.ButtonsType.CLOSE
- );
- error_dialog.show_error_details (e.message);
- error_dialog.run ();
+ try {
+ Application.model.update_task_list_display_name.end (res);
+ } catch (Error e) {
+ editable_title.text = source.display_name;
+
+ var error_dialog = new Granite.MessageDialog (
+ _("Renaming task list failed"),
+ _("The task list registry may be unavailable or unable to be written to."),
+ new ThemedIcon ("dialog-error"),
+ Gtk.ButtonsType.CLOSE
+ );
+ error_dialog.show_error_details (e.message);
+ error_dialog.present ();
+ error_dialog.response.connect (() => {
error_dialog.destroy ();
- }
-
- return GLib.Source.REMOVE;
- });
+ });
+ }
});
});
-
- show_all ();
}
private void on_show_completed_changed (bool show_completed) {
@@ -176,9 +171,7 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
}
private void set_view_for_query (string query) {
- while (task_list.get_row_at_index (0) != null) {
- task_list.remove (task_list.get_row_at_index (0));
- }
+ task_list.remove_all ();
if (view != null) {
Application.model.destroy_task_list_view (view);
@@ -210,7 +203,7 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
}
if (add_task_list.get_selected_rows ().length () == 0 && task_list.get_selected_rows ().length () == 0) {
- unowned var main_window = (Gtk.ApplicationWindow) get_toplevel ();
+ unowned var main_window = (Gtk.ApplicationWindow) ((Gtk.Application) GLib.Application.get_default ()).active_window;
((SimpleAction) main_window.lookup_action (MainWindow.ACTION_DELETE_SELECTED_LIST)).set_enabled (true);
}
}
@@ -220,12 +213,15 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
Tasks.Application.set_task_color (source, editable_title);
- task_list.@foreach ((row) => {
- if (row is Tasks.Widgets.TaskRow) {
- var task_row = (row as Tasks.Widgets.TaskRow);
+ unowned var child = task_list.get_first_child ();
+ while (child != null) {
+ if (child is Tasks.Widgets.TaskRow) {
+ unowned var task_row = (child as Tasks.Widgets.TaskRow);
task_row.update_request ();
}
- });
+
+ child = child.get_next_sibling ();
+ }
}
[CCode (instance_pos = -1)]
@@ -336,14 +332,13 @@ public class Tasks.Widgets.TaskListGrid : Gtk.Grid {
});
});
});
- task_list.add (task_row);
+ task_list.append (task_row);
return true;
});
Idle.add (() => {
task_list.invalidate_sort ();
- task_list.show_all ();
return Source.REMOVE;
});
diff --git a/src/Widgets/TaskRow.vala b/src/Widgets/TaskRow.vala
index a40f51024..3ae6b8248 100644
--- a/src/Widgets/TaskRow.vala
+++ b/src/Widgets/TaskRow.vala
@@ -23,7 +23,6 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
private Tasks.Widgets.EntryPopover.Location location_popover;
private Gtk.Revealer location_popover_revealer;
- private Gtk.EventBox event_box;
private Gtk.Stack state_stack;
private Gtk.Image icon;
private Gtk.CheckButton check;
@@ -35,7 +34,7 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
private Gtk.Revealer task_form_revealer;
private Gtk.TextBuffer description_textbuffer;
- private Gtk.EventControllerKey key_controller;
+ private Gtk.DragSource drag_source;
private TaskRow (ECal.Component task, E.Source source) {
Object (task: task, source: source);
@@ -53,7 +52,6 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
}
construct {
- can_focus = false;
created = calcomponent_created (task);
// GTasks tasks only have date on due time, so only show the date
@@ -66,22 +64,22 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
warning ("unable to get the registry, assuming task is not from gtask");
}
- icon = new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.MENU);
- icon.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ icon = new Gtk.Image.from_icon_name ("list-add-symbolic");
+ icon.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
check = new Gtk.CheckButton () {
valign = Gtk.Align.CENTER
};
+ check.add_css_class ("task-row-check");
state_stack = new Gtk.Stack () {
transition_type = Gtk.StackTransitionType.CROSSFADE
};
- state_stack.add (icon);
- state_stack.add (check);
+ state_stack.add_child (icon);
+ state_stack.add_child (check);
summary_entry = new Gtk.Entry ();
-
- summary_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
+ summary_entry.add_css_class (Granite.STYLE_CLASS_FLAT);
due_datetime_popover = new Tasks.Widgets.EntryPopover.DateTime ();
@@ -97,13 +95,13 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
};
due_datetime_popover.value_format.connect ((value) => {
- due_datetime_popover.get_style_context ().remove_class ("error");
+ due_datetime_popover.remove_css_class ("error");
if (value == null) {
return null;
}
var today = new GLib.DateTime.now_local ();
if (today.compare (value) > 0 && !completed) {
- due_datetime_popover.get_style_context ().add_class ("error");
+ due_datetime_popover.add_css_class ("error");
}
if (is_gtask) {
@@ -180,7 +178,7 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
lines = 1,
ellipsize = Pango.EllipsizeMode.END
};
- description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ description_label.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
// Should not use a transition that varies the width else label aligning and ellipsizing is incorrect.
description_label_revealer = new Gtk.Revealer () {
@@ -190,9 +188,9 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
};
var task_box = new Gtk.Box (HORIZONTAL, 0);
- task_box.add (due_datetime_popover_revealer);
- task_box.add (location_popover_revealer);
- task_box.add (description_label_revealer);
+ task_box.append (due_datetime_popover_revealer);
+ task_box.append (location_popover_revealer);
+ task_box.append (description_label_revealer);
task_detail_revealer = new Gtk.Revealer () {
child = task_box,
@@ -220,28 +218,28 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
var cancel_button = new Gtk.Button.with_label (_("Cancel"));
var save_button = new Gtk.Button.with_label (created ? _("Save Changes") : _("Add Task"));
- save_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
+ save_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION);
var right_buttons_box = new Gtk.Box (HORIZONTAL, 6) {
hexpand = true,
halign = END,
homogeneous = true
};
- right_buttons_box.add (cancel_button);
- right_buttons_box.add (save_button);
+ right_buttons_box.append (cancel_button);
+ right_buttons_box.append (save_button);
var button_box = new Gtk.Box (HORIZONTAL, 6) {
margin_top = 12
};
- button_box.get_style_context ().add_class ("button-box");
- button_box.pack_end (right_buttons_box);
+ button_box.add_css_class ("button-box");
+ button_box.append (right_buttons_box);
var form_box = new Gtk.Box (VERTICAL, 12) {
margin_top = 6,
margin_bottom = 6
};
- form_box.add (description_frame);
- form_box.add (button_box);
+ form_box.append (description_frame);
+ form_box.append (button_box);
task_form_revealer = new Gtk.Revealer () {
child = form_box,
@@ -267,23 +265,12 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
transition_type = SLIDE_UP
};
- event_box = new Gtk.EventBox () {
- hexpand = true,
- vexpand = true,
- above_child = false
- };
- event_box.add_events (
- Gdk.EventMask.BUTTON_PRESS_MASK |
- Gdk.EventMask.BUTTON_RELEASE_MASK
- );
- event_box.add (revealer);
-
- child = event_box;
+ child = revealer;
margin_start = 12;
margin_end = 12;
- get_style_context ().add_class ("task");
- get_style_context ().add_class (Granite.STYLE_CLASS_ROUNDED);
+ add_css_class ("task");
+ add_css_class (Granite.STYLE_CLASS_ROUNDED);
if (created) {
check.show ();
@@ -292,9 +279,9 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
var delete_button = new Gtk.Button.with_label (_("Delete Task")) {
halign = START
};
- delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
+ delete_button.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION);
- button_box.pack_start (delete_button);
+ button_box.prepend (delete_button);
delete_button.clicked.connect (() => {
end_editing ();
@@ -305,7 +292,8 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
build_drag_and_drop ();
- key_controller = new Gtk.EventControllerKey (this);
+ var key_controller = new Gtk.EventControllerKey ();
+ add_controller (key_controller);
check.toggled.connect (() => {
if (task == null) {
@@ -321,7 +309,9 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
end_editing ();
});
- summary_entry.grab_focus.connect (() => {
+ var summary_entry_focus_controller = new Gtk.EventControllerFocus ();
+ summary_entry.add_controller (summary_entry_focus_controller);
+ summary_entry_focus_controller.enter.connect (() => {
activate ();
});
@@ -405,18 +395,20 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
task_details_reveal_request (!value);
if (value) {
- get_style_context ().add_class ("collapsed");
- get_style_context ().add_class (Granite.STYLE_CLASS_CARD);
+ add_css_class ("collapsed");
+ add_css_class (Granite.STYLE_CLASS_CARD);
} else {
- get_style_context ().remove_class (Granite.STYLE_CLASS_CARD);
- get_style_context ().remove_class ("collapsed");
+ remove_css_class (Granite.STYLE_CLASS_CARD);
+ remove_css_class ("collapsed");
}
}
public void update_request () {
if (!is_scheduled_view) {
- Tasks.Application.set_task_color (source, check);
+ // FIXME: check.get_first_child () is used because Gtk.StyleContext.add_provider works differently in Gtk4
+ // Also, it's deprecated now, so we need to use Gtk.StyleContext.add_provider_for_display
+ Tasks.Application.set_task_color (source, check.get_first_child ());
}
var default_due_datetime = new DateTime.now_local ().add_hours (1);
@@ -429,10 +421,10 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
completed = false;
check.active = completed;
summary_entry.text = "";
- summary_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_DIM_LABEL);
- summary_entry.get_style_context ().add_class ("add-task");
+ summary_entry.remove_css_class (Granite.STYLE_CLASS_DIM_LABEL);
+ summary_entry.add_css_class ("add-task");
task_detail_revealer.reveal_child = false;
- task_detail_revealer.get_style_context ().remove_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ task_detail_revealer.remove_css_class (Granite.STYLE_CLASS_DIM_LABEL);
due_datetime_popover_revealer.reveal_child = false;
location_popover_revealer.reveal_child = false;
@@ -454,14 +446,14 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
}
summary_entry.text = ical_task.get_summary () == null ? "" : ical_task.get_summary ();
- summary_entry.get_style_context ().remove_class ("add-task");
+ summary_entry.remove_css_class ("add-task");
if (completed) {
- summary_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
- task_detail_revealer.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ summary_entry.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
+ task_detail_revealer.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
} else {
- summary_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_DIM_LABEL);
- task_detail_revealer.get_style_context ().remove_class (Gtk.STYLE_CLASS_DIM_LABEL);
+ summary_entry.remove_css_class (Granite.STYLE_CLASS_DIM_LABEL);
+ task_detail_revealer.remove_css_class (Granite.STYLE_CLASS_DIM_LABEL);
}
if (ical_task.get_due ().is_null_time ()) {
@@ -538,45 +530,55 @@ public class Tasks.Widgets.TaskRow : Gtk.ListBoxRow {
if (!created || is_scheduled_view) {
return;
}
- Gtk.drag_source_set (event_box, Gdk.ModifierType.BUTTON1_MASK, Application.DRAG_AND_DROP_TASK_DATA, Gdk.DragAction.MOVE);
- event_box.drag_begin.connect (on_drag_begin);
- event_box.drag_data_get.connect (on_drag_data_get);
- event_box.drag_data_delete.connect (on_drag_data_delete);
+ drag_source = new Gtk.DragSource ();
+ add_controller (drag_source);
+
+ drag_source.prepare.connect (on_drag_prepare);
+ drag_source.drag_begin.connect (on_drag_begin);
+ drag_source.drag_cancel.connect (on_drag_cancel);
+ drag_source.drag_end.connect (on_drag_end);
}
- private void on_drag_begin (Gdk.DragContext context) {
- Gtk.Allocation alloc;
- get_allocation (out alloc);
+ private int drag_offset_x;
+ private int drag_offset_y;
+ private bool had_cards_class;
+ private bool is_canceled;
- var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, alloc.width, alloc.height);
- var cairo_context = new Cairo.Context (surface);
+ private Gdk.ContentProvider? on_drag_prepare (double x, double y) {
+ drag_offset_x = (int) x;
+ drag_offset_y = (int) y;
- var had_cards_class = get_style_context ().has_class (Granite.STYLE_CLASS_CARD);
+ return new Gdk.ContentProvider.for_value ("task://%s/%s".printf (source.uid, task.get_uid ()));
+ }
- get_style_context ().add_class ("drag-active");
- if (had_cards_class) {
- get_style_context ().remove_class (Granite.STYLE_CLASS_CARD);
- }
- draw_to_cairo_context (cairo_context);
- if (had_cards_class) {
- get_style_context ().add_class (Granite.STYLE_CLASS_CARD);
- }
- get_style_context ().remove_class ("drag-active");
+ private void on_drag_begin (Gdk.Drag drag) {
+ drag_source.set_icon (new Gtk.WidgetPaintable (this), drag_offset_x, drag_offset_y);
- int drag_icon_x, drag_icon_y;
- translate_coordinates (this, 0, 0, out drag_icon_x, out drag_icon_y);
- surface.set_device_offset (-drag_icon_x, -drag_icon_y);
+ had_cards_class = has_css_class (Granite.STYLE_CLASS_CARD);
+ is_canceled = false;
- Gtk.drag_set_icon_surface (context, surface);
+ add_css_class ("drag-active");
+ if (had_cards_class) {
+ remove_css_class (Granite.STYLE_CLASS_CARD);
+ }
}
- private void on_drag_data_get (Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) {
- var task_uri = "task://%s/%s".printf (source.uid, task.get_uid ());
- selection_data.set_uris ({ task_uri });
+ private bool on_drag_cancel (Gdk.Drag drag, Gdk.DragCancelReason reason) {
+ is_canceled = true;
+
+ return true;
}
- private void on_drag_data_delete (Gdk.DragContext context) {
- destroy ();
+ private void on_drag_end (Gdk.Drag drag, bool delete_data) {
+ if (is_canceled) {
+ remove_css_class ("drag-active");
+ if (had_cards_class) {
+ add_css_class (Granite.STYLE_CLASS_CARD);
+ }
+ } else {
+ ((Gtk.ListBox) parent).remove (this);
+ destroy ();
+ }
}
}