[pan2: 205/268] improved tray icons/behaviour



commit af1655d5aa6c7d6bbc9f50e122626ffba6c41134
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Fri Nov 25 14:04:03 2011 +0100

    improved tray icons/behaviour

 pan.cbp                   |    1 +
 pan/data-impl/data-impl.h |   13 ++++
 pan/data-impl/headers.cc  |    6 ++
 pan/gui/actions.cc        |    6 ++
 pan/gui/gui.cc            |    7 ++
 pan/gui/gui.h             |    4 +
 pan/gui/pan-ui.h          |    1 +
 pan/gui/pan.cc            |  138 ++++++++++++++++++++++++++-------------------
 pan/gui/pan.ui.h          |    8 ++-
 pan/gui/prefs-ui.cc       |    4 +-
 pan/icons/Makefile.am     |    3 +-
 11 files changed, 128 insertions(+), 63 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
index 382480f..40f4e66 100644
--- a/pan.cbp
+++ b/pan.cbp
@@ -100,6 +100,7 @@
 		<Unit filename="pan/general/macros.h" />
 		<Unit filename="pan/general/map-vector.h" />
 		<Unit filename="pan/general/messages.h" />
+		<Unit filename="pan/general/non-gui.h" />
 		<Unit filename="pan/general/progress-test.cc" />
 		<Unit filename="pan/general/progress.cc" />
 		<Unit filename="pan/general/progress.h" />
diff --git a/pan/data-impl/data-impl.h b/pan/data-impl/data-impl.h
index fc96789..97c9ce3 100644
--- a/pan/data-impl/data-impl.h
+++ b/pan/data-impl/data-impl.h
@@ -309,6 +309,19 @@ namespace pan
 
     private: // implementation
 
+//      struct Headers
+//      {
+//        struct Listener
+//        {
+//          virtual ~Listener() {}
+//          /* functions that other listeners listen on */
+//          virtual void on_articles_plus (const Quark&, const quarks_t&) = 0;
+//        };
+//      };
+
+//      typedef std::set<Listener*> listeners_t;
+//      listeners_t _header_listeners;
+
       /** 'article' MUST have been allocated by GroupHeaders::alloc_new_article()!! */
       void load_article (const Quark& g, Article * article, const StringView& references);
 
