diff --git a/config.vala.in b/config.vala.in index 656cf0a05..b84a31e8d 100644 --- a/config.vala.in +++ b/config.vala.in @@ -6,4 +6,5 @@ namespace Build { public const string DATADIR = @DATADIR@; public const string PROFILE = @PROFILE@; public const string LOCALEDIR = @LOCALEDIR@; + public const string GNOMELOCALEDIR = @GNOMELOCALEDIR@; } \ No newline at end of file diff --git a/core/Objects/Project.vala b/core/Objects/Project.vala index 9e85cc982..7e4f73d38 100644 --- a/core/Objects/Project.vala +++ b/core/Objects/Project.vala @@ -234,7 +234,6 @@ public class Objects.Project : Objects.BaseObject { public signal void loading_changed (bool value); public signal void project_count_updated (); public signal void show_multi_select_change (); - public signal void expand_all_items (bool value); construct { deleted.connect (() => { diff --git a/core/QuickAdd.vala b/core/QuickAdd.vala index cc195ec8c..f46840b2d 100644 --- a/core/QuickAdd.vala +++ b/core/QuickAdd.vala @@ -4,7 +4,8 @@ public class Layouts.QuickAdd : Adw.Bin { private Gtk.Entry content_entry; private Widgets.LoadingButton submit_button; - private Widgets.HyperTextView description_textview; + private Widgets.Markdown.Buffer current_buffer; + private Widgets.Markdown.EditView markdown_edit_view; private Widgets.ItemLabels item_labels; private Widgets.ProjectPicker.ProjectPickerButton project_picker_button; private Widgets.ScheduleButton schedule_button; @@ -75,16 +76,16 @@ public class Layouts.QuickAdd : Adw.Bin { content_box.append (content_entry); - description_textview = new Widgets.HyperTextView (_("Add a description…")) { - height_request = 64, + current_buffer = new Widgets.Markdown.Buffer (); + + markdown_edit_view = new Widgets.Markdown.EditView () { left_margin = 14, right_margin = 6, top_margin = 6, - wrap_mode = Gtk.WrapMode.WORD_CHAR, - hexpand = true + connect_typing = false }; - - description_textview.remove_css_class ("view"); + + markdown_edit_view.buffer = current_buffer; item_labels = new Widgets.ItemLabels (item) { margin_start = 6, @@ -127,7 +128,7 @@ public class Layouts.QuickAdd : Adw.Bin { quick_add_content.add_css_class ("card"); quick_add_content.add_css_class ("sidebar-card"); quick_add_content.append (content_box); - quick_add_content.append (description_textview); + quick_add_content.append (markdown_edit_view); quick_add_content.append (item_labels); quick_add_content.append (action_box); @@ -280,15 +281,15 @@ public class Layouts.QuickAdd : Adw.Bin { return false; }); - var description_controller_key = new Gtk.EventControllerKey (); - description_textview.add_controller (description_controller_key); - description_controller_key.key_pressed.connect ((keyval, keycode, state) => { - if ((ctrl_pressed || shift_pressed) && keyval == 65293) { - add_item (); - } + // var description_controller_key = new Gtk.EventControllerKey (); + // description_textview.add_controller (description_controller_key); + // description_controller_key.key_pressed.connect ((keyval, keycode, state) => { + // if ((ctrl_pressed || shift_pressed) && keyval == 65293) { + // add_item (); + // } - return false; - }); + // return false; + // }); var event_controller_key = new Gtk.EventControllerKey (); ((Gtk.Widget) this).add_controller (event_controller_key); @@ -330,7 +331,7 @@ public class Layouts.QuickAdd : Adw.Bin { } item.content = content_entry.get_text (); - item.description = description_textview.get_text (); + item.description = current_buffer.get_all_text ().chomp (); if (item.project.backend_type == BackendType.LOCAL) { item.id = Util.get_default ().generate_id (); @@ -380,7 +381,7 @@ public class Layouts.QuickAdd : Adw.Bin { reset_item (); content_entry.text = ""; - description_textview.set_text (""); + current_buffer.set_text (""); schedule_button.reset (); priority_button.reset (); pin_button.reset (); diff --git a/core/Services/Database.vala b/core/Services/Database.vala index ba9c82f01..1acfa1952 100644 --- a/core/Services/Database.vala +++ b/core/Services/Database.vala @@ -1595,6 +1595,21 @@ public class Services.Database : GLib.Object { } } + public Gee.ArrayList get_items_no_parent (bool checked = true) { + Gee.ArrayList return_value = new Gee.ArrayList (); + lock (_items) { + foreach (Objects.Item item in items) { + if (!item.was_archived () && + item.checked == checked && + !item.has_parent) { + return_value.add (item); + } + } + + return return_value; + } + } + public bool valid_item_by_date (Objects.Item item, GLib.DateTime date, bool checked = true) { if (!item.has_due || item.was_archived ()) { return false; diff --git a/core/Services/EventBus.vala b/core/Services/EventBus.vala index 000d846a7..6566c2ab6 100644 --- a/core/Services/EventBus.vala +++ b/core/Services/EventBus.vala @@ -61,6 +61,7 @@ public class Services.EventBus : Object { public signal void section_sort_order_changed (string project_id); public signal void request_escape (); public signal void drag_n_drop_active (string project_id, bool active); + public signal void expand_all (string project_id, bool active); public bool _mobile_mode = Services.Settings.get_default ().settings.get_boolean ("mobile-mode"); public bool mobile_mode { diff --git a/core/Widgets/DateTimePicker/ScheduleButton.vala b/core/Widgets/DateTimePicker/ScheduleButton.vala index 623e0e269..56c7cd2ef 100644 --- a/core/Widgets/DateTimePicker/ScheduleButton.vala +++ b/core/Widgets/DateTimePicker/ScheduleButton.vala @@ -27,6 +27,7 @@ public class Widgets.ScheduleButton : Gtk.Grid { private Gtk.Box schedule_box; private Gtk.Image due_image; private Widgets.DateTimePicker.DateTimePicker datetime_picker; + private Gtk.Revealer clear_revealer; private GLib.DateTime _datetime; public GLib.DateTime datetime { @@ -52,6 +53,12 @@ public class Widgets.ScheduleButton : Gtk.Grid { } } + public bool visible_clear_button { + set { + clear_revealer.visible = value; + } + } + public signal void date_changed (GLib.DateTime? date); public ScheduleButton () { @@ -103,7 +110,7 @@ public class Widgets.ScheduleButton : Gtk.Grid { css_classes = { "flat" } }; - var clear_revealer = new Gtk.Revealer () { + clear_revealer = new Gtk.Revealer () { transition_type = Gtk.RevealerTransitionType.CROSSFADE, child = clear_button }; diff --git a/core/Widgets/Markdown/MarkdownEditView.vala b/core/Widgets/Markdown/MarkdownEditView.vala index 468a6ad31..864f0383f 100644 --- a/core/Widgets/Markdown/MarkdownEditView.vala +++ b/core/Widgets/Markdown/MarkdownEditView.vala @@ -4,7 +4,7 @@ * https://github.com/toolstack/Folio */ - public class Widgets.Markdown.EditView : Adw.Bin { + public class Widgets.Markdown.EditView : Adw.Bin { public bool text_mode { set { markdown_view.text_mode = value; @@ -68,12 +68,13 @@ } } + public bool connect_typing { get; set; default = false; } + private Widgets.Markdown.View markdown_view; private bool is_ctrl = false; public bool is_editable { get; set; } - public signal void enter (); public signal void leave (); public signal void changed (); @@ -166,7 +167,6 @@ var gesture = new Gtk.EventControllerFocus (); markdown_view.add_controller (gesture); - gesture.enter.connect (handle_focus_in); gesture.leave.connect (update_on_leave); @@ -190,8 +190,10 @@ } public void update_on_leave () { - Services.EventBus.get_default ().connect_typing_accel (); - leave (); + if (connect_typing) { + Services.EventBus.get_default ().connect_typing_accel (); + leave (); + } } public void on_dark_changed (bool dark) { diff --git a/data/io.github.alainm23.planify.service.in b/data/io.github.alainm23.planify.service.in new file mode 100644 index 000000000..d80571161 --- /dev/null +++ b/data/io.github.alainm23.planify.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=@app_id@ +Exec=@bindir@/@app_id@ --gapplication-service diff --git a/data/meson.build b/data/meson.build index 2be7e7602..be7ce08a2 100644 --- a/data/meson.build +++ b/data/meson.build @@ -62,4 +62,14 @@ install_data('markdownpp.lang', install_dir: get_option('datadir') / 'gtksourceview-5' / 'language-specs' ) +# service_conf = configuration_data() +# service_conf.set('appid', application_id) +# service_conf.set('bindir', bindir) +# configure_file( +# input: 'io.github.alainm23.planify.service.in', +# output: '@0@.service'.format(application_id), +# configuration: service_conf, +# install_dir: datadir / 'dbus-1' / 'services' +# ) + subdir('icons') \ No newline at end of file diff --git a/meson.build b/meson.build index 1d9a0e1d7..aca612bf5 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'io.github.alainm23.planify', 'vala', 'c', - version: '4.7.6' + version: '4.8' ) gnome = import('gnome') @@ -51,23 +51,31 @@ if profile == 'development' rev_txt = run_command('git','rev-parse','--short','HEAD').stdout().strip() rev = '-@0@'.format(rev_txt) application_id = 'io.github.alainm23.planify.Devel' + application_path = '/io/github/alainm23/planify/Devel' else rev = '' application_id = 'io.github.alainm23.planify' + application_path = '/io/github/alainm23/planify' endif ############ # Config # ############ +prefix = get_option('prefix') +bindir = prefix / get_option('bindir') +datadir = prefix / get_option('datadir') +localedir = prefix / get_option ('localedir') +libexecdir = prefix / get_option('libexecdir') conf_data = configuration_data() conf_data.set_quoted('APPLICATION_ID', application_id) conf_data.set_quoted('GETTEXT_PACKAGE', application_id) +conf_data.set_quoted('GNOMELOCALEDIR', localedir) conf_data.set_quoted('VERSION', meson.project_version()) -conf_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) +conf_data.set_quoted('LOCALEDIR', localedir) conf_data.set_quoted('PACKAGE_VERSION', meson.project_version()) -conf_data.set_quoted('PREFIX', get_option('prefix')) -conf_data.set_quoted('DATADIR', join_paths (get_option('prefix'), get_option('datadir'))) +conf_data.set_quoted('PREFIX', prefix) +conf_data.set_quoted('DATADIR', datadir) conf_data.set_quoted('PROFILE', profile) config_file = configure_file( @@ -80,6 +88,7 @@ subdir('core') subdir('src') subdir('quick-add') subdir('data') +# subdir('search-provider') subdir('po') summary({ diff --git a/search-provider/io.github.alainm23.planify.SearchProvider.ini.in b/search-provider/io.github.alainm23.planify.SearchProvider.ini.in new file mode 100644 index 000000000..12029e3bb --- /dev/null +++ b/search-provider/io.github.alainm23.planify.SearchProvider.ini.in @@ -0,0 +1,5 @@ +[Shell Search Provider] +DesktopId=@appid@.desktop +BusName=@appid@.SearchProvider +ObjectPath=@path@/SearchProvider +Version=2 \ No newline at end of file diff --git a/search-provider/io.github.alainm23.planify.SearchProvider.service.in b/search-provider/io.github.alainm23.planify.SearchProvider.service.in new file mode 100644 index 000000000..ceb6ae2e8 --- /dev/null +++ b/search-provider/io.github.alainm23.planify.SearchProvider.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=@appid@.SearchProvider +Exec=@libexecdir@/@appid@-search-provider \ No newline at end of file diff --git a/search-provider/main.vala b/search-provider/main.vala new file mode 100644 index 000000000..85c4d44a8 --- /dev/null +++ b/search-provider/main.vala @@ -0,0 +1,11 @@ +// This file is part of Highscore. License: GPL-3.0-or-later + +int main (string[] args) { + Intl.bindtextdomain (Build.GETTEXT_PACKAGE, Build.GNOMELOCALEDIR); + Intl.bind_textdomain_codeset (Build.GETTEXT_PACKAGE, "UTF-8"); + Intl.textdomain (Build.GETTEXT_PACKAGE); + + var app = new Planify.SearchProvider (); + + return app.run (args); +} diff --git a/search-provider/meson.build b/search-provider/meson.build new file mode 100644 index 000000000..bc7ed49ac --- /dev/null +++ b/search-provider/meson.build @@ -0,0 +1,47 @@ +search_provider_c_args = [ + '-DGETTEXT_PACKAGE="' + meson.project_name () + '"', + '-DG_LOG_DOMAIN="PlanifySearchProvider"', +] + +search_provider_sources = [ + 'main.vala', + 'search-provider.vala' +] + +search_provider_deps = [ + gio_dep, + gtk_dep, + sqlite3_dep, +] + +executable ( + 'io.github.alainmh23.planify-search-provider', + search_provider_sources, + config_file, + dependencies: search_provider_deps, + c_args: search_provider_c_args, + install: true, + install_dir: libexecdir +) + +search_provider_conf = configuration_data() +search_provider_conf.set('appid', application_id) +search_provider_conf.set('path', application_path) +configure_file( + configuration: search_provider_conf, + input: 'io.github.alainm23.planify.SearchProvider.ini.in', + install_dir: datadir / 'gnome-shell' / 'search-providers', + install: true, + output: '@0@.SearchProvider.ini'.format(application_id) +) + +search_provider_dbus_conf = configuration_data() +search_provider_dbus_conf.set('appid', application_id) +search_provider_dbus_conf.set('libexecdir', libexecdir) +configure_file ( + input: 'io.github.alainm23.planify.SearchProvider.service.in', + output: '@0@.SearchProvider.service'.format(application_id), + configuration: search_provider_dbus_conf, + install: true, + install_dir: datadir / 'dbus-1' / 'services' +) diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala new file mode 100644 index 000000000..3fce1b91e --- /dev/null +++ b/search-provider/search-provider.vala @@ -0,0 +1,28 @@ +// This file is part of Highscore. License: GPL-3.0+. + +[DBus (name = "org.gnome.Shell.SearchProvider2")] +public class Planify.SearchProvider : Gtk.Application { + internal SearchProvider () { + Object ( + application_id: Build.APPLICATION_ID + ".SearchProvider", + flags: ApplicationFlags.IS_SERVICE, + inactivity_timeout: 10000 + ); + } + + construct { + + } + + protected override bool dbus_register (DBusConnection connection, string object_path) { + try { + connection.register_object (object_path, this); + } catch (IOError e) { + warning ("Could not register search provider: %s", e.message); + quit (); + } + + return true; + } + +} \ No newline at end of file diff --git a/src/App.vala b/src/App.vala index 76c1fb219..75ad4794f 100644 --- a/src/App.vala +++ b/src/App.vala @@ -47,10 +47,15 @@ public class Planify : Adw.Application { { null } }; - construct { - application_id = Build.APPLICATION_ID; - flags |= ApplicationFlags.HANDLES_OPEN; + public Planify () { + Object ( + application_id: Build.APPLICATION_ID, + flags: ApplicationFlags.HANDLES_OPEN + ); + } + + construct { Intl.setlocale (LocaleCategory.ALL, ""); string langpack_dir = Path.build_filename (Build.INSTALL_PREFIX, "share", "locale"); Intl.bindtextdomain (Build.GETTEXT_PACKAGE, langpack_dir); diff --git a/src/Layouts/SectionRow.vala b/src/Layouts/SectionRow.vala index dfdd7ddf3..1dea617b7 100644 --- a/src/Layouts/SectionRow.vala +++ b/src/Layouts/SectionRow.vala @@ -478,9 +478,11 @@ public class Layouts.SectionRow : Gtk.ListBoxRow { is_loading = section.loading; }); - section.project.expand_all_items.connect ((value) => { - foreach (Layouts.ItemRow row in items.values) { - row.edit = value; + Services.EventBus.get_default ().expand_all.connect ((project_id, value) => { + if (section.project_id == project_id) { + foreach (Layouts.ItemRow row in items.values) { + row.edit = value; + } } }); } diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 3d12076f4..e30e05975 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -184,8 +184,6 @@ public class MainWindow : Adw.ApplicationWindow { }); Services.EventBus.get_default ().pane_selected.connect ((pane_type, id) => { - Services.EventBus.get_default ().unselect_all (); - if (pane_type == PaneType.PROJECT) { add_project_view (Services.Database.get_default ().get_project (id)); } else if (pane_type == PaneType.FILTER) { diff --git a/src/Views/Filter.vala b/src/Views/Filter.vala index 417445a58..a9c34bc8d 100644 --- a/src/Views/Filter.vala +++ b/src/Views/Filter.vala @@ -274,7 +274,7 @@ public class Views.Filter : Adw.Bin { add_item (item); } } else if (filter is Objects.Filters.AllItems) { - foreach (Objects.Item item in Services.Database.get_default ().items) { + foreach (Objects.Item item in Services.Database.get_default ().get_items_no_parent (false)) { add_item (item); } } diff --git a/src/Views/Project/Project.vala b/src/Views/Project/Project.vala index f624f7e58..8bf1226a8 100644 --- a/src/Views/Project/Project.vala +++ b/src/Views/Project/Project.vala @@ -372,12 +372,12 @@ public class Views.Project : Adw.Bin { expand_all_item.clicked.connect (() => { popover.popdown (); - project.expand_all_items (true); + Services.EventBus.get_default ().expand_all (project.id, true); }); collapse_all_item.clicked.connect (() => { popover.popdown (); - project.expand_all_items (false); + Services.EventBus.get_default ().expand_all (project.id, false); }); select_item.clicked.connect (() => { diff --git a/src/Widgets/MultiSelectToolbar.vala b/src/Widgets/MultiSelectToolbar.vala index 1108894c7..664fce0fd 100644 --- a/src/Widgets/MultiSelectToolbar.vala +++ b/src/Widgets/MultiSelectToolbar.vala @@ -45,13 +45,18 @@ public class Widgets.MultiSelectToolbar : Adw.Bin { css_classes = { "sidebar" }; size_label = new Gtk.Label (null) { - css_classes = { "font-bold" } + css_classes = { "font-bold", "card" }, + width_request = 32, + height_request = 24, + valign = Gtk.Align.CENTER, + margin_end = 6 }; schedule_button = new Widgets.ScheduleButton () { - sensitive = false + sensitive = false, + visible_clear_button = false, + visible_no_date = true }; - schedule_button.visible_no_date = true; label_button = new Widgets.LabelPicker.LabelButton () { sensitive = false @@ -80,7 +85,7 @@ public class Widgets.MultiSelectToolbar : Adw.Bin { css_classes = { "suggested-action" } }; - var content_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { + var content_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6) { valign = Gtk.Align.CENTER, halign = Gtk.Align.CENTER, margin_top = 9, @@ -127,14 +132,6 @@ public class Widgets.MultiSelectToolbar : Adw.Bin { unselect_all (); }); - Services.EventBus.get_default ().request_escape.connect (() => { - unselect_all (); - }); - - Services.EventBus.get_default ().unselect_all.connect (() => { - unselect_all (); - }); - schedule_button.date_changed.connect ((datetime) => { set_datetime (datetime); }); @@ -290,7 +287,7 @@ public class Widgets.MultiSelectToolbar : Adw.Bin { private void check_select_bar () { bool active = items_selected.size > 0; - size_label.label = active ? "(%d)".printf (items_selected.size) : ""; + size_label.label = active ? items_selected.size.to_string () : ""; schedule_button.sensitive = active; priority_button.sensitive = active; label_button.sensitive = active; diff --git a/src/Widgets/SubItems.vala b/src/Widgets/SubItems.vala index 4ae579fc4..4502955cf 100644 --- a/src/Widgets/SubItems.vala +++ b/src/Widgets/SubItems.vala @@ -108,8 +108,7 @@ public class Widgets.SubItems : Adw.Bin { selection_mode = Gtk.SelectionMode.SINGLE, hexpand = true, css_classes = { "listbox-background" }, - margin_start = 3, - margin_end = 6 + margin_start = 3 }; checked_listbox = new Gtk.ListBox () { @@ -287,6 +286,16 @@ public class Widgets.SubItems : Adw.Bin { } } })] = Services.Settings.get_default ().settings; + + signals_map[Services.EventBus.get_default ().expand_all.connect ((project_id, value) => { + if (item_parent.project_id == project_id) { + foreach (Layouts.ItemBase row_base in items.values) { + if (row_base is Layouts.ItemRow) { + ((Layouts.ItemRow) row_base).edit = value; + } + } + } + })] = Services.Settings.get_default (); } public void add_items () {