aboutsummaryrefslogtreecommitdiff
path: root/src/menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/menu.cpp')
-rw-r--r--src/menu.cpp137
1 files changed, 58 insertions, 79 deletions
diff --git a/src/menu.cpp b/src/menu.cpp
index bdf92c3..90ef41f 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -22,11 +22,11 @@
#include <datetime/formatter.h>
#include <datetime/state.h>
-#include <json-glib/json-glib.h>
-
#include <glib/gi18n.h>
#include <gio/gio.h>
+#include <vector>
+
namespace unity {
namespace indicator {
namespace datetime {
@@ -62,7 +62,7 @@ GMenuModel* Menu::menu_model()
****/
-#define FALLBACK_ALARM_CLOCK_ICON_NAME "clock"
+#define ALARM_ICON_NAME "alarm-clock"
#define CALENDAR_ICON_NAME "calendar"
class MenuImpl: public Menu
@@ -104,13 +104,16 @@ protected:
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<Appointment>&){
- update_section(Appointments); // "upcoming" is the list of Appointments we show
+ m_state->calendar_upcoming->appointments().changed().connect([this](const std::vector<Appointment>&){
+ update_upcoming(); // our m_upcoming is planner->upcoming() filtered by time
});
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
});
+ m_state->clock->minute_changed.connect([this](){
+ update_upcoming(); // our m_upcoming is planner->upcoming() filtered by time
+ });
m_state->locations->locations.changed().connect([this](const std::vector<Location>&) {
update_section(Locations); // "locations" is the list of Locations we show
});
@@ -133,6 +136,30 @@ protected:
g_action_group_change_action_state(action_group, action_name.c_str(), state);
}
+ void update_upcoming()
+ {
+ // show upcoming appointments that occur after "calendar_next_minute",
+ // where that is the wallclock time on the specified calendar day
+ const auto calendar_day = m_state->calendar_month->month().get();
+ const auto now = m_state->clock->localtime();
+ int y, m, d;
+ calendar_day.ymd(y, m, d);
+ const auto calendar_now = DateTime::Local(y, m, d, now.hour(), now.minute(), now.seconds());
+ const auto calendar_next_minute = calendar_now.add_full(0, 0, 0, 0, 1, -now.seconds());
+
+ std::vector<Appointment> upcoming;
+ for(const auto& a : m_state->calendar_upcoming->appointments().get())
+ if (calendar_next_minute <= a.begin)
+ upcoming.push_back(a);
+
+ if (m_upcoming != upcoming)
+ {
+ m_upcoming.swap(upcoming);
+ update_header(); // show an 'alarm' icon if there are upcoming alarms
+ update_section(Appointments); // "upcoming" is the list of Appointments we show
+ }
+ }
+
std::shared_ptr<const State> m_state;
std::shared_ptr<Actions> m_actions;
std::shared_ptr<const Formatter> m_formatter;
@@ -141,71 +168,19 @@ protected:
GVariant* get_serialized_alarm_icon()
{
if (G_UNLIKELY(m_serialized_alarm_icon == nullptr))
- m_serialized_alarm_icon = create_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()
- {
- 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)
- {
- 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);
- }
-
- if (icon_filename != nullptr)
- {
- GFile* file = g_file_new_for_path(icon_filename);
- GIcon* icon = g_file_icon_new(file);
-
- serialized = g_icon_serialize(icon);
-
- g_object_unref(icon);
- g_object_unref(file);
- 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);
+ auto i = g_themed_icon_new_with_default_fallbacks(ALARM_ICON_NAME);
+ m_serialized_alarm_icon = g_icon_serialize(i);
g_object_unref(i);
}
- return serialized;
+ return m_serialized_alarm_icon;
}
+ std::vector<Appointment> m_upcoming;
+
+private:
+
GVariant* get_serialized_calendar_icon()
{
if (G_UNLIKELY(m_serialized_calendar_icon == nullptr))
@@ -273,7 +248,7 @@ private:
// add calendar
if (show_calendar)
{
- item = g_menu_item_new ("[calendar]", NULL);
+ item = g_menu_item_new ("[calendar]", nullptr);
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",
@@ -292,18 +267,19 @@ private:
void add_appointments(GMenu* menu, Profile profile)
{
- int n = 0;
const int MAX_APPTS = 5;
std::set<std::string> added;
- for (const auto& appt : m_state->planner->upcoming.get())
+ for (const auto& appt : m_upcoming)
{
- if (n++ >= MAX_APPTS)
- break;
-
+ // don't show duplicates
if (added.count(appt.uid))
continue;
+ // don't show too many
+ if (g_menu_model_get_n_items (G_MENU_MODEL(menu)) >= MAX_APPTS)
+ break;
+
added.insert(appt.uid);
GDateTime* begin = appt.begin();
@@ -332,7 +308,7 @@ private:
g_menu_item_set_action_and_target_value (menu_item,
"indicator.activate-appointment",
g_variant_new_string (appt.uid.c_str()));
- else
+ else if (m_actions->can_open_planner())
g_menu_item_set_action_and_target_value (menu_item,
"indicator.activate-planner",
g_variant_new_int64 (unix_time));
@@ -349,13 +325,16 @@ private:
{
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);
+ if (m_actions->can_open_planner())
+ {
+ // 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);
+ }
}
else if (profile==Phone)
{
@@ -508,7 +487,7 @@ protected:
{
// are there alarms?
bool has_alarms = false;
- for(const auto& appointment : m_state->planner->upcoming.get())
+ for(const auto& appointment : m_upcoming)
if((has_alarms = appointment.has_alarms))
break;