diff --git a/pan/data-impl/headers.cc b/pan/data-impl/headers.cc
index 2198599..24c536c 100644
--- a/pan/data-impl/headers.cc
+++ b/pan/data-impl/headers.cc
@@ -1128,6 +1128,9 @@ DataImpl :: on_articles_removed (const quarks_t& mids) const
 void
 DataImpl :: on_articles_changed (const Quark& group, const quarks_t& mids, bool do_refilter)
 {
+//  for (listeners_t::iterator it(_header_listeners.begin()), end(_header_listeners.end()); it!=end; ++it)
+//    (*it)->on_articles_plus (group, mids);
+
   rescore_articles (group, mids);
 
   // notify the trees that the articles have changed...
@@ -1139,6 +1142,9 @@ void
 DataImpl :: on_articles_added (const Quark& group, const quarks_t& mids)
 {
 
+//  for (listeners_t::iterator it(_header_listeners.begin()), end(_header_listeners.end()); it!=end; ++it)
+//    (*it)->on_articles_plus (group, mids);
+
   if (!mids.empty())
   {
     Log::add_info_va (_("Added %lu articles to %s."),
diff --git a/pan/gui/actions.cc b/pan/gui/actions.cc
index 5b39311..01c30f8 100644
--- a/pan/gui/actions.cc
+++ b/pan/gui/actions.cc
@@ -110,6 +110,7 @@ namespace
   void do_show_task_window             (GtkAction*) { pan_ui->do_show_task_window(); }
   void do_show_log_window              (GtkAction*) { pan_ui->do_show_log_window(); }
   void do_quit                         (GtkAction*) { pan_ui->do_quit(); }
+  void do_quit_mainloop                (GtkAction*) { pan_ui->do_quit_mainloop(); }
   void do_clear_header_pane            (GtkAction*) { pan_ui->do_clear_header_pane(); }
   void do_clear_body_pane              (GtkAction*) { pan_ui->do_clear_body_pane(); }
   void do_select_all_articles          (GtkAction*) { pan_ui->do_select_all_articles(); }
@@ -366,6 +367,11 @@ namespace
       NULL,
       G_CALLBACK(do_quit) },
 
+    {
+      "quit-mainloop",NULL,
+      NULL, "", NULL,
+      G_CALLBACK(do_quit_mainloop) },
+
     { "select-all-articles", NULL,
       N_("Select _All Articles"), "<control>D",
       NULL,
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 628ee9a..71aa4b6 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -30,6 +30,7 @@ extern "C" {
 
 }
 #include <pan/general/debug.h>
+#include <pan/general/non-gui.h>
 #include <pan/general/e-util.h>
 #include <pan/general/file-util.h>
 #include <pan/general/macros.h>
@@ -1759,6 +1760,12 @@ void GUI :: do_quit ()
   gtk_main_quit ();
 }
 
+void GUI :: do_quit_mainloop ()
+{
+  mainloop_quit();
+}
+
+
 void GUI :: do_read_selected_group ()
 {
   const Quark group (_group_pane->get_first_selection ());
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index d81ed31..a8831ea 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -83,6 +83,7 @@ namespace pan
       virtual void do_save_articles_to_nzb ();
       virtual void do_print ();
       virtual void do_quit ();
+      virtual void do_quit_mainloop ();
       virtual void do_import_tasks ();
       virtual void do_cancel_latest_task ();
       virtual void do_show_task_window ();
@@ -256,6 +257,9 @@ namespace pan
       static void prefs_dialog_destroyed_cb (GtkWidget * w, gpointer self);
       void prefs_dialog_destroyed (GtkWidget* w);
       int score_int_from_string(std::string val, const char* rules[]);
+
+    public:
+      GtkUIManager* get_ui_manager() { return _ui_manager; }
   };
 }
 
diff --git a/pan/gui/pan-ui.h b/pan/gui/pan-ui.h
index 2cac8b5..b31f607 100644
--- a/pan/gui/pan-ui.h
+++ b/pan/gui/pan-ui.h
@@ -82,6 +82,7 @@ namespace pan
     virtual void do_tip_jar () = 0;
     virtual void do_about_pan () = 0;
     virtual void do_quit () = 0;
+    virtual void do_quit_mainloop () = 0;
 
     virtual void do_show_task_window () = 0;
     virtual void do_show_log_window () = 0;
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index b4aeda8..3139344 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -146,35 +146,37 @@ namespace
   }
 
 /* ****** Status Icon **********************************************************/
-
-namespace
-{
-  enum StatusIcons
+  namespace
   {
-    ICON_STATUS_ONLINE,
-    ICON_STATUS_OFFLINE,
-    ICON_STATUS_ACTIVE,
-    ICON_STATUS_QUEUE_EMPTY,
-    ICON_STATUS_ERROR,
-    ICON_STATUS_IDLE,
-    ICON_NUM_STATUS_ICONS
-  };
-
-  struct Icon {
-  const guint8 * pixbuf_txt;
-  GdkPixbuf * pixbuf;
-  } status_icons[ICON_NUM_STATUS_ICONS] = {
-    { icon_status_online,          0 },
-    { icon_status_offline,         0 },
-    { icon_status_active,          0 },
-    { icon_status_queue_empty,     0 },
-    { icon_status_error,           0 },
-    { icon_status_idle,            0 }
-  };
-}
+    enum StatusIcons
+    {
+      ICON_STATUS_ONLINE,
+      ICON_STATUS_OFFLINE,
+      ICON_STATUS_ACTIVE,
+      ICON_STATUS_QUEUE_EMPTY,
+      ICON_STATUS_ERROR,
+      ICON_STATUS_IDLE,
+      ICON_STATUS_NEW_ARTICLES,
+      ICON_NUM_STATUS_ICONS
+    };
+
+    struct Icon {
+    const guint8 * pixbuf_txt;
+    GdkPixbuf * pixbuf;
+    } status_icons[ICON_NUM_STATUS_ICONS] = {
+      { icon_status_online,          0 },
+      { icon_status_offline,         0 },
+      { icon_status_active,          0 },
+      { icon_status_queue_empty,     0 },
+      { icon_status_error,           0 },
+      { icon_status_idle,            0 },
+      { icon_status_new_articles,    0 }
+    };
+  }
 
