[pan2] https://bugzilla.gnome.org/show_bug.cgi?id=679274
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2] https://bugzilla.gnome.org/show_bug.cgi?id=679274
- Date: Mon, 9 Jul 2012 05:30:52 +0000 (UTC)
commit 29da552d63e9511338b62ea645915a1ded22b2a8
Author: Heinrich MÃller <henmull src gnome org>
Date: Mon Jul 9 07:29:02 2012 +0200
https://bugzilla.gnome.org/show_bug.cgi?id=679274
pan/gui/header-pane.cc | 12 +-
pan/gui/task-pane.cc | 262 +++++++++++++++++++++++++++++++++++++++++++++++-
pan/gui/task-pane.h | 8 ++-
3 files changed, 274 insertions(+), 8 deletions(-)
---
diff --git a/pan/gui/header-pane.cc b/pan/gui/header-pane.cc
index 68e4a29..aecf1e3 100644
--- a/pan/gui/header-pane.cc
+++ b/pan/gui/header-pane.cc
@@ -1783,12 +1783,12 @@ HeaderPane :: create_filter_entry ()
g_signal_connect (entry, "activate", G_CALLBACK(search_entry_activated), this);
entry_changed_tag = g_signal_connect (entry, "changed", G_CALLBACK(search_entry_changed), this);
- gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
- GTK_ENTRY_ICON_PRIMARY,
- GTK_STOCK_FIND);
- gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
- GTK_ENTRY_ICON_SECONDARY,
- GTK_STOCK_CLEAR );
+ gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+ GTK_ENTRY_ICON_PRIMARY,
+ GTK_STOCK_FIND);
+ gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_CLEAR );
bool regex = _prefs.get_flag ("use-regex", false);
GtkWidget * menu = gtk_menu_new ();
diff --git a/pan/gui/task-pane.cc b/pan/gui/task-pane.cc
index 11cdfcc..9a730b4 100644
--- a/pan/gui/task-pane.cc
+++ b/pan/gui/task-pane.cc
@@ -713,6 +713,256 @@ namespace
}
}
+namespace
+{
+ // the text typed by the user.
+ std::string search_text;
+
+ guint entry_changed_tag (0u);
+ guint activate_soon_tag (0u);
+
+ // AUTHOR, SUBJECT, SUBJECT_OR_AUTHOR, or MESSAGE_ID
+ int search_mode;
+
+ void set_search_entry (GtkWidget * entry, const char * s)
+ {
+ g_signal_handler_block (entry, entry_changed_tag);
+ gtk_entry_set_text (GTK_ENTRY(entry), s);
+ g_signal_handler_unblock (entry, entry_changed_tag);
+ }
+
+ gboolean search_entry_focus_in_cb (GtkWidget * w,
+ GdkEventFocus * ,
+ gpointer )
+ {
+#if !GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_modify_text (w, GTK_STATE_NORMAL, NULL); // resets
+#else
+ gtk_widget_override_color (w, GTK_STATE_FLAG_NORMAL, NULL);
+#endif
+ set_search_entry (w, search_text.c_str());
+ return false;
+ }
+
+ const char * mode_strings [] =
+ {
+ N_("Subject or Author"),
+ N_("Sub or Auth (regex)"),
+ N_("Subject"),
+ N_("Author"),
+ N_("Message-ID"),
+ };
+
+ enum
+ {
+ SUBJECT_OR_AUTHOR=0,
+ SUBJECT_OR_AUTHOR_REGEX=1,
+ SUBJECT=2,
+ AUTHOR=3,
+ MESSAGE_ID=4
+ };
+
+ void refresh_search_entry (GtkWidget * w)
+ {
+ if (search_text.empty() && !gtk_widget_has_focus(w))
+ {
+#if !GTK_CHECK_VERSION(3,0,0)
+ GdkColor c;
+ c.pixel = 0;
+ c.red = c.green = c.blue = 0xAAAA;
+ gtk_widget_modify_text (w, GTK_STATE_NORMAL, &c);
+#else
+ GdkRGBA c;
+ gdk_rgba_parse (&c, "0xAAA");
+ gtk_widget_override_color(w, GTK_STATE_FLAG_NORMAL, &c);
+#endif
+ set_search_entry (w, _(mode_strings[search_mode]));
+ }
+ }
+
+ gboolean search_entry_focus_out_cb (GtkWidget * w,
+ GdkEventFocus * ,
+ gpointer )
+ {
+ refresh_search_entry (w);
+ return false;
+ }
+
+ void search_activate (TaskPane * h)
+ {
+ h->filter (search_text, search_mode);
+ }
+
+ void remove_activate_soon_tag ()
+ {
+ if (activate_soon_tag != 0)
+ {
+ g_source_remove (activate_soon_tag);
+ activate_soon_tag = 0;
+ }
+ }
+
+ void search_entry_activated (GtkEntry *, gpointer h_gpointer)
+ {
+ search_activate (static_cast<TaskPane*>(h_gpointer));
+ remove_activate_soon_tag ();
+ }
+
+ gboolean activated_timeout_cb (gpointer h_gpointer)
+ {
+ search_activate (static_cast<TaskPane*>(h_gpointer));
+ remove_activate_soon_tag ();
+ return false; // remove the source
+ }
+
+ // ensure there's exactly one activation timeout
+ // and that it's set to go off in a half second from now.
+ void bump_activate_soon_tag (TaskPane * h)
+ {
+ remove_activate_soon_tag ();
+ activate_soon_tag = g_timeout_add (500, activated_timeout_cb, h);
+ }
+
+ // when the user changes the filter text,
+ // update our state variable and bump the activate timeout.
+ void search_entry_changed (GtkEditable * e, gpointer h_gpointer)
+ {
+ search_text = gtk_entry_get_text (GTK_ENTRY(e));
+ bump_activate_soon_tag (static_cast<TaskPane*>(h_gpointer));
+ refresh_search_entry (GTK_WIDGET(e));
+ }
+
+ // when the search mode is changed via the menu,
+ // update our state variable and bump the activate timeout.
+ void search_menu_toggled_cb (GtkCheckMenuItem * menu_item,
+ gpointer entry_g)
+ {
+ if (gtk_check_menu_item_get_active (menu_item))
+ {
+ search_mode = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(menu_item), "MODE"));
+ refresh_search_entry (GTK_WIDGET(entry_g));
+ TaskPane * h = (TaskPane*) g_object_get_data (G_OBJECT(entry_g), "pane");
+ bump_activate_soon_tag (h);
+ }
+ }
+
+ void entry_icon_release (GtkEntry*, GtkEntryIconPosition icon_pos, GdkEventButton*, gpointer menu)
+ {
+ if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
+ gtk_menu_popup (GTK_MENU(menu), 0, 0, 0, 0, 0, gtk_get_current_event_time());
+ }
+
+ void entry_icon_release_2 (GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton*, gpointer pane_gpointer)
+ {
+ if (icon_pos == GTK_ENTRY_ICON_SECONDARY) {
+ set_search_entry (GTK_WIDGET(entry), "");
+ refresh_search_entry (GTK_WIDGET(entry));
+ search_text.clear ();
+ search_entry_activated (NULL, pane_gpointer);
+ }
+ }
+
+ gboolean filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer gdata)
+ {
+
+ if (search_text.empty()) return true;
+
+ Task *task(0);
+ /* Get value from column */
+ gtk_tree_model_get( GTK_TREE_MODEL(model), iter, COL_TASK_POINTER, &task, -1 );
+
+ TaskArticle* ta (dynamic_cast<TaskArticle*>(task));
+
+/* SUBJECT_OR_AUTHOR=0,
+ SUBJECT_OR_AUTHOR_REGEX=1,
+ SUBJECT=2,
+ AUTHOR=3,
+ MESSAGE_ID=4
+*/
+ if (ta)
+ {
+ std::string s1("");
+ if (search_mode == 0)
+ {
+ s1 = ta->get_article().author.c_str();
+ if (s1.find(search_text) != s1.npos) return true;
+ s1 = ta->get_article().subject.c_str();
+ }
+ if (search_mode == 1)
+ {
+ GRegexCompileFlags cf0((GRegexCompileFlags)0);
+ GRegexMatchFlags mf0((GRegexMatchFlags)0);
+ GRegex* rex = g_regex_new (search_text.c_str(), cf0, mf0, NULL);
+ if (!rex) return false;
+ return g_regex_match (rex, ta->get_article().subject.c_str(), G_REGEX_MATCH_NOTEMPTY, NULL) ||
+ g_regex_match (rex, ta->get_article().author.c_str(), G_REGEX_MATCH_NOTEMPTY, NULL);
+ }
+ if (search_mode == 2)
+ s1 = ta->get_article().subject.c_str();
+ if (search_mode == 3)
+ s1 = ta->get_article().author.c_str();
+ if (search_mode == 4)
+ s1 = ta->get_article().message_id.c_str();
+
+ if (s1.find(search_text) != s1.npos) return true;
+ }
+
+ return false;
+
+ }
+}
+
+void
+TaskPane :: filter (const std::string& text, int mode)
+{
+ search_text = text;
+ search_mode = mode;
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(GTK_TREE_VIEW(_view))));
+}
+
+GtkWidget*
+TaskPane :: create_filter_entry ()
+{
+ GtkWidget * entry = gtk_entry_new ();
+// _action_manager.disable_accelerators_when_focused (entry);
+ g_object_set_data (G_OBJECT(entry), "pane", this);
+ g_signal_connect (entry, "focus-in-event", G_CALLBACK(search_entry_focus_in_cb), NULL);
+ g_signal_connect (entry, "focus-out-event", G_CALLBACK(search_entry_focus_out_cb), NULL);
+ g_signal_connect (entry, "activate", G_CALLBACK(search_entry_activated), this);
+ entry_changed_tag = g_signal_connect (entry, "changed", G_CALLBACK(search_entry_changed), this);
+
+ gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+ GTK_ENTRY_ICON_PRIMARY,
+ GTK_STOCK_FIND);
+ gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_CLEAR );
+
+ bool regex = false;//_prefs.get_flag ("use-regex", false);
+ GtkWidget * menu = gtk_menu_new ();
+ if (regex == true )
+ search_mode = 1;
+ else
+ search_mode = 0;
+ GSList * l = 0;
+ for (int i=0, qty=G_N_ELEMENTS(mode_strings); i<qty; ++i) {
+ GtkWidget * w = gtk_radio_menu_item_new_with_label (l, _(mode_strings[i]));
+ l = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM(w));
+ g_object_set_data (G_OBJECT(w), "MODE", GINT_TO_POINTER(i));
+ g_signal_connect (w, "toggled", G_CALLBACK(search_menu_toggled_cb),entry);
+ if (search_mode == i)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(w), TRUE);
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), w);
+ gtk_widget_show (w);
+ }
+ g_signal_connect (entry, "icon-release", G_CALLBACK(entry_icon_release), menu);
+ g_signal_connect (entry, "icon-release", G_CALLBACK(entry_icon_release_2), this);
+
+ refresh_search_entry (entry);
+
+ return entry;
+}
+
TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
{
_root = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -760,7 +1010,6 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
GtkWidget * hbox = gtk_hbox_new (false, PAD);
w = _status_label = gtk_label_new (0);
gtk_box_pack_start (GTK_BOX(hbox), w, false, false, PAD_SMALL);
- gtk_box_pack_start (GTK_BOX(vbox), hbox, false, false, PAD);
_store = gtk_list_store_new (NUM_COLS, G_TYPE_POINTER, G_TYPE_INT);
_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(_store));
@@ -785,6 +1034,17 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
add_actions(_view);
gtk_window_add_accel_group (GTK_WINDOW(_root), gtk_ui_manager_get_accel_group (_uim));
+ // search filter
+ gtk_box_pack_start (GTK_BOX(hbox), gtk_vseparator_new(), 0, 0, 0);
+ gtk_box_pack_start (GTK_BOX(hbox), create_filter_entry(), false, false, PAD);
+ GtkTreeModel* initial_model= gtk_tree_view_get_model(GTK_TREE_VIEW( _view ));
+ GtkTreeModel* filter_model = gtk_tree_model_filter_new( initial_model, NULL );
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER ( filter_model ),(GtkTreeModelFilterVisibleFunc) filter_visible_func, NULL, NULL);
+ gtk_tree_view_set_model( GTK_TREE_VIEW( _view ),filter_model);
+ g_object_unref( filter_model );
+
+ gtk_box_pack_start (GTK_BOX(vbox), hbox, false, false, PAD);
+
w = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(w), GTK_SHADOW_IN);
diff --git a/pan/gui/task-pane.h b/pan/gui/task-pane.h
index 736e495..0ac1efc 100644
--- a/pan/gui/task-pane.h
+++ b/pan/gui/task-pane.h
@@ -94,7 +94,13 @@ namespace pan
static void get_selected_tasks_foreach (GtkTreeModel*, GtkTreePath*, GtkTreeIter*, gpointer);
static void online_toggled_cb (GtkToggleButton*, Queue*);
- public: /// FIXME, privatize this again...
+ private:
+ GtkWidget* create_filter_entry ();
+
+ public:
+ void filter (const std::string& text, int mode);
+
+ public:
static void up_clicked_cb (GtkButton*, TaskPane*);
static void down_clicked_cb (GtkButton*, TaskPane*);
static void top_clicked_cb (GtkButton*, TaskPane*);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]