From ee64bb2698adfe27e55615a8856b0e2c78ad8469 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 14 Jan 2014 23:07:10 -0600 Subject: Function: add fully-tested ActionGroups, per-profile Menus, state object. Form: Add code annotations/comments. Remove dead code. Use Mir style guide. Todo: GSettings toggles, sync with new dbus-test-runner API, get GNOME Panel building again --- src/menu.cpp | 518 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 src/menu.cpp (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp new file mode 100644 index 0000000..76306cc --- /dev/null +++ b/src/menu.cpp @@ -0,0 +1,518 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace unity { +namespace indicator { +namespace datetime { + +/**** +***** +****/ + +#define ALARM_CLOCK_ICON_NAME "alarm-clock" +#define CALENDAR_ICON_NAME "calendar" + +class MenuImpl: public Menu +{ +protected: + MenuImpl(const Menu::Profile profile_in, + const std::string& name_in, + std::shared_ptr& state, + std::shared_ptr& actions, + std::shared_ptr formatter): + Menu(profile_in, name_in), + m_state(state), + m_actions(actions), + m_formatter(formatter) + { + // initialize the menu + create_gmenu(); + for (int i=0; iheader.changed().connect([this](const std::string&){ + update_header(); + }); + m_formatter->headerFormat.changed().connect([this](const std::string&){ + update_section(Locations); // need to update x-canonical-time-format + }); + m_formatter->relativeFormatChanged.connect([this](){ + update_section(Appointments); // uses formatter.getRelativeFormat() + update_section(Locations); // uses formatter.getRelativeFormat() + }); + m_state->show_clock.changed().connect([this](bool){ + update_header(); // update header's label + update_section(Locations); // locations' relative time may have changed + }); + m_state->show_events.changed().connect([this](bool){ + update_section(Appointments); // showing events got toggled + }); + m_state->planner->upcoming.changed().connect([this](const std::vector&){ + update_section(Appointments); // "upcoming" is the list of Appointments we show + }); + m_state->clock->dateChanged.connect([this](){ + update_section(Calendar); // need to update the Date menuitem + update_section(Locations); // locations' relative time may have changed + }); + m_state->locations->locations.changed().connect([this](const std::vector&) { + update_section(Locations); // "locations" is the list of Locations we show + }); + } + + virtual ~MenuImpl() + { + g_clear_object(&m_menu); + g_clear_pointer(&m_serialized_alarm_icon, g_variant_unref); + g_clear_pointer(&m_serialized_calendar_icon, g_variant_unref); + } + + virtual GVariant* create_header_state() =0; + + void update_header() + { + auto action_group = m_actions->action_group(); + auto action_name = name() + "-header"; + auto state = create_header_state(); + g_action_group_change_action_state(action_group, action_name.c_str(), state); + } + + std::shared_ptr m_state; + std::shared_ptr m_actions; + std::shared_ptr m_formatter; + GMenu* m_submenu = nullptr; + + GVariant* get_serialized_alarm_icon() + { + if (G_UNLIKELY(m_serialized_alarm_icon == nullptr)) + { + auto i = g_themed_icon_new_with_default_fallbacks(ALARM_CLOCK_ICON_NAME); + m_serialized_alarm_icon = g_icon_serialize(i); + g_object_unref(i); + } + + return m_serialized_alarm_icon; + } + +private: + + GVariant* get_serialized_calendar_icon() + { + if (G_UNLIKELY(m_serialized_calendar_icon == nullptr)) + { + auto i = g_themed_icon_new_with_default_fallbacks(CALENDAR_ICON_NAME); + m_serialized_calendar_icon = g_icon_serialize(i); + g_object_unref(i); + } + + return m_serialized_calendar_icon; + } + + void create_gmenu() + { + g_assert(m_submenu == nullptr); + + m_submenu = g_menu_new(); + + // build placeholders for the sections + for(int i=0; iclock->localtime().format(_("%A, %e %B %Y")); + auto item = g_menu_item_new (label.c_str(), nullptr); + auto v = get_serialized_calendar_icon(); + g_menu_item_set_attribute_value (item, G_MENU_ATTRIBUTE_ICON, v); + if (allow_activation) + { + v = g_variant_new_int64(0); + const char* action = "indicator.activate-planner"; + g_menu_item_set_action_and_target_value (item, action, v); + } + g_menu_append_item(menu, item); + g_object_unref(item); + + // add calendar + if (show_calendar) + { + item = g_menu_item_new ("[calendar]", NULL); + v = g_variant_new_int64(0); + g_menu_item_set_action_and_target_value (item, "indicator.calendar", v); + g_menu_item_set_attribute (item, "x-canonical-type", + "s", "com.canonical.indicator.calendar"); + if (allow_activation) + { + g_menu_item_set_attribute (item, "activation-action", + "s", "indicator.activate-planner"); + } + g_menu_append_item (menu, item); + g_object_unref (item); + } + + return G_MENU_MODEL(menu); + } + + void add_appointments(GMenu* menu, Profile profile) + { + int n = 0; + const int MAX_APPTS = 5; + std::set added; + + for (const auto& appt : m_state->planner->upcoming.get()) + { + if (n++ >= MAX_APPTS) + break; + + if (added.count(appt.uid)) + continue; + + added.insert(appt.uid); + + GDateTime* begin = appt.begin(); + GDateTime* end = appt.end(); + auto fmt = m_formatter->getRelativeFormat(begin, end); + auto unix_time = g_date_time_to_unix(begin); + + auto menu_item = g_menu_item_new (appt.summary.c_str(), nullptr); + g_menu_item_set_attribute (menu_item, "x-canonical-time", "x", unix_time); + g_menu_item_set_attribute (menu_item, "x-canonical-time-format", "s", fmt.c_str()); + + if (appt.has_alarms) + { + g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.alarm"); + g_menu_item_set_attribute_value(menu_item, G_MENU_ATTRIBUTE_ICON, get_serialized_alarm_icon()); + } + else + { + g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.appointment"); + + if (!appt.color.empty()) + g_menu_item_set_attribute (menu_item, "x-canonical-color", "s", appt.color.c_str()); + } + + if (profile == Phone) + g_menu_item_set_action_and_target_value (menu_item, + "indicator.activate-appointment", + g_variant_new_string (appt.uid.c_str())); + else + g_menu_item_set_action_and_target_value (menu_item, + "indicator.activate-planner", + g_variant_new_int64 (unix_time)); + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); + } + } + + GMenuModel* create_appointments_section(Profile profile) + { + auto menu = g_menu_new(); + + if (((profile==Phone) || (profile==Desktop)) && m_state->show_events.get()) + { + add_appointments (menu, profile); + + // add the 'Add Event…' menuitem + auto menu_item = g_menu_item_new(_("Add Event…"), nullptr); + const gchar* action_name = "indicator.activate_planner"; + auto v = g_variant_new_int64(0); + g_menu_item_set_action_and_target_value(menu_item, action_name, v); + g_menu_append_item(menu, menu_item); + g_object_unref(menu_item); + } + + return G_MENU_MODEL(menu); + } + + GMenuModel* create_locations_section(Profile profile) + { + GMenu* menu = g_menu_new(); + + if (profile == Desktop) + { + const auto now = m_state->clock->localtime(); + + for(const auto& location : m_state->locations->locations.get()) + { + const auto& zone = location.zone(); + const auto& name = location.name(); + const auto zone_now = now.to_timezone(zone); + const auto fmt = m_formatter->getRelativeFormat(zone_now.get()); + auto detailed_action = g_strdup_printf("indicator.set-location::%s %s", zone.c_str(), name.c_str()); + auto i = g_menu_item_new (name.c_str(), detailed_action); + g_menu_item_set_attribute(i, "x-canonical-type", "s", "com.canonical.indicator.location"); + g_menu_item_set_attribute(i, "x-canonical-timezone", "s", zone.c_str()); + g_menu_item_set_attribute(i, "x-canonical-time-format", "s", fmt.c_str()); + g_menu_append_item (menu, i); + g_object_unref(i); + g_free(detailed_action); + } + } + + return G_MENU_MODEL(menu); + } + + GMenuModel* create_settings_section(Profile profile) + { + auto menu = g_menu_new(); + + if (profile == Desktop) + { + g_menu_append (menu, _("Date & Time Settings…"), "indicator.activate-desktop-settings"); + } + else if (profile == Phone) + { + g_menu_append (menu, _("Time & Date settings…"), "indicator.activate-phone-settings"); + } + + return G_MENU_MODEL (menu); + } + + void update_section(Section section) + { + GMenuModel * model; + const auto p = profile(); + + switch (section) + { + case Calendar: model = create_calendar_section(p); break; + case Appointments: model = create_appointments_section(p); break; + case Locations: model = create_locations_section(p); break; + case Settings: model = create_settings_section(p); break; + default: g_warn_if_reached(); + } + + if (model) + { + g_menu_remove(m_submenu, section); + g_menu_insert_section(m_submenu, section, nullptr, model); + g_object_unref(model); + } + } + +//private: + GVariant * m_serialized_alarm_icon = nullptr; + GVariant * m_serialized_calendar_icon = nullptr; + +}; // class MenuImpl + + + +/*** +**** +***/ + +class DesktopBaseMenu: public MenuImpl +{ +protected: + DesktopBaseMenu(Menu::Profile profile_, + const std::string& name_, + std::shared_ptr& state_, + std::shared_ptr& actions_): + MenuImpl(profile_, name_, state_, actions_, + std::shared_ptr(new DesktopFormatter(state_->clock))) + { + update_header(); + } + + GVariant* create_header_state() + { + const auto visible = m_state->show_clock.get(); + const auto title = _("Date and Time"); + auto label = g_variant_new_string(m_formatter->header.get().c_str()); + + GVariantBuilder b; + g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&b, "{sv}", "accessible-desc", label); + g_variant_builder_add(&b, "{sv}", "label", label); + g_variant_builder_add(&b, "{sv}", "title", g_variant_new_string(title)); + g_variant_builder_add(&b, "{sv}", "visible", g_variant_new_boolean(visible)); + return g_variant_builder_end(&b); + } +}; + +class DesktopMenu: public DesktopBaseMenu +{ +public: + DesktopMenu(std::shared_ptr& state_, std::shared_ptr& actions_): + DesktopBaseMenu(Desktop,"desktop", state_, actions_) {} +}; + +class DesktopGreeterMenu: public DesktopBaseMenu +{ +public: + DesktopGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): + DesktopBaseMenu(DesktopGreeter,"desktop-greeter", state_, actions_) {} +}; + +class PhoneBaseMenu: public MenuImpl +{ +protected: + PhoneBaseMenu(Menu::Profile profile_, + const std::string& name_, + std::shared_ptr& state_, + std::shared_ptr& actions_): + MenuImpl(profile_, name_, state_, actions_, + std::shared_ptr(new PhoneFormatter(state_->clock))) + { + update_header(); + } + + GVariant* create_header_state() + { + // are there alarms? + bool has_alarms = false; + for(const auto& appointment : m_state->planner->upcoming.get()) + if((has_alarms = appointment.has_alarms)) + break; + + GVariantBuilder b; + g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&b, "{sv}", "title", g_variant_new_string (_("Upcoming"))); + g_variant_builder_add(&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); + if (has_alarms) + { + auto label = m_formatter->header.get(); + auto a11y = g_strdup_printf(_("%s (has alarms)"), label.c_str()); + g_variant_builder_add(&b, "{sv}", "label", g_variant_new_string(label.c_str())); + g_variant_builder_add(&b, "{sv}", "accessible-desc", g_variant_new_take_string(a11y)); + g_variant_builder_add(&b, "{sv}", "icon", get_serialized_alarm_icon()); + } + else + { + auto v = g_variant_new_string(m_formatter->header.get().c_str()); + g_variant_builder_add(&b, "{sv}", "label", v); + g_variant_builder_add(&b, "{sv}", "accessible-desc", v); + } + return g_variant_builder_end (&b); + } +}; + +class PhoneMenu: public PhoneBaseMenu +{ +public: + PhoneMenu(std::shared_ptr& state_, + std::shared_ptr& actions_): + PhoneBaseMenu(Phone, "phone", state_, actions_) {} +}; + +class PhoneGreeterMenu: public PhoneBaseMenu +{ +public: + PhoneGreeterMenu(std::shared_ptr& state_, + std::shared_ptr& actions_): + PhoneBaseMenu(PhoneGreeter, "phone-greeter", state_, actions_) {} +}; + +/**** +***** +****/ + +MenuFactory::MenuFactory(std::shared_ptr& actions_, + std::shared_ptr& state_): + m_actions(actions_), + m_state(state_) +{ +} + +std::shared_ptr +MenuFactory::buildMenu(Menu::Profile profile) +{ + std::shared_ptr menu; + m_state->show_clock.set (true); // FIXME + + //std::shared_ptr state(new State); + //state->clock = clock; + //state->planner = planner; + //state->locations = locations; + + switch (profile) + { + case Menu::Desktop: + m_state->show_events.set(true); // FIXME + menu.reset(new DesktopMenu(m_state, m_actions)); + break; + + case Menu::DesktopGreeter: + m_state->show_events.set(true); // FIXME + menu.reset(new DesktopGreeterMenu(m_state, m_actions)); + break; + + case Menu::Phone: + m_state->show_events.set(true); // FIXME + menu.reset(new PhoneMenu(m_state, m_actions)); + break; + + case Menu::PhoneGreeter: + m_state->show_events.set(false); // FIXME + menu.reset(new PhoneGreeterMenu(m_state, m_actions)); + break; + + default: + g_warn_if_reached(); + break; + } + + return menu; +} + +/**** +***** +****/ + +} // namespace datetime +} // namespace indicator +} // namespace unity -- cgit v1.2.3 From a2b5c79157fa8db36d94786de1b86b756308912d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 16:45:40 -0600 Subject: Plug the Settings object into the State container s.t. menus and actions can update themselves when the user's settings change. --- src/menu.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 76306cc..c81f185 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -69,11 +69,11 @@ protected: update_section(Appointments); // uses formatter.getRelativeFormat() update_section(Locations); // uses formatter.getRelativeFormat() }); - m_state->show_clock.changed().connect([this](bool){ + m_state->settings->show_clock.changed().connect([this](bool){ update_header(); // update header's label update_section(Locations); // locations' relative time may have changed }); - m_state->show_events.changed().connect([this](bool){ + m_state->settings->show_events.changed().connect([this](bool){ update_section(Appointments); // showing events got toggled }); m_state->planner->upcoming.changed().connect([this](const std::vector&){ @@ -261,7 +261,7 @@ private: { auto menu = g_menu_new(); - if (((profile==Phone) || (profile==Desktop)) && m_state->show_events.get()) + if (((profile==Phone) || (profile==Desktop)) && m_state->settings->show_events.get()) { add_appointments (menu, profile); @@ -363,14 +363,14 @@ protected: std::shared_ptr& state_, std::shared_ptr& actions_): MenuImpl(profile_, name_, state_, actions_, - std::shared_ptr(new DesktopFormatter(state_->clock))) + std::shared_ptr(new DesktopFormatter(state_->clock, state_->settings))) { update_header(); } GVariant* create_header_state() { - const auto visible = m_state->show_clock.get(); + const auto visible = m_state->settings->show_clock.get(); const auto title = _("Date and Time"); auto label = g_variant_new_string(m_formatter->header.get().c_str()); @@ -472,32 +472,22 @@ std::shared_ptr MenuFactory::buildMenu(Menu::Profile profile) { std::shared_ptr menu; - m_state->show_clock.set (true); // FIXME - - //std::shared_ptr state(new State); - //state->clock = clock; - //state->planner = planner; - //state->locations = locations; switch (profile) { case Menu::Desktop: - m_state->show_events.set(true); // FIXME menu.reset(new DesktopMenu(m_state, m_actions)); break; case Menu::DesktopGreeter: - m_state->show_events.set(true); // FIXME menu.reset(new DesktopGreeterMenu(m_state, m_actions)); break; case Menu::Phone: - m_state->show_events.set(true); // FIXME menu.reset(new PhoneMenu(m_state, m_actions)); break; case Menu::PhoneGreeter: - m_state->show_events.set(false); // FIXME menu.reset(new PhoneGreeterMenu(m_state, m_actions)); break; -- cgit v1.2.3 From 6e447b7bdb1273048dbaf9ead0eea629e73042e3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 08:08:44 -0600 Subject: plug in the greeter menus --- src/menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index c81f185..43e07ae 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -395,7 +395,7 @@ class DesktopGreeterMenu: public DesktopBaseMenu { public: DesktopGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): - DesktopBaseMenu(DesktopGreeter,"desktop-greeter", state_, actions_) {} + DesktopBaseMenu(DesktopGreeter,"desktop_greeter", state_, actions_) {} }; class PhoneBaseMenu: public MenuImpl @@ -454,7 +454,7 @@ class PhoneGreeterMenu: public PhoneBaseMenu public: PhoneGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): - PhoneBaseMenu(PhoneGreeter, "phone-greeter", state_, actions_) {} + PhoneBaseMenu(PhoneGreeter, "phone_greeter", state_, actions_) {} }; /**** -- cgit v1.2.3 From 56e036200e389f74064836ea2e3254a8b9bc267f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 08:35:54 -0600 Subject: the clock icon should match the one used by the clock app, so use click to ask the clock app which icon it's using --- src/menu.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 43e07ae..5b19d92 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -53,6 +55,9 @@ protected: m_actions(actions), m_formatter(formatter) { + // preload the alarm icon from click + m_serialized_alarm_icon = create_alarm_icon(); + // initialize the menu create_gmenu(); for (int i=0; i m_formatter; GMenu* m_submenu = nullptr; - GVariant* get_serialized_alarm_icon() + GVariant* get_serialized_alarm_icon() { return m_serialized_alarm_icon; } + +private: + + /* try to get the clock app's filename from click. (/$pkgdir/$icon) */ + static GVariant* create_alarm_icon() { - if (G_UNLIKELY(m_serialized_alarm_icon == nullptr)) + GVariant* serialized = nullptr; + gchar* icon_filename = nullptr; + gchar* standard_error = nullptr; + gchar* pkgdir = nullptr; + + g_spawn_command_line_sync("click pkgdir com.ubuntu.clock", &pkgdir, &standard_error, nullptr, nullptr); + g_clear_pointer(&standard_error, g_free); + if (pkgdir != nullptr) { - auto i = g_themed_icon_new_with_default_fallbacks(ALARM_CLOCK_ICON_NAME); - m_serialized_alarm_icon = g_icon_serialize(i); - g_object_unref(i); + gchar* manifest = nullptr; + g_strstrip(pkgdir); + g_spawn_command_line_sync("click info com.ubuntu.clock", &manifest, &standard_error, nullptr, nullptr); + g_clear_pointer(&standard_error, g_free); + if (manifest != nullptr) + { + JsonParser* parser = json_parser_new(); + if (json_parser_load_from_data(parser, manifest, -1, nullptr)) + { + JsonNode* root = json_parser_get_root(parser); /* transfer-none */ + if ((root != nullptr) && (JSON_NODE_TYPE(root) == JSON_NODE_OBJECT)) + { + JsonObject* o = json_node_get_object(root); /* transfer-none */ + const gchar* icon_name = json_object_get_string_member(o, "icon"); + if (icon_name != nullptr) + icon_filename = g_build_filename(pkgdir, icon_name, nullptr); + } + } + g_object_unref(parser); + g_free(manifest); + } + g_free(pkgdir); } - return m_serialized_alarm_icon; - } + if (icon_filename != nullptr) + { + GFile* file = g_file_new_for_path(icon_filename); + GIcon* icon = g_file_icon_new(file); -private: + serialized = g_icon_serialize(icon); + + g_object_unref(icon); + g_object_unref(file); + g_free(icon_filename); + } + + return serialized; + } GVariant* get_serialized_calendar_icon() { -- cgit v1.2.3 From b4a6c506a38e5e9d364a3909eb4aeeed91ed36c8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 09:53:27 -0600 Subject: copyediting: omit unnecessary #includes --- src/menu.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 5b19d92..503d47c 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -19,12 +19,8 @@ #include -#include #include -#include -#include #include -#include #include -- cgit v1.2.3 From 47ab9adad438b137b5e7e9b33ce503e184e019f8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 09:57:52 -0600 Subject: follow-up to r326, if we can't get the alarm icon from click, use a sane fallback icon --- src/menu.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 503d47c..9e76d4b 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -35,7 +35,7 @@ namespace datetime { ***** ****/ -#define ALARM_CLOCK_ICON_NAME "alarm-clock" +#define FALLBACK_ALARM_CLOCK_ICON_NAME "clock" #define CALENDAR_ICON_NAME "calendar" class MenuImpl: public Menu @@ -163,8 +163,15 @@ private: g_free(icon_filename); } + if (serialized == nullptr) + { + auto i = g_themed_icon_new_with_default_fallbacks(FALLBACK_ALARM_CLOCK_ICON_NAME); + serialized = g_icon_serialize(i); + g_object_unref(i); + } + return serialized; - } + } GVariant* get_serialized_calendar_icon() { -- cgit v1.2.3 From e57a2e9b860db9776d94356a6fc38e193c801f65 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 28 Jan 2014 11:50:50 -0600 Subject: silence compiler warning --- src/menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 9e76d4b..390a06f 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -381,7 +381,7 @@ private: case Appointments: model = create_appointments_section(p); break; case Locations: model = create_locations_section(p); break; case Settings: model = create_settings_section(p); break; - default: g_warn_if_reached(); + default: model = nullptr; g_warn_if_reached(); } if (model) -- cgit v1.2.3 From f07f97ef53522abdce52cf3c7b583c0d6d47aa40 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 12:50:59 -0600 Subject: sync with lp:~larsu/indicator-datetime/reset-date and add corresponding unit tests. --- src/menu.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 390a06f..b0ba79d 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -204,6 +204,8 @@ private: auto header = g_menu_item_new(nullptr, detailed_action.c_str()); g_menu_item_set_attribute(header, "x-canonical-type", "s", "com.canonical.indicator.root"); + g_menu_item_set_attribute(header, "submenu-action", "s", + "indicator.calendar-active"); g_menu_item_set_submenu(header, G_MENU_MODEL(m_submenu)); g_object_unref(m_submenu); -- cgit v1.2.3 From 6b2c01ed6063bd7fd12e192668b738a075dc3a24 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 16:10:50 -0600 Subject: fix instant calendar toggle issue reported in testing by seb128; add a test for this regression --- src/menu.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index b0ba79d..40a94fa 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -74,6 +74,9 @@ protected: update_header(); // update header's label update_section(Locations); // locations' relative time may have changed }); + m_state->settings->show_calendar.changed().connect([this](bool){ + update_section(Calendar); + }); m_state->settings->show_events.changed().connect([this](bool){ update_section(Appointments); // showing events got toggled }); @@ -219,8 +222,8 @@ private: { const bool allow_activation = (profile == Desktop) || (profile == Phone); - const bool show_calendar = (profile == Desktop) - || (profile == DesktopGreeter); + const bool show_calendar = m_state->settings->show_calendar.get() && + ((profile == Desktop) || (profile == DesktopGreeter)); auto menu = g_menu_new(); // add a menuitem that shows the current date -- cgit v1.2.3 From 131f7512975e3e0e1363cb787834abee5b79b4e5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 16:26:25 -0600 Subject: =?UTF-8?q?fix=20disabled=20'Add=20Event=E2=80=A6'=20menuitem=20is?= =?UTF-8?q?sue=20reported=20in=20testing=20by=20seb128;=20add=20a=20test?= =?UTF-8?q?=20for=20this=20regression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 40a94fa..44da7b7 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -321,7 +321,7 @@ private: // add the 'Add Event…' menuitem auto menu_item = g_menu_item_new(_("Add Event…"), nullptr); - const gchar* action_name = "indicator.activate_planner"; + const gchar* action_name = "indicator.activate-planner"; auto v = g_variant_new_int64(0); g_menu_item_set_action_and_target_value(menu_item, action_name, v); g_menu_append_item(menu, menu_item); -- cgit v1.2.3 From 9752ca1cd3e75e1245ebb8dcb4719503e332a352 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 10:57:19 -0600 Subject: fix 'clock app' menuitem on phone profile reported by seb128 and update the corresponding unit tests --- src/menu.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 44da7b7..d0756cc 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -293,10 +293,10 @@ private: else { g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.appointment"); - - if (!appt.color.empty()) - g_menu_item_set_attribute (menu_item, "x-canonical-color", "s", appt.color.c_str()); } + + if (!appt.color.empty()) + g_menu_item_set_attribute (menu_item, "x-canonical-color", "s", appt.color.c_str()); if (profile == Phone) g_menu_item_set_action_and_target_value (menu_item, @@ -315,7 +315,7 @@ private: { auto menu = g_menu_new(); - if (((profile==Phone) || (profile==Desktop)) && m_state->settings->show_events.get()) + if ((profile==Desktop) && m_state->settings->show_events.get()) { add_appointments (menu, profile); @@ -327,6 +327,15 @@ private: g_menu_append_item(menu, menu_item); g_object_unref(menu_item); } + else if (profile==Phone) + { + auto menu_item = g_menu_item_new (_("Clock"), "indicator.activate-phone-clock-app"); + g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ICON, get_serialized_alarm_icon()); + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); + + add_appointments (menu, profile); + } return G_MENU_MODEL(menu); } -- cgit v1.2.3 From d2caa37e18191c31d866dd3042b676c135bae50d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 12:45:50 -0600 Subject: as per review, don't inline getters --- src/menu.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index d0756cc..4bb4fb6 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -35,6 +35,27 @@ namespace datetime { ***** ****/ +const std::string& Menu::name() const +{ + return m_name; +} + +Menu::Profile Menu::profile() const +{ + return m_profile; +} + +GMenuModel* Menu::menu_model() +{ + return G_MENU_MODEL(m_menu); +} + + +/**** +***** +****/ + + #define FALLBACK_ALARM_CLOCK_ICON_NAME "clock" #define CALENDAR_ICON_NAME "calendar" @@ -531,6 +552,11 @@ MenuFactory::MenuFactory(std::shared_ptr& actions_, { } +std::shared_ptr MenuFactory::state() +{ + return m_state; +} + std::shared_ptr MenuFactory::buildMenu(Menu::Profile profile) { -- cgit v1.2.3 From cc2ad2ad457313cb87e4483bf0278f670a5a5cea Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 13:00:22 -0600 Subject: as per review, don't inline unless there are performance issues --- src/menu.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 4bb4fb6..b263520 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -35,6 +35,12 @@ namespace datetime { ***** ****/ +Menu::Menu (Profile profile_in, const std::string& name_in): + m_profile(profile_in), + m_name(name_in) +{ +} + const std::string& Menu::name() const { return m_name; -- cgit v1.2.3 From b56293e7b4fb4b253da17119ad153990744dac3b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 13:17:11 -0600 Subject: as per review, constify getters where possible. This isn't always possible due to system APIs asking for non-const pointers. --- src/menu.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index b263520..696ed2b 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -558,11 +558,6 @@ MenuFactory::MenuFactory(std::shared_ptr& actions_, { } -std::shared_ptr MenuFactory::state() -{ - return m_state; -} - std::shared_ptr MenuFactory::buildMenu(Menu::Profile profile) { -- cgit v1.2.3 From 0f384f4c9607b785d7df4da8566fe2b869ef11e4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 13:28:48 -0600 Subject: as per review, there were a few places that accidentally passed a shared_ptr& instead of a const shared_ptr& --- src/menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 696ed2b..42265c9 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -551,8 +551,8 @@ public: ***** ****/ -MenuFactory::MenuFactory(std::shared_ptr& actions_, - std::shared_ptr& state_): +MenuFactory::MenuFactory(const std::shared_ptr& actions_, + const std::shared_ptr& state_): m_actions(actions_), m_state(state_) { -- cgit v1.2.3 From 197309468247c893bdaa37ef47a98db695b2ea78 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 13:44:12 -0600 Subject: following on the review comment covered in the last commit, use shared_ptr instead of shared_ptr where possible. --- src/menu.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index 42265c9..e92d398 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -70,9 +70,9 @@ class MenuImpl: public Menu protected: MenuImpl(const Menu::Profile profile_in, const std::string& name_in, - std::shared_ptr& state, + std::shared_ptr& state, std::shared_ptr& actions, - std::shared_ptr formatter): + std::shared_ptr formatter): Menu(profile_in, name_in), m_state(state), m_actions(actions), @@ -136,9 +136,9 @@ protected: g_action_group_change_action_state(action_group, action_name.c_str(), state); } - std::shared_ptr m_state; + std::shared_ptr m_state; std::shared_ptr m_actions; - std::shared_ptr m_formatter; + std::shared_ptr m_formatter; GMenu* m_submenu = nullptr; GVariant* get_serialized_alarm_icon() { return m_serialized_alarm_icon; } @@ -450,10 +450,10 @@ class DesktopBaseMenu: public MenuImpl protected: DesktopBaseMenu(Menu::Profile profile_, const std::string& name_, - std::shared_ptr& state_, + std::shared_ptr& state_, std::shared_ptr& actions_): MenuImpl(profile_, name_, state_, actions_, - std::shared_ptr(new DesktopFormatter(state_->clock, state_->settings))) + std::shared_ptr(new DesktopFormatter(state_->clock, state_->settings))) { update_header(); } @@ -477,14 +477,14 @@ protected: class DesktopMenu: public DesktopBaseMenu { public: - DesktopMenu(std::shared_ptr& state_, std::shared_ptr& actions_): + DesktopMenu(std::shared_ptr& state_, std::shared_ptr& actions_): DesktopBaseMenu(Desktop,"desktop", state_, actions_) {} }; class DesktopGreeterMenu: public DesktopBaseMenu { public: - DesktopGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): + DesktopGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): DesktopBaseMenu(DesktopGreeter,"desktop_greeter", state_, actions_) {} }; @@ -493,7 +493,7 @@ class PhoneBaseMenu: public MenuImpl protected: PhoneBaseMenu(Menu::Profile profile_, const std::string& name_, - std::shared_ptr& state_, + std::shared_ptr& state_, std::shared_ptr& actions_): MenuImpl(profile_, name_, state_, actions_, std::shared_ptr(new PhoneFormatter(state_->clock))) @@ -534,7 +534,7 @@ protected: class PhoneMenu: public PhoneBaseMenu { public: - PhoneMenu(std::shared_ptr& state_, + PhoneMenu(std::shared_ptr& state_, std::shared_ptr& actions_): PhoneBaseMenu(Phone, "phone", state_, actions_) {} }; @@ -542,7 +542,7 @@ public: class PhoneGreeterMenu: public PhoneBaseMenu { public: - PhoneGreeterMenu(std::shared_ptr& state_, + PhoneGreeterMenu(std::shared_ptr& state_, std::shared_ptr& actions_): PhoneBaseMenu(PhoneGreeter, "phone_greeter", state_, actions_) {} }; @@ -552,7 +552,7 @@ public: ****/ MenuFactory::MenuFactory(const std::shared_ptr& actions_, - const std::shared_ptr& state_): + const std::shared_ptr& state_): m_actions(actions_), m_state(state_) { -- cgit v1.2.3 From a7a09a5ca5012fb1c48f259d2587542316e7349b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 18:33:14 -0600 Subject: copyediting: as per review, use name_of_thing() instead of get_name_of_thing() or getNameOfThing() --- src/menu.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/menu.cpp') diff --git a/src/menu.cpp b/src/menu.cpp index e92d398..91f7dd2 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -90,12 +90,12 @@ protected: m_formatter->header.changed().connect([this](const std::string&){ update_header(); }); - m_formatter->headerFormat.changed().connect([this](const std::string&){ + m_formatter->header_format.changed().connect([this](const std::string&){ update_section(Locations); // need to update x-canonical-time-format }); - m_formatter->relativeFormatChanged.connect([this](){ - update_section(Appointments); // uses formatter.getRelativeFormat() - update_section(Locations); // uses formatter.getRelativeFormat() + m_formatter->relative_format_changed.connect([this](){ + update_section(Appointments); // uses formatter.relative_format() + update_section(Locations); // uses formatter.relative_format() }); m_state->settings->show_clock.changed().connect([this](bool){ update_header(); // update header's label @@ -110,7 +110,7 @@ protected: m_state->planner->upcoming.changed().connect([this](const std::vector&){ update_section(Appointments); // "upcoming" is the list of Appointments we show }); - m_state->clock->dateChanged.connect([this](){ + m_state->clock->date_changed.connect([this](){ update_section(Calendar); // need to update the Date menuitem update_section(Locations); // locations' relative time may have changed }); @@ -305,7 +305,7 @@ private: GDateTime* begin = appt.begin(); GDateTime* end = appt.end(); - auto fmt = m_formatter->getRelativeFormat(begin, end); + auto fmt = m_formatter->relative_format(begin, end); auto unix_time = g_date_time_to_unix(begin); auto menu_item = g_menu_item_new (appt.summary.c_str(), nullptr); @@ -380,7 +380,7 @@ private: const auto& zone = location.zone(); const auto& name = location.name(); const auto zone_now = now.to_timezone(zone); - const auto fmt = m_formatter->getRelativeFormat(zone_now.get()); + const auto fmt = m_formatter->relative_format(zone_now.get()); auto detailed_action = g_strdup_printf("indicator.set-location::%s %s", zone.c_str(), name.c_str()); auto i = g_menu_item_new (name.c_str(), detailed_action); g_menu_item_set_attribute(i, "x-canonical-type", "s", "com.canonical.indicator.location"); -- cgit v1.2.3