-  struct StatusIconListener : public  Prefs::Listener,
-                              public  Queue::Listener
+  struct StatusIconListener : public Prefs::Listener,
+                              public Queue::Listener,
+                              public Data::Listener
   {
 
     static gboolean status_icon_periodic_refresh (gpointer p)
@@ -182,23 +184,26 @@ namespace
       static_cast<StatusIconListener*>(p)->update_status_tooltip();
     }
 
-    StatusIconListener(GtkStatusIcon * i, Prefs& p, Queue& q) : icon(i), prefs(p), queue(q),
-      tasks_active(0), tasks_total(0), is_online(false), blinked_cnt(0)
+    StatusIconListener(GtkStatusIcon * i, GtkWidget* r, Prefs& p, Queue& q, Data& d, bool v) : icon(i), root(r), prefs(p), queue(q), data(d),
+      tasks_active(0), tasks_total(0), is_online(false)
     {
       prefs.add_listener(this);
       queue.add_listener(this);
+      data.add_listener(this);
       update_status_tooltip();
-      status_icon_timeout_tag = g_timeout_add (250, status_icon_periodic_refresh, this);
+      status_icon_timeout_tag = g_timeout_add (500, status_icon_periodic_refresh, this);
     }
 
     ~StatusIconListener()
     {
       prefs.remove_listener(this);
       queue.remove_listener(this);
+      data.remove_listener(this);
       g_source_remove (status_icon_timeout_tag);
     }
 
-    void on_prefs_flag_changed (const StringView &key, bool value)
+    /* prefs::listener */
+    virtual void on_prefs_flag_changed (const StringView &key, bool value)
     {
        if(key == "status-icon")
          gtk_status_icon_set_visible(icon, value);
@@ -218,28 +223,32 @@ namespace
                                   tasks_active, tasks_total, queue.get_speed_KiBps());
       gtk_status_icon_set_tooltip_markup(icon, buf);
     }
-
     void update_status_icon(StatusIcons si)
     {
-      if (si == ICON_STATUS_ONLINE)
-        gtk_status_icon_set_from_stock(icon, GTK_STOCK_CONNECT);
-      else if (si == ICON_STATUS_OFFLINE)
-        gtk_status_icon_set_from_stock(icon, GTK_STOCK_DISCONNECT);
-      else
+      if (si==ICON_STATUS_IDLE)
+      {
+        if (is_online)
+          gtk_status_icon_set_from_pixbuf(icon, status_icons[ICON_STATUS_ONLINE].pixbuf);
+        else
+          gtk_status_icon_set_from_pixbuf(icon, status_icons[ICON_STATUS_OFFLINE].pixbuf);
+      } else
         gtk_status_icon_set_from_pixbuf(icon, status_icons[si].pixbuf);
     }
 
+    /* queue::listener */
     virtual void on_queue_task_active_changed (Queue&, Task&, bool active)
     {
-      if (active) ++tasks_active; else --tasks_active; update_status_tooltip();
+      update_status_tooltip();
     }
     virtual void on_queue_tasks_added (Queue&, int index UNUSED, int count)
     {
-      tasks_total += count; update_status_tooltip();
+      tasks_total += count;
+      update_status_tooltip();
+      update_status_icon(ICON_STATUS_ACTIVE);
     }
     virtual void on_queue_task_removed (Queue&, Task&, int pos UNUSED)
     {
-      --tasks_total;
+      update_status_icon(ICON_STATUS_ACTIVE);
     }
     virtual void on_queue_task_moved (Queue&, Task&, int new_pos UNUSED, int old_pos UNUSED) {}
     virtual void on_queue_connection_count_changed (Queue&, int count) {}
