From 45c95b06f330c6f57a0d552671406c384ed7fdb9 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Mon, 15 Nov 2010 08:43:00 +0200 Subject: * move mug/ to toys/mug --- Makefile.am | 8 +- configure.ac | 11 +- mug/Makefile.am | 69 ------ mug/TODO | 28 --- mug/mug-msg-list-view.c | 408 ---------------------------------- mug/mug-msg-list-view.h | 70 ------ mug/mug-msg-view.c | 298 ------------------------- mug/mug-msg-view.h | 63 ------ mug/mug-query-bar.c | 141 ------------ mug/mug-query-bar.h | 48 ---- mug/mug-shortcuts.c | 155 ------------- mug/mug-shortcuts.h | 69 ------ mug/mug.cc | 338 ---------------------------- mug/mug.desktop.in | 12 - mug/mug.svg | 510 ------------------------------------------- toys/Makefile.am | 25 +++ toys/mug/Makefile.am | 69 ++++++ toys/mug/TODO | 28 +++ toys/mug/mug-msg-list-view.c | 408 ++++++++++++++++++++++++++++++++++ toys/mug/mug-msg-list-view.h | 70 ++++++ toys/mug/mug-msg-view.c | 298 +++++++++++++++++++++++++ toys/mug/mug-msg-view.h | 63 ++++++ toys/mug/mug-query-bar.c | 141 ++++++++++++ toys/mug/mug-query-bar.h | 48 ++++ toys/mug/mug-shortcuts.c | 155 +++++++++++++ toys/mug/mug-shortcuts.h | 69 ++++++ toys/mug/mug.cc | 338 ++++++++++++++++++++++++++++ toys/mug/mug.desktop.in | 12 + toys/mug/mug.svg | 510 +++++++++++++++++++++++++++++++++++++++++++ 29 files changed, 2241 insertions(+), 2221 deletions(-) delete mode 100644 mug/Makefile.am delete mode 100644 mug/TODO delete mode 100644 mug/mug-msg-list-view.c delete mode 100644 mug/mug-msg-list-view.h delete mode 100644 mug/mug-msg-view.c delete mode 100644 mug/mug-msg-view.h delete mode 100644 mug/mug-query-bar.c delete mode 100644 mug/mug-query-bar.h delete mode 100644 mug/mug-shortcuts.c delete mode 100644 mug/mug-shortcuts.h delete mode 100644 mug/mug.cc delete mode 100644 mug/mug.desktop.in delete mode 100644 mug/mug.svg create mode 100644 toys/Makefile.am create mode 100644 toys/mug/Makefile.am create mode 100644 toys/mug/TODO create mode 100644 toys/mug/mug-msg-list-view.c create mode 100644 toys/mug/mug-msg-list-view.h create mode 100644 toys/mug/mug-msg-view.c create mode 100644 toys/mug/mug-msg-view.h create mode 100644 toys/mug/mug-query-bar.c create mode 100644 toys/mug/mug-query-bar.h create mode 100644 toys/mug/mug-shortcuts.c create mode 100644 toys/mug/mug-shortcuts.h create mode 100644 toys/mug/mug.cc create mode 100644 toys/mug/mug.desktop.in create mode 100644 toys/mug/mug.svg diff --git a/Makefile.am b/Makefile.am index 499b99d..d1ec008 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,13 +16,7 @@ include $(top_srcdir)/gtest.mk -SUBDIRS=man src contrib - -# build if there is some gtk available -if HAVE_GTK -SUBDIRS += mug -endif - +SUBDIRS=man src contrib toys # so we can say 'make test' check: test cleanupnote diff --git a/configure.ac b/configure.ac index c53cdc7..71099b4 100644 --- a/configure.ac +++ b/configure.ac @@ -153,8 +153,9 @@ AC_CONFIG_FILES([ Makefile src/Makefile src/tests/Makefile -mug/Makefile -mug/mug.desktop +toys/Makefile +toys/mug/Makefile +toys/mug/mug.desktop man/Makefile contrib/Makefile ]) @@ -165,9 +166,9 @@ echo "mu configuration is complete." echo "-----------------------------" echo -echo "Note: the Xapian database is no longer stored as /xapian-0.6" -echo "but instead simply as /xapian. You can remove the older" -echo "/xapian-0.6 directory to save some disk space" +echo "Note: since version 0.7, the Xapian database is no longer stored as " +echo "/xapian-0.6 but instead simply as /xapian. You can " +echo "remove the olde /xapian-0.6 directory to save some disk space" echo echo "type 'make' to build mu, or 'make check' to run the unit tests." diff --git a/mug/Makefile.am b/mug/Makefile.am deleted file mode 100644 index 337c5ab..0000000 --- a/mug/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ -## Copyright (C) 2008-2010 Dirk-Jan C. Binnema -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY 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, write to the Free Software Foundation, -## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -include $(top_srcdir)/gtest.mk - -# enforce compiling this dir first before decending into tests/ -SUBDIRS= . - -#if HAVE_GTEST -#SUBDIRS += tests -#endif - -INCLUDES=-I${top_srcdir}/src $(GTK_CFLAGS) - -# don't use -Werror, as it might break on other compilers -# use -Wno-unused-parameters, because some callbacks may not -# really need all the params they get -AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement -AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter -DICONDIR='"$(icondir)"' \ - -DICONDIR='"$(icondir)"' - -bin_PROGRAMS= \ - mug - -# note, mu.cc is only '.cc' and not '.c' because libmu must explicitly -# be linked as c++, not c. -mug_SOURCES= \ - mug.cc \ - mug-msg-list-view.c \ - mug-msg-list-view.h \ - mug-msg-view.h \ - mug-msg-view.c \ - mug-query-bar.h \ - mug-query-bar.c \ - mug-shortcuts.c \ - mug-shortcuts.h - -mug_LDADD= \ - ${top_builddir}/src/libmu.la \ - ${GTK_LIBS} - -icondir= \ - $(datarootdir)/icons - -icon_DATA= \ - ${top_srcdir}/mug/mug.svg - -desktopdir= \ - $(datarootdir)/applications - -desktop_DATA= \ - mug.desktop - -EXTRA_DIST= \ - $(desktopentry_DATA) - diff --git a/mug/TODO b/mug/TODO deleted file mode 100644 index 745f4e8..0000000 --- a/mug/TODO +++ /dev/null @@ -1,28 +0,0 @@ -* todo for mug - - - [X] column sizing - - [X] query in status bar - - [X] tool bar working - - [X] pretty-print addresses - - [X] pretty-print dates - - [X] up/down arrows => need msg-list-view support - - [X] unread mails => bold, important mails => red - - [X] detail info about current msg - - [X] guess maildir - - [ ] bookmarks - - [ ] icon / .desktop file - - [X] clear msg when starting new query - - [X] focus search bar at startup - - [X] focus first msg after query - - [X] sorting for columns - - [X] add about menu - - [X] make scrollbars automatic - - [ ] progress-bar, incremental - - [ ] cmdline arg for mu home dir - - [ ] error messages if there's no db / old db - -# Local Variables: -# mode: org; org-startup-folded: t -# End: - - diff --git a/mug/mug-msg-list-view.c b/mug/mug-msg-list-view.c deleted file mode 100644 index 0eb1457..0000000 --- a/mug/mug-msg-list-view.c +++ /dev/null @@ -1,408 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#include "mug-msg-list-view.h" -#include "mu-query.h" -#include "mu-msg-str.h" -/* include other impl specific header files */ - -/* 'private'/'protected' functions */ -static void mug_msg_list_view_class_init (MugMsgListViewClass *klass); -static void mug_msg_list_view_init (MugMsgListView *obj); -static void mug_msg_list_view_finalize (GObject *obj); - -/* list my signals */ -enum { - MUG_MSG_SELECTED, - LAST_SIGNAL -}; - - -enum { - MUG_COL_DATE, - MUG_COL_MAILDIR, - MUG_COL_FLAGSSTR, - MUG_COL_FROM, - MUG_COL_TO, - MUG_COL_SUBJECT, - MUG_COL_PATH, - MUG_COL_PRIO, - MUG_COL_FLAGS, - - MUG_N_COLS -}; - -typedef struct _MugMsgListViewPrivate MugMsgListViewPrivate; -struct _MugMsgListViewPrivate { - GtkListStore *_store; - char *_xpath; - char *_query; -}; -#define MUG_MSG_LIST_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_MSG_LIST_VIEW, \ - MugMsgListViewPrivate)) -/* globals */ -static GtkTreeViewClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (MugMsgListView, mug_msg_list_view, GTK_TYPE_TREE_VIEW); - - -static void -mug_msg_list_view_class_init (MugMsgListViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = mug_msg_list_view_finalize; - - g_type_class_add_private (gobject_class, sizeof(MugMsgListViewPrivate)); - - signals[MUG_MSG_SELECTED] = - g_signal_new ("msg-selected", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(MugMsgListViewClass, msg_selected), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); -} - - -static void -on_cursor_changed (GtkTreeView *tview, MugMsgListView *lst) -{ - GtkTreeSelection *sel; - GtkTreeIter iter; - MugMsgListViewPrivate *priv; - - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(tview); - - sel = gtk_tree_view_get_selection (tview); - if (!sel) - return; /* hmmm */ - if (gtk_tree_selection_get_selected (sel, NULL, &iter)) { - char *path; - gtk_tree_model_get (GTK_TREE_MODEL(priv->_store), &iter, - MUG_COL_PATH, &path, -1); - g_signal_emit (G_OBJECT(lst), - signals[MUG_MSG_SELECTED], 0, - path); - g_free (path); - } -} - - -static void -treecell_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) -{ - MuMsgFlags flags; - MuMsgPrio prio; - - gtk_tree_model_get (tree_model, iter, - MUG_COL_FLAGS, &flags, - MUG_COL_PRIO, &prio, - -1); - - g_object_set (G_OBJECT(renderer), - "weight", (flags & MU_MSG_FLAG_NEW) ? 800 : 400, - "weight", (flags & MU_MSG_FLAG_SEEN) ? 400 : 800, - "foreground", prio == MU_MSG_PRIO_HIGH ? "red" : NULL, - NULL); -} - - -static void -append_col (GtkTreeView *treeview, const char* label, int colidx, gint maxwidth) -{ - GtkTreeViewColumn *col; - GtkCellRenderer *renderer; - - renderer = gtk_cell_renderer_text_new (); - g_object_set (G_OBJECT(renderer),"ellipsize", PANGO_ELLIPSIZE_END, NULL); - - col = gtk_tree_view_column_new_with_attributes (label, renderer, "text", - colidx, NULL); - g_object_set (G_OBJECT(col), "resizable", TRUE, NULL); - - gtk_tree_view_column_set_sort_indicator (col, TRUE); - gtk_tree_view_column_set_sort_column_id (col, colidx); - - if (maxwidth) { - gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width (col, maxwidth); - gtk_tree_view_column_set_expand (col, FALSE); - } else { - //gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); - gtk_tree_view_column_set_expand (col, TRUE); - } - - gtk_tree_view_column_set_cell_data_func (col, renderer, - (GtkTreeCellDataFunc) treecell_func, - NULL, NULL); - - gtk_tree_view_append_column (treeview, col); -} - -static void -mug_msg_list_view_init (MugMsgListView *obj) -{ - MugMsgListViewPrivate *priv; - GtkTreeView *tview; - - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); - - priv->_xpath = priv->_query = NULL; - priv->_store = gtk_list_store_new (MUG_N_COLS, - G_TYPE_STRING, /* date */ - G_TYPE_STRING, /* folder */ - G_TYPE_STRING, /* flagstr */ - G_TYPE_STRING, /* from */ - G_TYPE_STRING, /* to */ - G_TYPE_STRING, /* subject */ - G_TYPE_STRING, /* path */ - G_TYPE_UINT, /* prio */ - G_TYPE_UINT); /* flags */ - - tview = GTK_TREE_VIEW (obj); - gtk_tree_view_set_model (tview, GTK_TREE_MODEL(priv->_store)); - - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE); - gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(obj), - GTK_TREE_VIEW_GRID_LINES_VERTICAL); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), TRUE); - - append_col (tview, "Date", MUG_COL_DATE, 80); - append_col (tview, "Folder", MUG_COL_MAILDIR, 60); - append_col (tview, "Flags", MUG_COL_FLAGSSTR, 20); - append_col (tview, "From", MUG_COL_FROM, 0); - append_col (tview, "To", MUG_COL_TO, 0); - append_col (tview, "Subject", MUG_COL_SUBJECT, 0); - - g_signal_connect (G_OBJECT(obj), "cursor-changed", - G_CALLBACK(on_cursor_changed), - obj); -} - -static void -mug_msg_list_view_finalize (GObject *obj) -{ - MugMsgListViewPrivate *priv; - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); - - if (priv->_store) - g_object_unref (priv->_store); - - g_free (priv->_xpath); - g_free (priv->_query); - - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - -void -mug_msg_list_view_move_first (MugMsgListView *self) -{ - GtkTreePath *path; - - g_return_if_fail (MUG_IS_MSG_LIST_VIEW(self)); - - path = gtk_tree_path_new_first (); - gtk_tree_view_set_cursor (GTK_TREE_VIEW(self), path, - NULL, FALSE); - - gtk_tree_path_free (path); -} - - -static gboolean -msg_list_view_move (MugMsgListView *self, gboolean next) -{ - GtkTreePath *path; - - gtk_tree_view_get_cursor (GTK_TREE_VIEW(self), &path, NULL); - if (!path) - return FALSE; - - if (next) - gtk_tree_path_next (path); - else - gtk_tree_path_prev (path); - - gtk_tree_view_set_cursor (GTK_TREE_VIEW(self), path, NULL, FALSE); - gtk_tree_path_free (path); - - return TRUE; -} - - -gboolean -mug_msg_list_view_move_next (MugMsgListView *self) -{ - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); - - return msg_list_view_move (self, TRUE); -} - - -gboolean -mug_msg_list_view_move_prev (MugMsgListView *self) -{ - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); - - return msg_list_view_move (self, FALSE); -} - -GtkWidget* -mug_msg_list_view_new (const char *xpath) -{ - GtkWidget *w; - MugMsgListViewPrivate *priv; - - g_return_val_if_fail (xpath, NULL); - - w = GTK_WIDGET(g_object_new(MUG_TYPE_MSG_LIST_VIEW, NULL)); - - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(w); - priv->_xpath = g_strdup (xpath); - - return w; -} - - -static gchar* -empty_or_display_contact (const gchar* str) -{ - if (!str || *str == '\0') - return g_strdup ("-"); - else - return mu_msg_str_display_contact (str); - -} - -static MuMsgIter * -run_query (const char *xpath, const char *query) -{ - MuQuery *xapian; - MuMsgIter *iter; - - xapian = mu_query_new (xpath); - if (!xapian) { - g_printerr ("Failed to create a Xapian query\n"); - return NULL; - } - - iter = mu_query_run (xapian, query, NULL, TRUE, 0); - mu_query_destroy (xapian); - if (!iter) { - g_warning ("error: running query failed\n"); - return NULL; - } - - return iter; -} - -static void -add_row (GtkListStore *store, MuMsgIter *iter) -{ - GtkTreeIter treeiter; - const gchar *datestr, *flagstr; - gchar *from, *to; - time_t date; - - date = mu_msg_iter_get_date (iter); - datestr = date == 0 ? "-" : mu_msg_str_display_date_s (date); - from = empty_or_display_contact (mu_msg_iter_get_from(iter)); - to = empty_or_display_contact (mu_msg_iter_get_to(iter)); - flagstr = mu_msg_flags_to_str_s(mu_msg_iter_get_flags (iter)); - - gtk_list_store_append (store, &treeiter); - gtk_list_store_set (store, &treeiter, - MUG_COL_DATE, datestr, - MUG_COL_MAILDIR, mu_msg_iter_get_maildir (iter), - MUG_COL_FLAGSSTR, flagstr, - MUG_COL_FROM, from, - MUG_COL_TO, to, - MUG_COL_SUBJECT,mu_msg_iter_get_subject (iter), - MUG_COL_PATH, mu_msg_iter_get_path (iter), - MUG_COL_PRIO, mu_msg_iter_get_prio(iter), - MUG_COL_FLAGS, mu_msg_iter_get_flags(iter), - -1); - g_free (from); - g_free (to); -} - - -static int -update_model (GtkListStore *store, const char *xpath, const char *query) -{ - MuMsgIter *iter; - int count; - - iter = run_query (xpath, query); - if (!iter) { - g_warning ("error: running query failed\n"); - return -1; - } - - for (count = 0; !mu_msg_iter_is_done (iter); - mu_msg_iter_next (iter), ++count) - add_row (store, iter); - - mu_msg_iter_destroy (iter); - - return count; -} - - -int -mug_msg_list_view_query (MugMsgListView *self, const char *query) -{ - MugMsgListViewPrivate *priv; - gboolean rv; - - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); - - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(self); - gtk_list_store_clear (priv->_store); - - g_free (priv->_query); - priv->_query = query ? g_strdup(query) : NULL; - - if (!query) - return TRUE; - - rv = update_model (priv->_store, priv->_xpath, query); - - gtk_tree_view_columns_autosize (GTK_TREE_VIEW(self)); - - return rv; -} - - -const gchar* -mug_msg_list_view_get_query (MugMsgListView *self) -{ - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), NULL); - - return MUG_MSG_LIST_VIEW_GET_PRIVATE(self)->_query; -} diff --git a/mug/mug-msg-list-view.h b/mug/mug-msg-list-view.h deleted file mode 100644 index 755cc5e..0000000 --- a/mug/mug-msg-list-view.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#ifndef __MUG_MSG_LIST_VIEW_H__ -#define __MUG_MSG_LIST_VIEW_H__ - -#include -/* other include files */ - -G_BEGIN_DECLS - -/* convenience macros */ -#define MUG_TYPE_MSG_LIST_VIEW (mug_msg_list_view_get_type()) -#define MUG_MSG_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_MSG_LIST_VIEW,MugMsgListView)) -#define MUG_MSG_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_MSG_LIST_VIEW,MugMsgListViewClass)) -#define MUG_IS_MSG_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_MSG_LIST_VIEW)) -#define MUG_IS_MSG_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_MSG_LIST_VIEW)) -#define MUG_MSG_LIST_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_MSG_LIST_VIEW,MugMsgListViewClass)) - -typedef struct _MugMsgListView MugMsgListView; -typedef struct _MugMsgListViewClass MugMsgListViewClass; - -struct _MugMsgListView { - GtkTreeView parent; - /* insert public members, if any */ -}; - -struct _MugMsgListViewClass { - GtkTreeViewClass parent_class; - /* insert signal callback declarations, e.g. */ - void (* msg_selected) (MugMsgListView* obj, const char* msgpath); -}; - -/* member functions */ -GType mug_msg_list_view_get_type (void) G_GNUC_CONST; - -/* parameter-less _new function (constructor) */ -/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mug_msg_list_view_new (const char *xpath); - -int mug_msg_list_view_query (MugMsgListView *self, const char *query); - - -void mug_msg_list_view_move_first (MugMsgListView *self); - -gboolean mug_msg_list_view_move_prev (MugMsgListView *self); -gboolean mug_msg_list_view_move_next (MugMsgListView *self); - -const gchar* mug_msg_list_view_get_query (MugMsgListView *self); - -G_END_DECLS - -#endif /* __MUG_MSG_LIST_VIEW_H__ */ - diff --git a/mug/mug-msg-view.c b/mug/mug-msg-view.c deleted file mode 100644 index 9bb4090..0000000 --- a/mug/mug-msg-view.c +++ /dev/null @@ -1,298 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - - -#include "mug-msg-view.h" -#include "mu-msg.h" -#include "mu-msg-str.h" - -/* 'private'/'protected' functions */ -static void mug_msg_view_class_init (MugMsgViewClass *klass); -static void mug_msg_view_init (MugMsgView *obj); -static void mug_msg_view_finalize (GObject *obj); - -/* list my signals */ -enum { - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL -}; - -enum _HeaderRow { - HEADER_ROW_FROM, - HEADER_ROW_TO, - HEADER_ROW_SUBJECT, - HEADER_ROW_CC, - HEADER_ROW_DATE, - HEADER_ROW_PATH, - HEADER_ROW_MSGID, - HEADER_ROW_SIZE, - HEADER_ROW_NUM -}; -typedef enum _HeaderRow HeaderRow; - -struct _HeaderInfo { - HeaderRow row; - const char *title; -}; -typedef struct _HeaderInfo HeaderInfo; - -static const HeaderInfo HEADER_INFO[] = { - {HEADER_ROW_CC, "Cc"}, - {HEADER_ROW_SUBJECT, "Subject"}, - {HEADER_ROW_DATE, "Date"} -}; - -static const HeaderInfo HEADER_INFO_EXPANDER[] = { - {HEADER_ROW_FROM, "From"}, - {HEADER_ROW_TO, "To"}, - {HEADER_ROW_PATH, "Path"}, - {HEADER_ROW_MSGID, "Message-Id" }, - {HEADER_ROW_SIZE, "Size"} -}; - -typedef struct _MugMsgViewPrivate MugMsgViewPrivate; -struct _MugMsgViewPrivate { - - GtkWidget *_headers_area; - GtkWidget *_tablemain, *_tableexpander; - GtkWidget *_headervals [HEADER_ROW_NUM]; - - GtkWidget *_expander_header, *_expander; - GtkWidget *_view; -}; -#define MUG_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_MSG_VIEW, MugMsgViewPrivate)) -/* globals */ -static GtkVBoxClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -/* static guint signals[LAST_SIGNAL] = {0}; */ - - -G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_VBOX); - -static void -mug_msg_view_class_init (MugMsgViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = mug_msg_view_finalize; - - g_type_class_add_private (gobject_class, sizeof(MugMsgViewPrivate)); - - /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ -} - - -static GtkWidget* -create_table (MugMsgViewPrivate *priv, const HeaderInfo *hinfo, guint num) -{ - guint i; - GtkWidget *table; - - table = gtk_table_new (num, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE(table), 5); - - for (i = 0; i < num; ++i) { - - char *str; - GtkWidget *l, *al; - - l = gtk_label_new(NULL); - gtk_misc_set_alignment (GTK_MISC(l), 0.0, 0.5); - - gtk_label_set_justify (GTK_LABEL(l), GTK_JUSTIFY_LEFT); - str = g_strdup_printf ("%s:", hinfo[i].title); - gtk_label_set_markup (GTK_LABEL(l), str); - g_free (str); - - gtk_table_attach (GTK_TABLE(table), l, - 0, 1, i, i+1, - GTK_FILL, GTK_FILL, - 0, 0); - - l = priv->_headervals[hinfo[i].row] = gtk_label_new (NULL); - al = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); - gtk_label_set_line_wrap_mode (GTK_LABEL(l), PANGO_WRAP_WORD_CHAR); - gtk_label_set_line_wrap (GTK_LABEL(l), TRUE); - gtk_label_set_selectable (GTK_LABEL(l), TRUE); - - gtk_container_add (GTK_CONTAINER(al), l); - gtk_label_set_justify (GTK_LABEL(l), GTK_JUSTIFY_LEFT); - gtk_table_attach (GTK_TABLE(table), al, - 1, 2, i, i+1, - GTK_FILL, GTK_FILL, - 0, 0); - } - - return table; -} - -static GtkWidget* -headers_area (MugMsgViewPrivate *priv) -{ - GtkWidget *scrolled, *vbox; - - priv->_tablemain = create_table (priv, HEADER_INFO, - G_N_ELEMENTS(HEADER_INFO)); - priv->_tableexpander = create_table (priv, HEADER_INFO_EXPANDER, - G_N_ELEMENTS(HEADER_INFO_EXPANDER)); - priv->_expander = gtk_expander_new ("Details"); - gtk_container_add (GTK_CONTAINER(priv->_expander), - priv->_tableexpander); - - vbox = gtk_vbox_new (FALSE, FALSE); - gtk_box_pack_start (GTK_BOX(vbox), priv->_tablemain, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(vbox), priv->_expander, FALSE, FALSE, 0); - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled), vbox); - - return priv->_headers_area = scrolled; -} - - -static void -mug_msg_view_init (MugMsgView *obj) -{ - MugMsgViewPrivate *priv; - GtkWidget *scrolled; - - priv = MUG_MSG_VIEW_GET_PRIVATE(obj); - - priv->_view = gtk_text_view_new (); - gtk_text_view_set_editable (GTK_TEXT_VIEW(priv->_view), FALSE); - gtk_text_view_set_left_margin (GTK_TEXT_VIEW(priv->_view), 10); - gtk_text_view_set_right_margin (GTK_TEXT_VIEW(priv->_view), 10); - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (scrolled), priv->_view); - - gtk_box_pack_start (GTK_BOX(obj), headers_area(priv), FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(obj), scrolled, TRUE, TRUE, 0); - - gtk_widget_hide (priv->_headers_area); -} - -static void -mug_msg_view_finalize (GObject *obj) -{ -/* free/unref instance resources here */ - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - -GtkWidget* -mug_msg_view_new (void) -{ - return GTK_WIDGET(g_object_new(MUG_TYPE_MSG_VIEW, NULL)); -} - - - -gboolean -mug_msg_view_set_text (MugMsgView *self, const char* txt) -{ - MugMsgViewPrivate *priv; - GtkTextBuffer *buf; - - g_return_val_if_fail (MUG_IS_MSG_VIEW(self), FALSE); - priv = MUG_MSG_VIEW_GET_PRIVATE(self); - - buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->_view)); - gtk_text_buffer_set_text (buf, txt ? txt : "", -1); - - return TRUE; -} - - -static void -fill_header (MugMsgViewPrivate *priv, MuMsg* msg) -{ - int i; - for (i = 0; i != HEADER_ROW_NUM; ++i) { - const gchar* val; - switch (i) { - case HEADER_ROW_FROM: val = mu_msg_get_from(msg); break; - case HEADER_ROW_TO: val = mu_msg_get_to(msg); break; - case HEADER_ROW_SUBJECT: val = mu_msg_get_subject(msg); break; - case HEADER_ROW_MSGID: val = mu_msg_get_msgid(msg); break; - case HEADER_ROW_CC: val = mu_msg_get_cc (msg); break; - case HEADER_ROW_PATH: val = mu_msg_get_path (msg); break; - case HEADER_ROW_DATE: val = mu_msg_str_date_s( - "%c", mu_msg_get_date (msg)); - break; - case HEADER_ROW_SIZE: val = mu_msg_str_size_s (mu_msg_get_size(msg)); - break; - default: val = NULL; - } - - { - gchar *str; - str = g_markup_escape_text (val ? val : "", -1); - gtk_label_set_markup (GTK_LABEL(priv->_headervals[i]), str); - g_free (str); - } - } - - gtk_widget_show (priv->_tablemain); - gtk_widget_show (priv->_expander); -} - - -gboolean -mug_msg_view_set_msg (MugMsgView *self, const char* msgpath) -{ - MugMsgViewPrivate *priv; - MuMsg* msg; - gboolean rv; - - g_return_val_if_fail (MUG_IS_MSG_VIEW(self), FALSE); - - priv = MUG_MSG_VIEW_GET_PRIVATE(self); - - if (!msgpath) { - mug_msg_view_set_text (self, ""); - gtk_widget_hide (priv->_headers_area); - return TRUE; - } - - msg = mu_msg_new (msgpath, NULL); - if (!msg) - return FALSE; - - rv = mug_msg_view_set_text (self, mu_msg_get_body_text(msg)); - fill_header (priv, msg); - gtk_widget_show (priv->_headers_area); - - mu_msg_destroy (msg); - - return rv; -} diff --git a/mug/mug-msg-view.h b/mug/mug-msg-view.h deleted file mode 100644 index 88380ff..0000000 --- a/mug/mug-msg-view.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -** Copyright (C) 2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - - -#ifndef __MUG_MSG_VIEW_H__ -#define __MUG_MSG_VIEW_H__ - -#include -/* other include files */ - -G_BEGIN_DECLS - -/* convenience macros */ -#define MUG_TYPE_MSG_VIEW (mug_msg_view_get_type()) -#define MUG_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_MSG_VIEW,MugMsgView)) -#define MUG_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_MSG_VIEW,MugMsgViewClass)) -#define MUG_IS_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_MSG_VIEW)) -#define MUG_IS_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_MSG_VIEW)) -#define MUG_MSG_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_MSG_VIEW,MugMsgViewClass)) - -typedef struct _MugMsgView MugMsgView; -typedef struct _MugMsgViewClass MugMsgViewClass; - -struct _MugMsgView { - GtkVBox parent; - /* insert public members, if any */ -}; - -struct _MugMsgViewClass { - GtkVBoxClass parent_class; - /* insert signal callback declarations, e.g. */ - /* void (* my_event) (MugMsg* obj); */ -}; - -/* member functions */ -GType mug_msg_view_get_type (void) G_GNUC_CONST; - -/* parameter-less _new function (constructor) */ -/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mug_msg_view_new (void); -gboolean mug_msg_view_set_msg (MugMsgView *self, const char* msgpath); -gboolean mug_msg_view_set_text (MugMsgView *self, const char* txt); - -G_END_DECLS - -#endif /* __MUG_MSG_VIEW_H__ */ - diff --git a/mug/mug-query-bar.c b/mug/mug-query-bar.c deleted file mode 100644 index f925c73..0000000 --- a/mug/mug-query-bar.c +++ /dev/null @@ -1,141 +0,0 @@ -/* mug-query-bar.c */ - -/* insert (c)/licensing information) */ - -#include "mug-query-bar.h" -/* include other impl specific header files */ - -/* 'private'/'protected' functions */ -static void mug_query_bar_class_init (MugQueryBarClass *klass); -static void mug_query_bar_init (MugQueryBar *obj); -static void mug_query_bar_finalize (GObject *obj); - -/* list my signals */ -enum { - MUG_QUERY_CHANGED, - LAST_SIGNAL -}; - -typedef struct _MugQueryBarPrivate MugQueryBarPrivate; -struct _MugQueryBarPrivate { - GtkWidget *_entry; -}; -#define MUG_QUERY_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_QUERY_BAR, \ - MugQueryBarPrivate)) -/* globals */ -static GtkContainerClass *parent_class = NULL; - -static guint signals[LAST_SIGNAL] = {0}; - -GType -mug_query_bar_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(MugQueryBarClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) mug_query_bar_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(MugQueryBar), - 0, /* n_preallocs, ignored since 2.10 */ - (GInstanceInitFunc) mug_query_bar_init, - NULL - }; - my_type = g_type_register_static (GTK_TYPE_HBOX, - "MugQueryBar", - &my_info, 0); - } - return my_type; -} - -static void -mug_query_bar_class_init (MugQueryBarClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = mug_query_bar_finalize; - - g_type_class_add_private (gobject_class, sizeof(MugQueryBarPrivate)); - - /* signal definitions go here, e.g.: */ - signals[MUG_QUERY_CHANGED] = - g_signal_new ("query_changed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(MugQueryBarClass, query_changed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); -} - - -static void -on_entry_activated (GtkWidget *w, MugQueryBar *bar) -{ - MugQueryBarPrivate *priv; - - priv = MUG_QUERY_BAR_GET_PRIVATE(bar); - - g_signal_emit (G_OBJECT(bar), signals[MUG_QUERY_CHANGED], 0, - gtk_entry_get_text(GTK_ENTRY(w))); -} - -static void -mug_query_bar_init (MugQueryBar *obj) -{ - MugQueryBarPrivate *priv; - - priv = MUG_QUERY_BAR_GET_PRIVATE(obj); - - priv->_entry = gtk_entry_new (); - - g_signal_connect (priv->_entry, "activate", G_CALLBACK(on_entry_activated), - obj); - - gtk_box_pack_start (GTK_BOX(obj), priv->_entry, TRUE, TRUE, 0); -} - -static void -mug_query_bar_finalize (GObject *obj) -{ -/* free/unref instance resources here */ - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - -GtkWidget* -mug_query_bar_new (void) -{ - return GTK_WIDGET(g_object_new(MUG_TYPE_QUERY_BAR, NULL)); -} - - -void -mug_query_bar_set_query (MugQueryBar *self, const char *query, gboolean run) -{ - MugQueryBarPrivate *priv; - - g_return_if_fail (MUG_IS_QUERY_BAR(self)); - priv = MUG_QUERY_BAR_GET_PRIVATE(self); - - gtk_entry_set_text (GTK_ENTRY(priv->_entry), query ? query : ""); - - if (run) - on_entry_activated (priv->_entry, self); -} - - -void -mug_query_bar_grab_focus (MugQueryBar *self) -{ - g_return_if_fail (MUG_IS_QUERY_BAR(self)); - - gtk_widget_grab_focus - (GTK_WIDGET(MUG_QUERY_BAR_GET_PRIVATE(self)->_entry)); -} - diff --git a/mug/mug-query-bar.h b/mug/mug-query-bar.h deleted file mode 100644 index 2c954cf..0000000 --- a/mug/mug-query-bar.h +++ /dev/null @@ -1,48 +0,0 @@ -/* mug-query-bar.h */ -/* insert (c)/licensing information) */ - -#ifndef __MUG_QUERY_BAR_H__ -#define __MUG_QUERY_BAR_H__ - -#include -/* other include files */ - -G_BEGIN_DECLS - -/* convenience macros */ -#define MUG_TYPE_QUERY_BAR (mug_query_bar_get_type()) -#define MUG_QUERY_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_QUERY_BAR,MugQueryBar)) -#define MUG_QUERY_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_QUERY_BAR,MugQueryBarClass)) -#define MUG_IS_QUERY_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_QUERY_BAR)) -#define MUG_IS_QUERY_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_QUERY_BAR)) -#define MUG_QUERY_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_QUERY_BAR,MugQueryBarClass)) - -typedef struct _MugQueryBar MugQueryBar; -typedef struct _MugQueryBarClass MugQueryBarClass; - -struct _MugQueryBar { - GtkHBox parent; - /* insert public members, if any */ -}; - -struct _MugQueryBarClass { - GtkHBoxClass parent_class; - /* insert signal callback declarations, e.g. */ - void (* query_changed) (MugQueryBar* obj, const char *query); -}; - -/* member functions */ -GType mug_query_bar_get_type (void) G_GNUC_CONST; - -/* parameter-less _new function (constructor) */ -/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mug_query_bar_new (void); - -void mug_query_bar_grab_focus (MugQueryBar *self); - -void mug_query_bar_set_query (MugQueryBar *self, const char *query, gboolean run); - -G_END_DECLS - -#endif /* __MUG_QUERY_BAR_H__ */ - diff --git a/mug/mug-shortcuts.c b/mug/mug-shortcuts.c deleted file mode 100644 index 808b2fc..0000000 --- a/mug/mug-shortcuts.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -** Copyright (C) 2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#include "mug-shortcuts.h" -#include "mu-bookmarks.h" - -/* include other impl specific header files */ - -/* 'private'/'protected' functions */ -static void mug_shortcuts_class_init (MugShortcutsClass *klass); -static void mug_shortcuts_init (MugShortcuts *obj); -static void mug_shortcuts_finalize (GObject *obj); - -#define MUG_SHORTCUT_BOOKMARK "bookmark" - -/* list my signals */ -enum { - SHORTCUT_CLICKED, - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL -}; - -struct _MugShortcutsPrivate { - GtkWidget *_bbox; - -}; -#define MUG_SHORTCUTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_SHORTCUTS, \ - MugShortcutsPrivate)) -/* globals */ -static GtkVBoxClass *parent_class = NULL; - -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_VBOX); - -static void -mug_shortcuts_class_init (MugShortcutsClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = mug_shortcuts_finalize; - - g_type_class_add_private (gobject_class, sizeof(MugShortcutsPrivate)); - - /* signal definitions go here, e.g.: */ - signals[SHORTCUT_CLICKED] = - g_signal_new ("clicked", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(MugShortcutsClass, clicked), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ -} - -static void -mug_shortcuts_init (MugShortcuts *obj) -{ - obj->_priv = MUG_SHORTCUTS_GET_PRIVATE(obj); - - obj->_priv->_bbox = gtk_vbutton_box_new (); - gtk_button_box_set_layout (GTK_BUTTON_BOX(obj->_priv->_bbox), - GTK_BUTTONBOX_START); - gtk_box_pack_start (GTK_BOX(obj), obj->_priv->_bbox, TRUE, TRUE, 0); -} - -static void -mug_shortcuts_finalize (GObject *obj) -{ -/* free/unref instance resources here */ - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - -static void -on_button_clicked (GtkWidget *button, MugShortcuts *self) -{ - g_signal_emit (G_OBJECT(self), - signals[SHORTCUT_CLICKED], 0, - (const gchar*)g_object_get_data (G_OBJECT(button), - MUG_SHORTCUT_BOOKMARK)); -} - - -static void -each_bookmark (const char* key, const char* val, MugShortcuts *self) -{ - GtkWidget *button; - - button = gtk_button_new_with_label (key); - g_object_set_data_full (G_OBJECT(button), MUG_SHORTCUT_BOOKMARK, - g_strdup(val), g_free); - g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), - self); - - gtk_container_add (GTK_CONTAINER(self->_priv->_bbox), button); -} - -static gboolean -init_shortcuts (MugShortcuts *self, const char* bmpath) -{ - MuBookmarks *bookmarks; - - bookmarks = mu_bookmarks_new (bmpath); - if (!bookmarks) - return TRUE; - - mu_bookmarks_foreach (bookmarks, (MuBookmarksForeachFunc)each_bookmark, - self); - - mu_bookmarks_destroy (bookmarks); - return TRUE; -} - -GtkWidget* -mug_shortcuts_new (const char *bmpath) -{ - MugShortcuts *self; - - self = MUG_SHORTCUTS(g_object_new(MUG_TYPE_SHORTCUTS, NULL)); - if (!init_shortcuts (self, bmpath)) { - g_object_unref (self); - return NULL; - } - - return GTK_WIDGET(self); -} - -/* following: other function implementations */ -/* such as mug_shortcuts_do_something, or mug_shortcuts_has_foo */ - diff --git a/mug/mug-shortcuts.h b/mug/mug-shortcuts.h deleted file mode 100644 index 16970fc..0000000 --- a/mug/mug-shortcuts.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -** Copyright (C) 2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - - -#ifndef __MUG_SHORTCUTS_H__ -#define __MUG_SHORTCUTS_H__ - -#include -/* other include files */ - -G_BEGIN_DECLS - -/* convenience macros */ -#define MUG_TYPE_SHORTCUTS (mug_shortcuts_get_type()) -#define MUG_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_SHORTCUTS,MugShortcuts)) -#define MUG_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_SHORTCUTS,MugShortcutsClass)) -#define MUG_IS_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_SHORTCUTS)) -#define MUG_IS_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_SHORTCUTS)) -#define MUG_SHORTCUTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_SHORTCUTS,MugShortcutsClass)) - -typedef struct _MugShortcuts MugShortcuts; -typedef struct _MugShortcutsClass MugShortcutsClass; -typedef struct _MugShortcutsPrivate MugShortcutsPrivate; - -struct _MugShortcuts { - GtkVBox parent; - /* insert public members, if any */ - - /* private */ - MugShortcutsPrivate *_priv; -}; - -struct _MugShortcutsClass { - GtkVBoxClass parent_class; - void (*clicked) (MugShortcuts* obj, const char* query); -}; - -/* member functions */ -GType mug_shortcuts_get_type (void) G_GNUC_CONST; - -/* parameter-less _new function (constructor) */ -/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mug_shortcuts_new (const char *bmpath); - -/* fill in other public functions, e.g.: */ -/* void mug_shortcuts_do_something (MugShortcuts *self, const gchar* param); */ -/* gboolean mug_shortcuts_has_foo (MugShortcuts *self, gint value); */ - - -G_END_DECLS - -#endif /* __MUG_SHORTCUTS_H__ */ - diff --git a/mug/mug.cc b/mug/mug.cc deleted file mode 100644 index f9316f6..0000000 --- a/mug/mug.cc +++ /dev/null @@ -1,338 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY 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, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#if HAVE_CONFIG_H -#include "config.h" -#endif /*HAVE_CONFIG*/ - -#include -#include /* for memset */ - -#include "mu-util.h" -#include "mu-runtime.h" - -#include "mug-msg-list-view.h" -#include "mug-query-bar.h" -#include "mug-msg-view.h" -#include "mug-shortcuts.h" - -struct _MugData { - GtkWidget *win; - GtkWidget *statusbar; - GtkWidget *mlist; - GtkWidget *toolbar; - GtkWidget *msgview; - GtkWidget *querybar; - GtkWidget *shortcuts; - gchar *muhome; -}; -typedef struct _MugData MugData; - - -static void -about_mug (MugData *mugdata) -{ - GtkWidget *about; - about = gtk_message_dialog_new - (GTK_WINDOW(mugdata->win), GTK_DIALOG_MODAL, - GTK_MESSAGE_INFO,GTK_BUTTONS_OK, - "Mug version %s\n" - "A graphical frontend to the 'mu' e-mail search engine\n\n" - "(c) 2010 Dirk-Jan C. Binnema\n" - "Released under the terms of the GPLv3+", VERSION); - - gtk_dialog_run (GTK_DIALOG(about)); - gtk_widget_destroy (about); -} - -enum _ToolAction { - ACTION_PREV_MSG = 1, - ACTION_NEXT_MSG, - ACTION_DO_QUIT, - ACTION_ABOUT, - ACTION_SEPARATOR /* pseudo action */ -}; -typedef enum _ToolAction ToolAction; - -static void -on_tool_button_clicked (GtkToolButton *btn, MugData *mugdata) -{ - ToolAction action; - action = (ToolAction)GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(btn), - "action")); - switch (action) { - - case ACTION_DO_QUIT: - gtk_main_quit(); - break; - case ACTION_NEXT_MSG: - mug_msg_list_view_move_next (MUG_MSG_LIST_VIEW(mugdata->mlist)); - break; - case ACTION_PREV_MSG: - mug_msg_list_view_move_prev (MUG_MSG_LIST_VIEW(mugdata->mlist)); - break; - case ACTION_ABOUT: - about_mug (mugdata); - break; - default: - g_print ("%u\n", action); - } -} - -static GtkWidget* -mug_toolbar (MugData *mugdata) -{ - GtkWidget *toolbar; - int i; - struct { - const char* stock_id; - ToolAction action; - } tools[] = { - { GTK_STOCK_GO_UP, ACTION_PREV_MSG }, - { GTK_STOCK_GO_DOWN, ACTION_NEXT_MSG }, - { NULL, ACTION_SEPARATOR }, - { GTK_STOCK_ABOUT, ACTION_ABOUT }, - { NULL, ACTION_SEPARATOR }, - { GTK_STOCK_QUIT, ACTION_DO_QUIT }, - }; - - for (toolbar = gtk_toolbar_new(), i = 0; i != G_N_ELEMENTS(tools); ++i) { - GtkToolItem *btn; - - /* separator item ? */ - if (tools[i].action == ACTION_SEPARATOR) { - gtk_toolbar_insert (GTK_TOOLBAR(toolbar), - gtk_separator_tool_item_new(), i); - continue; - } - - /* nope: a real item */ - btn = gtk_tool_button_new_from_stock (tools[i].stock_id); - g_object_set_data (G_OBJECT(btn), "action", - GUINT_TO_POINTER(tools[i].action)); - g_signal_connect (G_OBJECT(btn), "clicked", - G_CALLBACK(on_tool_button_clicked), - mugdata); - gtk_toolbar_insert (GTK_TOOLBAR(toolbar), btn, i); - } - - return toolbar; -} - -static void -on_shortcut_clicked (GtkWidget *w, const gchar *query, MugData *mdata) -{ - mug_query_bar_set_query (MUG_QUERY_BAR(mdata->querybar), - query, TRUE); -} - - -static GtkWidget* -mug_shortcuts_bar (MugData *data) -{ - data->shortcuts = mug_shortcuts_new (mu_runtime_bookmarks_file()); - - g_signal_connect (G_OBJECT(data->shortcuts), "clicked", - G_CALLBACK(on_shortcut_clicked), data); - - return data->shortcuts; -} - - -static GtkWidget* -mug_statusbar (void) -{ - GtkWidget *statusbar; - - statusbar = gtk_statusbar_new (); - - return statusbar; -} - -static void -on_query_changed (MugQueryBar *bar, const char* query, MugData *mugdata) -{ - int count; - - /* clear the old message */ - mug_msg_view_set_text (MUG_MSG_VIEW(mugdata->msgview), NULL); - - count = mug_msg_list_view_query (MUG_MSG_LIST_VIEW(mugdata->mlist), - query); - if (count >= 0) { - gchar *msg = - g_strdup_printf ("%d message%s found matching '%s'", - count, - count > 1 ? "s" : "", - mug_msg_list_view_get_query - (MUG_MSG_LIST_VIEW(mugdata->mlist))); - gtk_statusbar_push (GTK_STATUSBAR(mugdata->statusbar), 0, msg); - g_free (msg); - - mug_msg_list_view_move_first (MUG_MSG_LIST_VIEW(mugdata->mlist)); - gtk_widget_grab_focus (GTK_WIDGET(mugdata->mlist)); - } -} - - -static void -on_msg_selected (MugMsgListView *mlist, const char* mpath, MugData *mugdata) -{ - // g_warning ("msg selected: %s", mpath); - mug_msg_view_set_msg (MUG_MSG_VIEW(mugdata->msgview), mpath); -} - - - -static GtkWidget* -mug_querybar (void) -{ - GtkWidget *querybar; - - querybar = mug_query_bar_new (); - - return querybar; -} - - -static GtkWidget* -mug_query_area (MugData *mugdata) -{ - GtkWidget *queryarea; - GtkWidget *paned; - GtkWidget *scrolled; - - queryarea = gtk_vbox_new (FALSE, 2); - paned = gtk_vpaned_new (); - - mugdata->mlist = mug_msg_list_view_new(mu_runtime_xapian_dir()); - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_container_add (GTK_CONTAINER(scrolled), mugdata->mlist); - gtk_paned_add1 (GTK_PANED (paned), scrolled); - - mugdata->msgview = mug_msg_view_new (); - mug_msg_view_set_msg (MUG_MSG_VIEW(mugdata->msgview), NULL); - g_signal_connect (G_OBJECT(mugdata->mlist), "msg-selected", - G_CALLBACK(on_msg_selected), mugdata); - gtk_paned_add2 (GTK_PANED (paned), mugdata->msgview); - - mugdata->querybar = mug_querybar(); - g_signal_connect (G_OBJECT(mugdata->querybar), "query-changed", - G_CALLBACK(on_query_changed), - mugdata); - - gtk_box_pack_start (GTK_BOX(queryarea), - mugdata->querybar, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX(queryarea), - paned, TRUE, TRUE, 2); - - return queryarea; -} - - -static GtkWidget* -mug_main_area (MugData *mugdata) -{ - GtkWidget *mainarea; - - mainarea = gtk_hbox_new (FALSE, 0); - - gtk_box_pack_start (GTK_BOX(mainarea), mug_shortcuts_bar(mugdata), - FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(mainarea), mug_query_area(mugdata), - TRUE, TRUE, 0); - - return mainarea; -} - - -GtkWidget* -mug_shell (MugData *mugdata) -{ - GtkWidget *vbox; - gchar *icon; - - mugdata->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW(mugdata->win), "Mug Mail Search"); - - vbox = gtk_vbox_new (FALSE, 2); - mugdata->toolbar = mug_toolbar(mugdata); - gtk_box_pack_start (GTK_BOX(vbox), mugdata->toolbar, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX(vbox), mug_main_area(mugdata), TRUE, TRUE, 2); - - mugdata->statusbar = mug_statusbar(); - gtk_box_pack_start (GTK_BOX(vbox), mugdata->statusbar, FALSE, FALSE, 2); - - gtk_container_add (GTK_CONTAINER(mugdata->win), vbox); - gtk_widget_show_all (vbox); - - gtk_window_set_default_size (GTK_WINDOW(mugdata->win), 700, 500); - gtk_window_set_resizable (GTK_WINDOW(mugdata->win), TRUE); - - icon = g_strdup_printf ("%s%cmug.svg", ICONDIR, G_DIR_SEPARATOR); - gtk_window_set_icon_from_file (GTK_WINDOW(mugdata->win), icon, NULL); - g_free (icon); - - return mugdata->win; -} - -int -main (int argc, char *argv[]) -{ - MugData mugdata; - GtkWidget *mugshell; - GOptionContext *octx; - GOptionEntry entries[] = { - {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &mugdata.muhome, - "specify an alternative mu directory", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} /* sentinel */ - }; - - gtk_init (&argc, &argv); - - octx = g_option_context_new ("- mug options"); - g_option_context_add_main_entries (octx, entries, "Mug"); - - memset (&mugdata, 0, sizeof(MugData)); - if (!g_option_context_parse (octx, &argc, &argv, NULL)) { - g_printerr ("mug: error in options\n"); - return 1; - } - - mu_runtime_init (mugdata.muhome); - - mugshell = mug_shell (&mugdata); - g_signal_connect(G_OBJECT(mugshell), "destroy", - G_CALLBACK(gtk_main_quit), NULL); - - gtk_widget_show (mugshell); - mug_query_bar_grab_focus (MUG_QUERY_BAR(mugdata.querybar)); - - gtk_main (); - g_free (mugdata.muhome); - - mu_runtime_uninit (); - - return 0; -} diff --git a/mug/mug.desktop.in b/mug/mug.desktop.in deleted file mode 100644 index 8a60306..0000000 --- a/mug/mug.desktop.in +++ /dev/null @@ -1,12 +0,0 @@ -[Desktop Entry] -Version=@PACKAGE_VERSION@ -Type=Application -Name=Mug -GenericName=Mail Searcher -Comment=A UI for the mu mail searcher -Exec=@prefix@/bin/mug -X-Text-Domain=mu -Terminal=false -Icon=mug -StartupWMClass=mug -MimeType=application/x-executable; diff --git a/mug/mug.svg b/mug/mug.svg deleted file mode 100644 index 926deb5..0000000 --- a/mug/mug.svg +++ /dev/null @@ -1,510 +0,0 @@ - - - - - - - - image/svg+xml - - - - Sheikh Tuhin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/toys/Makefile.am b/toys/Makefile.am new file mode 100644 index 0000000..22f6fc0 --- /dev/null +++ b/toys/Makefile.am @@ -0,0 +1,25 @@ +## Copyright (C) 2008-2010 Dirk-Jan C. Binnema +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY 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, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +SUBDIRS= + +# build if there is some gtk available +if HAVE_GTK +SUBDIRS += mug +endif + diff --git a/toys/mug/Makefile.am b/toys/mug/Makefile.am new file mode 100644 index 0000000..a1c7360 --- /dev/null +++ b/toys/mug/Makefile.am @@ -0,0 +1,69 @@ +## Copyright (C) 2008-2010 Dirk-Jan C. Binnema +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY 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, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +# enforce compiling this dir first before decending into tests/ +SUBDIRS= . + +#if HAVE_GTEST +#SUBDIRS += tests +#endif + +INCLUDES=-I${top_srcdir}/src $(GTK_CFLAGS) + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement +AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter -DICONDIR='"$(icondir)"' \ + -DICONDIR='"$(icondir)"' + +bin_PROGRAMS= \ + mug + +# note, mu.cc is only '.cc' and not '.c' because libmu must explicitly +# be linked as c++, not c. +mug_SOURCES= \ + mug.cc \ + mug-msg-list-view.c \ + mug-msg-list-view.h \ + mug-msg-view.h \ + mug-msg-view.c \ + mug-query-bar.h \ + mug-query-bar.c \ + mug-shortcuts.c \ + mug-shortcuts.h + +mug_LDADD= \ + ${top_builddir}/src/libmu.la \ + ${GTK_LIBS} + +icondir= \ + $(datarootdir)/icons + +icon_DATA= \ + ${top_srcdir}/toys/mug/mug.svg + +desktopdir= \ + $(datarootdir)/applications + +desktop_DATA= \ + mug.desktop + +EXTRA_DIST= \ + $(desktopentry_DATA) + diff --git a/toys/mug/TODO b/toys/mug/TODO new file mode 100644 index 0000000..745f4e8 --- /dev/null +++ b/toys/mug/TODO @@ -0,0 +1,28 @@ +* todo for mug + + - [X] column sizing + - [X] query in status bar + - [X] tool bar working + - [X] pretty-print addresses + - [X] pretty-print dates + - [X] up/down arrows => need msg-list-view support + - [X] unread mails => bold, important mails => red + - [X] detail info about current msg + - [X] guess maildir + - [ ] bookmarks + - [ ] icon / .desktop file + - [X] clear msg when starting new query + - [X] focus search bar at startup + - [X] focus first msg after query + - [X] sorting for columns + - [X] add about menu + - [X] make scrollbars automatic + - [ ] progress-bar, incremental + - [ ] cmdline arg for mu home dir + - [ ] error messages if there's no db / old db + +# Local Variables: +# mode: org; org-startup-folded: t +# End: + + diff --git a/toys/mug/mug-msg-list-view.c b/toys/mug/mug-msg-list-view.c new file mode 100644 index 0000000..0eb1457 --- /dev/null +++ b/toys/mug/mug-msg-list-view.c @@ -0,0 +1,408 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mug-msg-list-view.h" +#include "mu-query.h" +#include "mu-msg-str.h" +/* include other impl specific header files */ + +/* 'private'/'protected' functions */ +static void mug_msg_list_view_class_init (MugMsgListViewClass *klass); +static void mug_msg_list_view_init (MugMsgListView *obj); +static void mug_msg_list_view_finalize (GObject *obj); + +/* list my signals */ +enum { + MUG_MSG_SELECTED, + LAST_SIGNAL +}; + + +enum { + MUG_COL_DATE, + MUG_COL_MAILDIR, + MUG_COL_FLAGSSTR, + MUG_COL_FROM, + MUG_COL_TO, + MUG_COL_SUBJECT, + MUG_COL_PATH, + MUG_COL_PRIO, + MUG_COL_FLAGS, + + MUG_N_COLS +}; + +typedef struct _MugMsgListViewPrivate MugMsgListViewPrivate; +struct _MugMsgListViewPrivate { + GtkListStore *_store; + char *_xpath; + char *_query; +}; +#define MUG_MSG_LIST_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MUG_TYPE_MSG_LIST_VIEW, \ + MugMsgListViewPrivate)) +/* globals */ +static GtkTreeViewClass *parent_class = NULL; + +/* uncomment the following if you have defined any signals */ +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (MugMsgListView, mug_msg_list_view, GTK_TYPE_TREE_VIEW); + + +static void +mug_msg_list_view_class_init (MugMsgListViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = mug_msg_list_view_finalize; + + g_type_class_add_private (gobject_class, sizeof(MugMsgListViewPrivate)); + + signals[MUG_MSG_SELECTED] = + g_signal_new ("msg-selected", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugMsgListViewClass, msg_selected), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + + +static void +on_cursor_changed (GtkTreeView *tview, MugMsgListView *lst) +{ + GtkTreeSelection *sel; + GtkTreeIter iter; + MugMsgListViewPrivate *priv; + + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(tview); + + sel = gtk_tree_view_get_selection (tview); + if (!sel) + return; /* hmmm */ + if (gtk_tree_selection_get_selected (sel, NULL, &iter)) { + char *path; + gtk_tree_model_get (GTK_TREE_MODEL(priv->_store), &iter, + MUG_COL_PATH, &path, -1); + g_signal_emit (G_OBJECT(lst), + signals[MUG_MSG_SELECTED], 0, + path); + g_free (path); + } +} + + +static void +treecell_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + MuMsgFlags flags; + MuMsgPrio prio; + + gtk_tree_model_get (tree_model, iter, + MUG_COL_FLAGS, &flags, + MUG_COL_PRIO, &prio, + -1); + + g_object_set (G_OBJECT(renderer), + "weight", (flags & MU_MSG_FLAG_NEW) ? 800 : 400, + "weight", (flags & MU_MSG_FLAG_SEEN) ? 400 : 800, + "foreground", prio == MU_MSG_PRIO_HIGH ? "red" : NULL, + NULL); +} + + +static void +append_col (GtkTreeView *treeview, const char* label, int colidx, gint maxwidth) +{ + GtkTreeViewColumn *col; + GtkCellRenderer *renderer; + + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT(renderer),"ellipsize", PANGO_ELLIPSIZE_END, NULL); + + col = gtk_tree_view_column_new_with_attributes (label, renderer, "text", + colidx, NULL); + g_object_set (G_OBJECT(col), "resizable", TRUE, NULL); + + gtk_tree_view_column_set_sort_indicator (col, TRUE); + gtk_tree_view_column_set_sort_column_id (col, colidx); + + if (maxwidth) { + gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_fixed_width (col, maxwidth); + gtk_tree_view_column_set_expand (col, FALSE); + } else { + //gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); + gtk_tree_view_column_set_expand (col, TRUE); + } + + gtk_tree_view_column_set_cell_data_func (col, renderer, + (GtkTreeCellDataFunc) treecell_func, + NULL, NULL); + + gtk_tree_view_append_column (treeview, col); +} + +static void +mug_msg_list_view_init (MugMsgListView *obj) +{ + MugMsgListViewPrivate *priv; + GtkTreeView *tview; + + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); + + priv->_xpath = priv->_query = NULL; + priv->_store = gtk_list_store_new (MUG_N_COLS, + G_TYPE_STRING, /* date */ + G_TYPE_STRING, /* folder */ + G_TYPE_STRING, /* flagstr */ + G_TYPE_STRING, /* from */ + G_TYPE_STRING, /* to */ + G_TYPE_STRING, /* subject */ + G_TYPE_STRING, /* path */ + G_TYPE_UINT, /* prio */ + G_TYPE_UINT); /* flags */ + + tview = GTK_TREE_VIEW (obj); + gtk_tree_view_set_model (tview, GTK_TREE_MODEL(priv->_store)); + + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE); + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(obj), + GTK_TREE_VIEW_GRID_LINES_VERTICAL); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), TRUE); + + append_col (tview, "Date", MUG_COL_DATE, 80); + append_col (tview, "Folder", MUG_COL_MAILDIR, 60); + append_col (tview, "Flags", MUG_COL_FLAGSSTR, 20); + append_col (tview, "From", MUG_COL_FROM, 0); + append_col (tview, "To", MUG_COL_TO, 0); + append_col (tview, "Subject", MUG_COL_SUBJECT, 0); + + g_signal_connect (G_OBJECT(obj), "cursor-changed", + G_CALLBACK(on_cursor_changed), + obj); +} + +static void +mug_msg_list_view_finalize (GObject *obj) +{ + MugMsgListViewPrivate *priv; + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); + + if (priv->_store) + g_object_unref (priv->_store); + + g_free (priv->_xpath); + g_free (priv->_query); + + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +void +mug_msg_list_view_move_first (MugMsgListView *self) +{ + GtkTreePath *path; + + g_return_if_fail (MUG_IS_MSG_LIST_VIEW(self)); + + path = gtk_tree_path_new_first (); + gtk_tree_view_set_cursor (GTK_TREE_VIEW(self), path, + NULL, FALSE); + + gtk_tree_path_free (path); +} + + +static gboolean +msg_list_view_move (MugMsgListView *self, gboolean next) +{ + GtkTreePath *path; + + gtk_tree_view_get_cursor (GTK_TREE_VIEW(self), &path, NULL); + if (!path) + return FALSE; + + if (next) + gtk_tree_path_next (path); + else + gtk_tree_path_prev (path); + + gtk_tree_view_set_cursor (GTK_TREE_VIEW(self), path, NULL, FALSE); + gtk_tree_path_free (path); + + return TRUE; +} + + +gboolean +mug_msg_list_view_move_next (MugMsgListView *self) +{ + g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); + + return msg_list_view_move (self, TRUE); +} + + +gboolean +mug_msg_list_view_move_prev (MugMsgListView *self) +{ + g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); + + return msg_list_view_move (self, FALSE); +} + +GtkWidget* +mug_msg_list_view_new (const char *xpath) +{ + GtkWidget *w; + MugMsgListViewPrivate *priv; + + g_return_val_if_fail (xpath, NULL); + + w = GTK_WIDGET(g_object_new(MUG_TYPE_MSG_LIST_VIEW, NULL)); + + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(w); + priv->_xpath = g_strdup (xpath); + + return w; +} + + +static gchar* +empty_or_display_contact (const gchar* str) +{ + if (!str || *str == '\0') + return g_strdup ("-"); + else + return mu_msg_str_display_contact (str); + +} + +static MuMsgIter * +run_query (const char *xpath, const char *query) +{ + MuQuery *xapian; + MuMsgIter *iter; + + xapian = mu_query_new (xpath); + if (!xapian) { + g_printerr ("Failed to create a Xapian query\n"); + return NULL; + } + + iter = mu_query_run (xapian, query, NULL, TRUE, 0); + mu_query_destroy (xapian); + if (!iter) { + g_warning ("error: running query failed\n"); + return NULL; + } + + return iter; +} + +static void +add_row (GtkListStore *store, MuMsgIter *iter) +{ + GtkTreeIter treeiter; + const gchar *datestr, *flagstr; + gchar *from, *to; + time_t date; + + date = mu_msg_iter_get_date (iter); + datestr = date == 0 ? "-" : mu_msg_str_display_date_s (date); + from = empty_or_display_contact (mu_msg_iter_get_from(iter)); + to = empty_or_display_contact (mu_msg_iter_get_to(iter)); + flagstr = mu_msg_flags_to_str_s(mu_msg_iter_get_flags (iter)); + + gtk_list_store_append (store, &treeiter); + gtk_list_store_set (store, &treeiter, + MUG_COL_DATE, datestr, + MUG_COL_MAILDIR, mu_msg_iter_get_maildir (iter), + MUG_COL_FLAGSSTR, flagstr, + MUG_COL_FROM, from, + MUG_COL_TO, to, + MUG_COL_SUBJECT,mu_msg_iter_get_subject (iter), + MUG_COL_PATH, mu_msg_iter_get_path (iter), + MUG_COL_PRIO, mu_msg_iter_get_prio(iter), + MUG_COL_FLAGS, mu_msg_iter_get_flags(iter), + -1); + g_free (from); + g_free (to); +} + + +static int +update_model (GtkListStore *store, const char *xpath, const char *query) +{ + MuMsgIter *iter; + int count; + + iter = run_query (xpath, query); + if (!iter) { + g_warning ("error: running query failed\n"); + return -1; + } + + for (count = 0; !mu_msg_iter_is_done (iter); + mu_msg_iter_next (iter), ++count) + add_row (store, iter); + + mu_msg_iter_destroy (iter); + + return count; +} + + +int +mug_msg_list_view_query (MugMsgListView *self, const char *query) +{ + MugMsgListViewPrivate *priv; + gboolean rv; + + g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), FALSE); + + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(self); + gtk_list_store_clear (priv->_store); + + g_free (priv->_query); + priv->_query = query ? g_strdup(query) : NULL; + + if (!query) + return TRUE; + + rv = update_model (priv->_store, priv->_xpath, query); + + gtk_tree_view_columns_autosize (GTK_TREE_VIEW(self)); + + return rv; +} + + +const gchar* +mug_msg_list_view_get_query (MugMsgListView *self) +{ + g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW(self), NULL); + + return MUG_MSG_LIST_VIEW_GET_PRIVATE(self)->_query; +} diff --git a/toys/mug/mug-msg-list-view.h b/toys/mug/mug-msg-list-view.h new file mode 100644 index 0000000..755cc5e --- /dev/null +++ b/toys/mug/mug-msg-list-view.h @@ -0,0 +1,70 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MUG_MSG_LIST_VIEW_H__ +#define __MUG_MSG_LIST_VIEW_H__ + +#include +/* other include files */ + +G_BEGIN_DECLS + +/* convenience macros */ +#define MUG_TYPE_MSG_LIST_VIEW (mug_msg_list_view_get_type()) +#define MUG_MSG_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_MSG_LIST_VIEW,MugMsgListView)) +#define MUG_MSG_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_MSG_LIST_VIEW,MugMsgListViewClass)) +#define MUG_IS_MSG_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_MSG_LIST_VIEW)) +#define MUG_IS_MSG_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_MSG_LIST_VIEW)) +#define MUG_MSG_LIST_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_MSG_LIST_VIEW,MugMsgListViewClass)) + +typedef struct _MugMsgListView MugMsgListView; +typedef struct _MugMsgListViewClass MugMsgListViewClass; + +struct _MugMsgListView { + GtkTreeView parent; + /* insert public members, if any */ +}; + +struct _MugMsgListViewClass { + GtkTreeViewClass parent_class; + /* insert signal callback declarations, e.g. */ + void (* msg_selected) (MugMsgListView* obj, const char* msgpath); +}; + +/* member functions */ +GType mug_msg_list_view_get_type (void) G_GNUC_CONST; + +/* parameter-less _new function (constructor) */ +/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ +GtkWidget* mug_msg_list_view_new (const char *xpath); + +int mug_msg_list_view_query (MugMsgListView *self, const char *query); + + +void mug_msg_list_view_move_first (MugMsgListView *self); + +gboolean mug_msg_list_view_move_prev (MugMsgListView *self); +gboolean mug_msg_list_view_move_next (MugMsgListView *self); + +const gchar* mug_msg_list_view_get_query (MugMsgListView *self); + +G_END_DECLS + +#endif /* __MUG_MSG_LIST_VIEW_H__ */ + diff --git a/toys/mug/mug-msg-view.c b/toys/mug/mug-msg-view.c new file mode 100644 index 0000000..9bb4090 --- /dev/null +++ b/toys/mug/mug-msg-view.c @@ -0,0 +1,298 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#include "mug-msg-view.h" +#include "mu-msg.h" +#include "mu-msg-str.h" + +/* 'private'/'protected' functions */ +static void mug_msg_view_class_init (MugMsgViewClass *klass); +static void mug_msg_view_init (MugMsgView *obj); +static void mug_msg_view_finalize (GObject *obj); + +/* list my signals */ +enum { + /* MY_SIGNAL_1, */ + /* MY_SIGNAL_2, */ + LAST_SIGNAL +}; + +enum _HeaderRow { + HEADER_ROW_FROM, + HEADER_ROW_TO, + HEADER_ROW_SUBJECT, + HEADER_ROW_CC, + HEADER_ROW_DATE, + HEADER_ROW_PATH, + HEADER_ROW_MSGID, + HEADER_ROW_SIZE, + HEADER_ROW_NUM +}; +typedef enum _HeaderRow HeaderRow; + +struct _HeaderInfo { + HeaderRow row; + const char *title; +}; +typedef struct _HeaderInfo HeaderInfo; + +static const HeaderInfo HEADER_INFO[] = { + {HEADER_ROW_CC, "Cc"}, + {HEADER_ROW_SUBJECT, "Subject"}, + {HEADER_ROW_DATE, "Date"} +}; + +static const HeaderInfo HEADER_INFO_EXPANDER[] = { + {HEADER_ROW_FROM, "From"}, + {HEADER_ROW_TO, "To"}, + {HEADER_ROW_PATH, "Path"}, + {HEADER_ROW_MSGID, "Message-Id" }, + {HEADER_ROW_SIZE, "Size"} +}; + +typedef struct _MugMsgViewPrivate MugMsgViewPrivate; +struct _MugMsgViewPrivate { + + GtkWidget *_headers_area; + GtkWidget *_tablemain, *_tableexpander; + GtkWidget *_headervals [HEADER_ROW_NUM]; + + GtkWidget *_expander_header, *_expander; + GtkWidget *_view; +}; +#define MUG_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MUG_TYPE_MSG_VIEW, MugMsgViewPrivate)) +/* globals */ +static GtkVBoxClass *parent_class = NULL; + +/* uncomment the following if you have defined any signals */ +/* static guint signals[LAST_SIGNAL] = {0}; */ + + +G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_VBOX); + +static void +mug_msg_view_class_init (MugMsgViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = mug_msg_view_finalize; + + g_type_class_add_private (gobject_class, sizeof(MugMsgViewPrivate)); + + /* signal definitions go here, e.g.: */ +/* signals[MY_SIGNAL_1] = */ +/* g_signal_new ("my_signal_1",....); */ +/* signals[MY_SIGNAL_2] = */ +/* g_signal_new ("my_signal_2",....); */ +/* etc. */ +} + + +static GtkWidget* +create_table (MugMsgViewPrivate *priv, const HeaderInfo *hinfo, guint num) +{ + guint i; + GtkWidget *table; + + table = gtk_table_new (num, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE(table), 5); + + for (i = 0; i < num; ++i) { + + char *str; + GtkWidget *l, *al; + + l = gtk_label_new(NULL); + gtk_misc_set_alignment (GTK_MISC(l), 0.0, 0.5); + + gtk_label_set_justify (GTK_LABEL(l), GTK_JUSTIFY_LEFT); + str = g_strdup_printf ("%s:", hinfo[i].title); + gtk_label_set_markup (GTK_LABEL(l), str); + g_free (str); + + gtk_table_attach (GTK_TABLE(table), l, + 0, 1, i, i+1, + GTK_FILL, GTK_FILL, + 0, 0); + + l = priv->_headervals[hinfo[i].row] = gtk_label_new (NULL); + al = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); + gtk_label_set_line_wrap_mode (GTK_LABEL(l), PANGO_WRAP_WORD_CHAR); + gtk_label_set_line_wrap (GTK_LABEL(l), TRUE); + gtk_label_set_selectable (GTK_LABEL(l), TRUE); + + gtk_container_add (GTK_CONTAINER(al), l); + gtk_label_set_justify (GTK_LABEL(l), GTK_JUSTIFY_LEFT); + gtk_table_attach (GTK_TABLE(table), al, + 1, 2, i, i+1, + GTK_FILL, GTK_FILL, + 0, 0); + } + + return table; +} + +static GtkWidget* +headers_area (MugMsgViewPrivate *priv) +{ + GtkWidget *scrolled, *vbox; + + priv->_tablemain = create_table (priv, HEADER_INFO, + G_N_ELEMENTS(HEADER_INFO)); + priv->_tableexpander = create_table (priv, HEADER_INFO_EXPANDER, + G_N_ELEMENTS(HEADER_INFO_EXPANDER)); + priv->_expander = gtk_expander_new ("Details"); + gtk_container_add (GTK_CONTAINER(priv->_expander), + priv->_tableexpander); + + vbox = gtk_vbox_new (FALSE, FALSE); + gtk_box_pack_start (GTK_BOX(vbox), priv->_tablemain, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(vbox), priv->_expander, FALSE, FALSE, 0); + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled), vbox); + + return priv->_headers_area = scrolled; +} + + +static void +mug_msg_view_init (MugMsgView *obj) +{ + MugMsgViewPrivate *priv; + GtkWidget *scrolled; + + priv = MUG_MSG_VIEW_GET_PRIVATE(obj); + + priv->_view = gtk_text_view_new (); + gtk_text_view_set_editable (GTK_TEXT_VIEW(priv->_view), FALSE); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW(priv->_view), 10); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW(priv->_view), 10); + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (scrolled), priv->_view); + + gtk_box_pack_start (GTK_BOX(obj), headers_area(priv), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(obj), scrolled, TRUE, TRUE, 0); + + gtk_widget_hide (priv->_headers_area); +} + +static void +mug_msg_view_finalize (GObject *obj) +{ +/* free/unref instance resources here */ + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +GtkWidget* +mug_msg_view_new (void) +{ + return GTK_WIDGET(g_object_new(MUG_TYPE_MSG_VIEW, NULL)); +} + + + +gboolean +mug_msg_view_set_text (MugMsgView *self, const char* txt) +{ + MugMsgViewPrivate *priv; + GtkTextBuffer *buf; + + g_return_val_if_fail (MUG_IS_MSG_VIEW(self), FALSE); + priv = MUG_MSG_VIEW_GET_PRIVATE(self); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->_view)); + gtk_text_buffer_set_text (buf, txt ? txt : "", -1); + + return TRUE; +} + + +static void +fill_header (MugMsgViewPrivate *priv, MuMsg* msg) +{ + int i; + for (i = 0; i != HEADER_ROW_NUM; ++i) { + const gchar* val; + switch (i) { + case HEADER_ROW_FROM: val = mu_msg_get_from(msg); break; + case HEADER_ROW_TO: val = mu_msg_get_to(msg); break; + case HEADER_ROW_SUBJECT: val = mu_msg_get_subject(msg); break; + case HEADER_ROW_MSGID: val = mu_msg_get_msgid(msg); break; + case HEADER_ROW_CC: val = mu_msg_get_cc (msg); break; + case HEADER_ROW_PATH: val = mu_msg_get_path (msg); break; + case HEADER_ROW_DATE: val = mu_msg_str_date_s( + "%c", mu_msg_get_date (msg)); + break; + case HEADER_ROW_SIZE: val = mu_msg_str_size_s (mu_msg_get_size(msg)); + break; + default: val = NULL; + } + + { + gchar *str; + str = g_markup_escape_text (val ? val : "", -1); + gtk_label_set_markup (GTK_LABEL(priv->_headervals[i]), str); + g_free (str); + } + } + + gtk_widget_show (priv->_tablemain); + gtk_widget_show (priv->_expander); +} + + +gboolean +mug_msg_view_set_msg (MugMsgView *self, const char* msgpath) +{ + MugMsgViewPrivate *priv; + MuMsg* msg; + gboolean rv; + + g_return_val_if_fail (MUG_IS_MSG_VIEW(self), FALSE); + + priv = MUG_MSG_VIEW_GET_PRIVATE(self); + + if (!msgpath) { + mug_msg_view_set_text (self, ""); + gtk_widget_hide (priv->_headers_area); + return TRUE; + } + + msg = mu_msg_new (msgpath, NULL); + if (!msg) + return FALSE; + + rv = mug_msg_view_set_text (self, mu_msg_get_body_text(msg)); + fill_header (priv, msg); + gtk_widget_show (priv->_headers_area); + + mu_msg_destroy (msg); + + return rv; +} diff --git a/toys/mug/mug-msg-view.h b/toys/mug/mug-msg-view.h new file mode 100644 index 0000000..88380ff --- /dev/null +++ b/toys/mug/mug-msg-view.h @@ -0,0 +1,63 @@ +/* +** Copyright (C) 2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#ifndef __MUG_MSG_VIEW_H__ +#define __MUG_MSG_VIEW_H__ + +#include +/* other include files */ + +G_BEGIN_DECLS + +/* convenience macros */ +#define MUG_TYPE_MSG_VIEW (mug_msg_view_get_type()) +#define MUG_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_MSG_VIEW,MugMsgView)) +#define MUG_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_MSG_VIEW,MugMsgViewClass)) +#define MUG_IS_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_MSG_VIEW)) +#define MUG_IS_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_MSG_VIEW)) +#define MUG_MSG_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_MSG_VIEW,MugMsgViewClass)) + +typedef struct _MugMsgView MugMsgView; +typedef struct _MugMsgViewClass MugMsgViewClass; + +struct _MugMsgView { + GtkVBox parent; + /* insert public members, if any */ +}; + +struct _MugMsgViewClass { + GtkVBoxClass parent_class; + /* insert signal callback declarations, e.g. */ + /* void (* my_event) (MugMsg* obj); */ +}; + +/* member functions */ +GType mug_msg_view_get_type (void) G_GNUC_CONST; + +/* parameter-less _new function (constructor) */ +/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ +GtkWidget* mug_msg_view_new (void); +gboolean mug_msg_view_set_msg (MugMsgView *self, const char* msgpath); +gboolean mug_msg_view_set_text (MugMsgView *self, const char* txt); + +G_END_DECLS + +#endif /* __MUG_MSG_VIEW_H__ */ + diff --git a/toys/mug/mug-query-bar.c b/toys/mug/mug-query-bar.c new file mode 100644 index 0000000..f925c73 --- /dev/null +++ b/toys/mug/mug-query-bar.c @@ -0,0 +1,141 @@ +/* mug-query-bar.c */ + +/* insert (c)/licensing information) */ + +#include "mug-query-bar.h" +/* include other impl specific header files */ + +/* 'private'/'protected' functions */ +static void mug_query_bar_class_init (MugQueryBarClass *klass); +static void mug_query_bar_init (MugQueryBar *obj); +static void mug_query_bar_finalize (GObject *obj); + +/* list my signals */ +enum { + MUG_QUERY_CHANGED, + LAST_SIGNAL +}; + +typedef struct _MugQueryBarPrivate MugQueryBarPrivate; +struct _MugQueryBarPrivate { + GtkWidget *_entry; +}; +#define MUG_QUERY_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MUG_TYPE_QUERY_BAR, \ + MugQueryBarPrivate)) +/* globals */ +static GtkContainerClass *parent_class = NULL; + +static guint signals[LAST_SIGNAL] = {0}; + +GType +mug_query_bar_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(MugQueryBarClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) mug_query_bar_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(MugQueryBar), + 0, /* n_preallocs, ignored since 2.10 */ + (GInstanceInitFunc) mug_query_bar_init, + NULL + }; + my_type = g_type_register_static (GTK_TYPE_HBOX, + "MugQueryBar", + &my_info, 0); + } + return my_type; +} + +static void +mug_query_bar_class_init (MugQueryBarClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = mug_query_bar_finalize; + + g_type_class_add_private (gobject_class, sizeof(MugQueryBarPrivate)); + + /* signal definitions go here, e.g.: */ + signals[MUG_QUERY_CHANGED] = + g_signal_new ("query_changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugQueryBarClass, query_changed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + + +static void +on_entry_activated (GtkWidget *w, MugQueryBar *bar) +{ + MugQueryBarPrivate *priv; + + priv = MUG_QUERY_BAR_GET_PRIVATE(bar); + + g_signal_emit (G_OBJECT(bar), signals[MUG_QUERY_CHANGED], 0, + gtk_entry_get_text(GTK_ENTRY(w))); +} + +static void +mug_query_bar_init (MugQueryBar *obj) +{ + MugQueryBarPrivate *priv; + + priv = MUG_QUERY_BAR_GET_PRIVATE(obj); + + priv->_entry = gtk_entry_new (); + + g_signal_connect (priv->_entry, "activate", G_CALLBACK(on_entry_activated), + obj); + + gtk_box_pack_start (GTK_BOX(obj), priv->_entry, TRUE, TRUE, 0); +} + +static void +mug_query_bar_finalize (GObject *obj) +{ +/* free/unref instance resources here */ + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +GtkWidget* +mug_query_bar_new (void) +{ + return GTK_WIDGET(g_object_new(MUG_TYPE_QUERY_BAR, NULL)); +} + + +void +mug_query_bar_set_query (MugQueryBar *self, const char *query, gboolean run) +{ + MugQueryBarPrivate *priv; + + g_return_if_fail (MUG_IS_QUERY_BAR(self)); + priv = MUG_QUERY_BAR_GET_PRIVATE(self); + + gtk_entry_set_text (GTK_ENTRY(priv->_entry), query ? query : ""); + + if (run) + on_entry_activated (priv->_entry, self); +} + + +void +mug_query_bar_grab_focus (MugQueryBar *self) +{ + g_return_if_fail (MUG_IS_QUERY_BAR(self)); + + gtk_widget_grab_focus + (GTK_WIDGET(MUG_QUERY_BAR_GET_PRIVATE(self)->_entry)); +} + diff --git a/toys/mug/mug-query-bar.h b/toys/mug/mug-query-bar.h new file mode 100644 index 0000000..2c954cf --- /dev/null +++ b/toys/mug/mug-query-bar.h @@ -0,0 +1,48 @@ +/* mug-query-bar.h */ +/* insert (c)/licensing information) */ + +#ifndef __MUG_QUERY_BAR_H__ +#define __MUG_QUERY_BAR_H__ + +#include +/* other include files */ + +G_BEGIN_DECLS + +/* convenience macros */ +#define MUG_TYPE_QUERY_BAR (mug_query_bar_get_type()) +#define MUG_QUERY_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_QUERY_BAR,MugQueryBar)) +#define MUG_QUERY_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_QUERY_BAR,MugQueryBarClass)) +#define MUG_IS_QUERY_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_QUERY_BAR)) +#define MUG_IS_QUERY_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_QUERY_BAR)) +#define MUG_QUERY_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_QUERY_BAR,MugQueryBarClass)) + +typedef struct _MugQueryBar MugQueryBar; +typedef struct _MugQueryBarClass MugQueryBarClass; + +struct _MugQueryBar { + GtkHBox parent; + /* insert public members, if any */ +}; + +struct _MugQueryBarClass { + GtkHBoxClass parent_class; + /* insert signal callback declarations, e.g. */ + void (* query_changed) (MugQueryBar* obj, const char *query); +}; + +/* member functions */ +GType mug_query_bar_get_type (void) G_GNUC_CONST; + +/* parameter-less _new function (constructor) */ +/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ +GtkWidget* mug_query_bar_new (void); + +void mug_query_bar_grab_focus (MugQueryBar *self); + +void mug_query_bar_set_query (MugQueryBar *self, const char *query, gboolean run); + +G_END_DECLS + +#endif /* __MUG_QUERY_BAR_H__ */ + diff --git a/toys/mug/mug-shortcuts.c b/toys/mug/mug-shortcuts.c new file mode 100644 index 0000000..808b2fc --- /dev/null +++ b/toys/mug/mug-shortcuts.c @@ -0,0 +1,155 @@ +/* +** Copyright (C) 2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mug-shortcuts.h" +#include "mu-bookmarks.h" + +/* include other impl specific header files */ + +/* 'private'/'protected' functions */ +static void mug_shortcuts_class_init (MugShortcutsClass *klass); +static void mug_shortcuts_init (MugShortcuts *obj); +static void mug_shortcuts_finalize (GObject *obj); + +#define MUG_SHORTCUT_BOOKMARK "bookmark" + +/* list my signals */ +enum { + SHORTCUT_CLICKED, + /* MY_SIGNAL_1, */ + /* MY_SIGNAL_2, */ + LAST_SIGNAL +}; + +struct _MugShortcutsPrivate { + GtkWidget *_bbox; + +}; +#define MUG_SHORTCUTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MUG_TYPE_SHORTCUTS, \ + MugShortcutsPrivate)) +/* globals */ +static GtkVBoxClass *parent_class = NULL; + +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_VBOX); + +static void +mug_shortcuts_class_init (MugShortcutsClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = mug_shortcuts_finalize; + + g_type_class_add_private (gobject_class, sizeof(MugShortcutsPrivate)); + + /* signal definitions go here, e.g.: */ + signals[SHORTCUT_CLICKED] = + g_signal_new ("clicked", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugShortcutsClass, clicked), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + +/* signals[MY_SIGNAL_2] = */ +/* g_signal_new ("my_signal_2",....); */ +/* etc. */ +} + +static void +mug_shortcuts_init (MugShortcuts *obj) +{ + obj->_priv = MUG_SHORTCUTS_GET_PRIVATE(obj); + + obj->_priv->_bbox = gtk_vbutton_box_new (); + gtk_button_box_set_layout (GTK_BUTTON_BOX(obj->_priv->_bbox), + GTK_BUTTONBOX_START); + gtk_box_pack_start (GTK_BOX(obj), obj->_priv->_bbox, TRUE, TRUE, 0); +} + +static void +mug_shortcuts_finalize (GObject *obj) +{ +/* free/unref instance resources here */ + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +static void +on_button_clicked (GtkWidget *button, MugShortcuts *self) +{ + g_signal_emit (G_OBJECT(self), + signals[SHORTCUT_CLICKED], 0, + (const gchar*)g_object_get_data (G_OBJECT(button), + MUG_SHORTCUT_BOOKMARK)); +} + + +static void +each_bookmark (const char* key, const char* val, MugShortcuts *self) +{ + GtkWidget *button; + + button = gtk_button_new_with_label (key); + g_object_set_data_full (G_OBJECT(button), MUG_SHORTCUT_BOOKMARK, + g_strdup(val), g_free); + g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), + self); + + gtk_container_add (GTK_CONTAINER(self->_priv->_bbox), button); +} + +static gboolean +init_shortcuts (MugShortcuts *self, const char* bmpath) +{ + MuBookmarks *bookmarks; + + bookmarks = mu_bookmarks_new (bmpath); + if (!bookmarks) + return TRUE; + + mu_bookmarks_foreach (bookmarks, (MuBookmarksForeachFunc)each_bookmark, + self); + + mu_bookmarks_destroy (bookmarks); + return TRUE; +} + +GtkWidget* +mug_shortcuts_new (const char *bmpath) +{ + MugShortcuts *self; + + self = MUG_SHORTCUTS(g_object_new(MUG_TYPE_SHORTCUTS, NULL)); + if (!init_shortcuts (self, bmpath)) { + g_object_unref (self); + return NULL; + } + + return GTK_WIDGET(self); +} + +/* following: other function implementations */ +/* such as mug_shortcuts_do_something, or mug_shortcuts_has_foo */ + diff --git a/toys/mug/mug-shortcuts.h b/toys/mug/mug-shortcuts.h new file mode 100644 index 0000000..16970fc --- /dev/null +++ b/toys/mug/mug-shortcuts.h @@ -0,0 +1,69 @@ +/* +** Copyright (C) 2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#ifndef __MUG_SHORTCUTS_H__ +#define __MUG_SHORTCUTS_H__ + +#include +/* other include files */ + +G_BEGIN_DECLS + +/* convenience macros */ +#define MUG_TYPE_SHORTCUTS (mug_shortcuts_get_type()) +#define MUG_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MUG_TYPE_SHORTCUTS,MugShortcuts)) +#define MUG_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MUG_TYPE_SHORTCUTS,MugShortcutsClass)) +#define MUG_IS_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MUG_TYPE_SHORTCUTS)) +#define MUG_IS_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MUG_TYPE_SHORTCUTS)) +#define MUG_SHORTCUTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MUG_TYPE_SHORTCUTS,MugShortcutsClass)) + +typedef struct _MugShortcuts MugShortcuts; +typedef struct _MugShortcutsClass MugShortcutsClass; +typedef struct _MugShortcutsPrivate MugShortcutsPrivate; + +struct _MugShortcuts { + GtkVBox parent; + /* insert public members, if any */ + + /* private */ + MugShortcutsPrivate *_priv; +}; + +struct _MugShortcutsClass { + GtkVBoxClass parent_class; + void (*clicked) (MugShortcuts* obj, const char* query); +}; + +/* member functions */ +GType mug_shortcuts_get_type (void) G_GNUC_CONST; + +/* parameter-less _new function (constructor) */ +/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ +GtkWidget* mug_shortcuts_new (const char *bmpath); + +/* fill in other public functions, e.g.: */ +/* void mug_shortcuts_do_something (MugShortcuts *self, const gchar* param); */ +/* gboolean mug_shortcuts_has_foo (MugShortcuts *self, gint value); */ + + +G_END_DECLS + +#endif /* __MUG_SHORTCUTS_H__ */ + diff --git a/toys/mug/mug.cc b/toys/mug/mug.cc new file mode 100644 index 0000000..f9316f6 --- /dev/null +++ b/toys/mug/mug.cc @@ -0,0 +1,338 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY 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, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG*/ + +#include +#include /* for memset */ + +#include "mu-util.h" +#include "mu-runtime.h" + +#include "mug-msg-list-view.h" +#include "mug-query-bar.h" +#include "mug-msg-view.h" +#include "mug-shortcuts.h" + +struct _MugData { + GtkWidget *win; + GtkWidget *statusbar; + GtkWidget *mlist; + GtkWidget *toolbar; + GtkWidget *msgview; + GtkWidget *querybar; + GtkWidget *shortcuts; + gchar *muhome; +}; +typedef struct _MugData MugData; + + +static void +about_mug (MugData *mugdata) +{ + GtkWidget *about; + about = gtk_message_dialog_new + (GTK_WINDOW(mugdata->win), GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO,GTK_BUTTONS_OK, + "Mug version %s\n" + "A graphical frontend to the 'mu' e-mail search engine\n\n" + "(c) 2010 Dirk-Jan C. Binnema\n" + "Released under the terms of the GPLv3+", VERSION); + + gtk_dialog_run (GTK_DIALOG(about)); + gtk_widget_destroy (about); +} + +enum _ToolAction { + ACTION_PREV_MSG = 1, + ACTION_NEXT_MSG, + ACTION_DO_QUIT, + ACTION_ABOUT, + ACTION_SEPARATOR /* pseudo action */ +}; +typedef enum _ToolAction ToolAction; + +static void +on_tool_button_clicked (GtkToolButton *btn, MugData *mugdata) +{ + ToolAction action; + action = (ToolAction)GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(btn), + "action")); + switch (action) { + + case ACTION_DO_QUIT: + gtk_main_quit(); + break; + case ACTION_NEXT_MSG: + mug_msg_list_view_move_next (MUG_MSG_LIST_VIEW(mugdata->mlist)); + break; + case ACTION_PREV_MSG: + mug_msg_list_view_move_prev (MUG_MSG_LIST_VIEW(mugdata->mlist)); + break; + case ACTION_ABOUT: + about_mug (mugdata); + break; + default: + g_print ("%u\n", action); + } +} + +static GtkWidget* +mug_toolbar (MugData *mugdata) +{ + GtkWidget *toolbar; + int i; + struct { + const char* stock_id; + ToolAction action; + } tools[] = { + { GTK_STOCK_GO_UP, ACTION_PREV_MSG }, + { GTK_STOCK_GO_DOWN, ACTION_NEXT_MSG }, + { NULL, ACTION_SEPARATOR }, + { GTK_STOCK_ABOUT, ACTION_ABOUT }, + { NULL, ACTION_SEPARATOR }, + { GTK_STOCK_QUIT, ACTION_DO_QUIT }, + }; + + for (toolbar = gtk_toolbar_new(), i = 0; i != G_N_ELEMENTS(tools); ++i) { + GtkToolItem *btn; + + /* separator item ? */ + if (tools[i].action == ACTION_SEPARATOR) { + gtk_toolbar_insert (GTK_TOOLBAR(toolbar), + gtk_separator_tool_item_new(), i); + continue; + } + + /* nope: a real item */ + btn = gtk_tool_button_new_from_stock (tools[i].stock_id); + g_object_set_data (G_OBJECT(btn), "action", + GUINT_TO_POINTER(tools[i].action)); + g_signal_connect (G_OBJECT(btn), "clicked", + G_CALLBACK(on_tool_button_clicked), + mugdata); + gtk_toolbar_insert (GTK_TOOLBAR(toolbar), btn, i); + } + + return toolbar; +} + +static void +on_shortcut_clicked (GtkWidget *w, const gchar *query, MugData *mdata) +{ + mug_query_bar_set_query (MUG_QUERY_BAR(mdata->querybar), + query, TRUE); +} + + +static GtkWidget* +mug_shortcuts_bar (MugData *data) +{ + data->shortcuts = mug_shortcuts_new (mu_runtime_bookmarks_file()); + + g_signal_connect (G_OBJECT(data->shortcuts), "clicked", + G_CALLBACK(on_shortcut_clicked), data); + + return data->shortcuts; +} + + +static GtkWidget* +mug_statusbar (void) +{ + GtkWidget *statusbar; + + statusbar = gtk_statusbar_new (); + + return statusbar; +} + +static void +on_query_changed (MugQueryBar *bar, const char* query, MugData *mugdata) +{ + int count; + + /* clear the old message */ + mug_msg_view_set_text (MUG_MSG_VIEW(mugdata->msgview), NULL); + + count = mug_msg_list_view_query (MUG_MSG_LIST_VIEW(mugdata->mlist), + query); + if (count >= 0) { + gchar *msg = + g_strdup_printf ("%d message%s found matching '%s'", + count, + count > 1 ? "s" : "", + mug_msg_list_view_get_query + (MUG_MSG_LIST_VIEW(mugdata->mlist))); + gtk_statusbar_push (GTK_STATUSBAR(mugdata->statusbar), 0, msg); + g_free (msg); + + mug_msg_list_view_move_first (MUG_MSG_LIST_VIEW(mugdata->mlist)); + gtk_widget_grab_focus (GTK_WIDGET(mugdata->mlist)); + } +} + + +static void +on_msg_selected (MugMsgListView *mlist, const char* mpath, MugData *mugdata) +{ + // g_warning ("msg selected: %s", mpath); + mug_msg_view_set_msg (MUG_MSG_VIEW(mugdata->msgview), mpath); +} + + + +static GtkWidget* +mug_querybar (void) +{ + GtkWidget *querybar; + + querybar = mug_query_bar_new (); + + return querybar; +} + + +static GtkWidget* +mug_query_area (MugData *mugdata) +{ + GtkWidget *queryarea; + GtkWidget *paned; + GtkWidget *scrolled; + + queryarea = gtk_vbox_new (FALSE, 2); + paned = gtk_vpaned_new (); + + mugdata->mlist = mug_msg_list_view_new(mu_runtime_xapian_dir()); + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER(scrolled), mugdata->mlist); + gtk_paned_add1 (GTK_PANED (paned), scrolled); + + mugdata->msgview = mug_msg_view_new (); + mug_msg_view_set_msg (MUG_MSG_VIEW(mugdata->msgview), NULL); + g_signal_connect (G_OBJECT(mugdata->mlist), "msg-selected", + G_CALLBACK(on_msg_selected), mugdata); + gtk_paned_add2 (GTK_PANED (paned), mugdata->msgview); + + mugdata->querybar = mug_querybar(); + g_signal_connect (G_OBJECT(mugdata->querybar), "query-changed", + G_CALLBACK(on_query_changed), + mugdata); + + gtk_box_pack_start (GTK_BOX(queryarea), + mugdata->querybar, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX(queryarea), + paned, TRUE, TRUE, 2); + + return queryarea; +} + + +static GtkWidget* +mug_main_area (MugData *mugdata) +{ + GtkWidget *mainarea; + + mainarea = gtk_hbox_new (FALSE, 0); + + gtk_box_pack_start (GTK_BOX(mainarea), mug_shortcuts_bar(mugdata), + FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(mainarea), mug_query_area(mugdata), + TRUE, TRUE, 0); + + return mainarea; +} + + +GtkWidget* +mug_shell (MugData *mugdata) +{ + GtkWidget *vbox; + gchar *icon; + + mugdata->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW(mugdata->win), "Mug Mail Search"); + + vbox = gtk_vbox_new (FALSE, 2); + mugdata->toolbar = mug_toolbar(mugdata); + gtk_box_pack_start (GTK_BOX(vbox), mugdata->toolbar, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX(vbox), mug_main_area(mugdata), TRUE, TRUE, 2); + + mugdata->statusbar = mug_statusbar(); + gtk_box_pack_start (GTK_BOX(vbox), mugdata->statusbar, FALSE, FALSE, 2); + + gtk_container_add (GTK_CONTAINER(mugdata->win), vbox); + gtk_widget_show_all (vbox); + + gtk_window_set_default_size (GTK_WINDOW(mugdata->win), 700, 500); + gtk_window_set_resizable (GTK_WINDOW(mugdata->win), TRUE); + + icon = g_strdup_printf ("%s%cmug.svg", ICONDIR, G_DIR_SEPARATOR); + gtk_window_set_icon_from_file (GTK_WINDOW(mugdata->win), icon, NULL); + g_free (icon); + + return mugdata->win; +} + +int +main (int argc, char *argv[]) +{ + MugData mugdata; + GtkWidget *mugshell; + GOptionContext *octx; + GOptionEntry entries[] = { + {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &mugdata.muhome, + "specify an alternative mu directory", NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} /* sentinel */ + }; + + gtk_init (&argc, &argv); + + octx = g_option_context_new ("- mug options"); + g_option_context_add_main_entries (octx, entries, "Mug"); + + memset (&mugdata, 0, sizeof(MugData)); + if (!g_option_context_parse (octx, &argc, &argv, NULL)) { + g_printerr ("mug: error in options\n"); + return 1; + } + + mu_runtime_init (mugdata.muhome); + + mugshell = mug_shell (&mugdata); + g_signal_connect(G_OBJECT(mugshell), "destroy", + G_CALLBACK(gtk_main_quit), NULL); + + gtk_widget_show (mugshell); + mug_query_bar_grab_focus (MUG_QUERY_BAR(mugdata.querybar)); + + gtk_main (); + g_free (mugdata.muhome); + + mu_runtime_uninit (); + + return 0; +} diff --git a/toys/mug/mug.desktop.in b/toys/mug/mug.desktop.in new file mode 100644 index 0000000..8a60306 --- /dev/null +++ b/toys/mug/mug.desktop.in @@ -0,0 +1,12 @@ +[Desktop Entry] +Version=@PACKAGE_VERSION@ +Type=Application +Name=Mug +GenericName=Mail Searcher +Comment=A UI for the mu mail searcher +Exec=@prefix@/bin/mug +X-Text-Domain=mu +Terminal=false +Icon=mug +StartupWMClass=mug +MimeType=application/x-executable; diff --git a/toys/mug/mug.svg b/toys/mug/mug.svg new file mode 100644 index 0000000..926deb5 --- /dev/null +++ b/toys/mug/mug.svg @@ -0,0 +1,510 @@ + + + + + + + + image/svg+xml + + + + Sheikh Tuhin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.0