@@ -247,31 +256,54 @@ namespace
     {
       tasks_total = total;
       tasks_active = active;
+      if (tasks_total == 0 || tasks_active == 0)
+      {
+        update_status_icon(ICON_STATUS_IDLE);
+      }
       update_status_tooltip();
     }
+
     virtual void on_queue_online_changed (Queue&, bool online)
     {
       is_online = online;
-      update_status_icon(is_online ? ICON_STATUS_ONLINE : ICON_STATUS_OFFLINE);
+      update_status_icon(ICON_STATUS_IDLE);
       update_status_tooltip();
     }
+
     virtual void on_queue_error (Queue&, const StringView& message)
     {
       update_status_icon(ICON_STATUS_ERROR);
     }
 
+    /* data::listener */
+    virtual void on_group_counts (const Quark&, unsigned long, unsigned long)
+    {
+      update_status_icon(ICON_STATUS_NEW_ARTICLES);
+    }
+
     private:
-      GtkStatusIcon *icon;
       Queue& queue;
       Prefs& prefs;
+      Data& data;
       int tasks_active;
       int tasks_total;
-      int blinked_cnt;
       bool is_online;
       guint status_icon_timeout_tag;
+
+    public:
+      GtkStatusIcon *icon;
+      GtkWidget* root;
   };
 
-  StatusIconListener* _status_icon;
+  static StatusIconListener* _status_icon;
+/* ****** End Status Icon ******************************************************/
+
+  void status_icon_activate (GtkStatusIcon *icon, gpointer data)
+  {
+    gtk_widget_show(GTK_WIDGET(data));
+    gtk_window_deiconify(GTK_WINDOW(data));
+
+  }
 
   static gboolean window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer trayIcon)
   {
@@ -284,20 +316,11 @@ namespace
     else if(event->changed_mask == GDK_WINDOW_STATE_WITHDRAWN && (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED ||
                                                                   event->new_window_state == (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED)))
     {
-        gtk_widget_show (GTK_WIDGET(widget));
         gtk_status_icon_set_visible(GTK_STATUS_ICON(trayIcon), FALSE);
     }
     return TRUE;
   }
 
-
-  void status_icon_activate (GtkStatusIcon *icon, gpointer data)
-  {
-    GtkWindow * window = GTK_WINDOW(data);
-    gtk_widget_show(GTK_WIDGET(window));
-    gtk_window_deiconify(GTK_WINDOW(window));
-  }
-
   void status_icon_popup_menu (GtkStatusIcon *icon,
                                guint button,
                                guint activation_time,
@@ -307,7 +330,7 @@ namespace
     gtk_menu_popup(menu, NULL, NULL, NULL, NULL, button, activation_time);
   }
 
-  void run_pan_with_status_icon (GtkWindow * window, GdkPixbuf * pixbuf, Queue& queue, Prefs & prefs)
+  void run_pan_with_status_icon (GtkWindow * window, GdkPixbuf * pixbuf, Queue& queue, Prefs & prefs, Data& data)
   {
     for (guint i=0; i<ICON_NUM_STATUS_ICONS; ++i)
         status_icons[i].pixbuf = gdk_pixbuf_new_from_inline (-1, status_icons[i].pixbuf_txt, FALSE, 0);
@@ -316,16 +339,15 @@ namespace
     GtkWidget * menu = gtk_menu_new ();
     GtkWidget * menu_quit = gtk_image_menu_item_new_from_stock ( GTK_STOCK_QUIT, NULL);
     gtk_status_icon_set_visible(icon, prefs.get_flag("status-icon", false));
-    StatusIconListener* pl = _status_icon = new StatusIconListener(icon, prefs, queue);
+    StatusIconListener* pl = _status_icon = new StatusIconListener(icon, GTK_WIDGET(window), prefs, queue, data, prefs.get_flag("start-minimized", false));
     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_quit);
     gtk_widget_show_all(menu);
     g_signal_connect(icon, "activate", G_CALLBACK(status_icon_activate), window);
     g_signal_connect(icon, "popup-menu", G_CALLBACK(status_icon_popup_menu), menu);
     g_signal_connect(menu_quit, "activate", G_CALLBACK(mainloop_quit), NULL);
-//    g_signal_connect (G_OBJECT (window), "window-state-event", G_CALLBACK (window_state_event), icon);
+    g_signal_connect (G_OBJECT (window), "window-state-event", G_CALLBACK (window_state_event), icon);
   }
 
-/* ****** End Status Icon ******************************************************/
 
   void run_pan_in_window (Data          & data,
                           Queue         & queue,
@@ -598,7 +620,7 @@ main (int argc, char *argv[])
       gtk_window_set_title (GTK_WINDOW(window), "Pan");
       gtk_window_set_resizable (GTK_WINDOW(window), true);
       gtk_window_set_default_icon (pixbuf);
-      run_pan_with_status_icon(GTK_WINDOW(window), pixbuf, queue, prefs);
+      run_pan_with_status_icon(GTK_WINDOW(window), pixbuf, queue, prefs, data);
       g_object_unref (pixbuf);
       run_pan_in_window (data, queue, prefs, group_prefs, GTK_WINDOW(window));
     }
diff --git a/pan/gui/pan.ui.h b/pan/gui/pan.ui.h
index 82ec450..83525de 100644
--- a/pan/gui/pan.ui.h
+++ b/pan/gui/pan.ui.h
@@ -94,9 +94,6 @@ const char * fallback_ui_file =
 "      <menuitem action='read-next-thread' />\n"
 "      <menuitem action='read-previous-thread' />\n"
 "    </menu>\n"
-//"    <menu action='actions-menu'>\n"
-//"      <menuitem action='save-articles' />\n"
-//"      <separator />\n"
 "      <menu action='group-actions-menu'>\n"
 "        <menuitem action='read-selected-group' />\n"
 "        <menuitem action='mark-groups-read' />\n"
@@ -224,5 +221,10 @@ const char * fallback_ui_file =
 "    <separator />\n"
 "    <menuitem action='delete-groups-articles' />\n"
 "  </popup>\n"
+"  <popup name='tray-icon-popup'>\n"
+"    <menuitem action='quit-mainloop' />\n"
+"    <separator />\n"
+"    <menuitem action='work-online' />\n"
+"  </popup>\n"
 "\n"
 "</ui>\n";
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index acb78c2..a37971a 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -543,7 +543,9 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
     HIG::workarea_add_row (t, &row, w, l);
     HIG :: workarea_add_section_title (t, &row, _("Status Icon"));
     HIG :: workarea_add_section_spacer (t, row, 3);
-    w = new_check_button (_("Hide window to system tray instead of closing it"), "status-icon", true, prefs);
+    w = new_check_button (_("Hide window to system tray instead of closing it"), "status-icon", false, prefs);
+    HIG :: workarea_add_wide_control (t, &row, w);
+    w = new_check_button (_("Start Pan minimized"),  "start-minimized", false, prefs);
     HIG :: workarea_add_wide_control (t, &row, w);
   HIG :: workarea_finish (t, &row);
   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("_Behavior")));
diff --git a/pan/icons/Makefile.am b/pan/icons/Makefile.am
index 39d669d..d95a5dd 100644
--- a/pan/icons/Makefile.am
+++ b/pan/icons/Makefile.am
@@ -52,7 +52,8 @@ stock_images = \
   icon_status_active.png \
   icon_status_queue_empty.png \
   icon_status_error.png \
-  icon_status_idle.png
+  icon_status_idle.png \
+  icon_status_new_articles.png
 
 
 EXTRA_DIST = \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]