14d1fa71dfbfd80f3635797131fb5d9e53a2042c
[mstardict] / src / mstardict.cpp
1 /*
2  *  MStarDict - International dictionary for Maemo.
3  *  Copyright (C) 2010 Roman Moravcik
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <cerrno>
25 #include <cstring>
26 #include <cstdlib>
27 #include <cstdio>
28 #include <clocale>
29
30 #include <glib.h>
31 #include <glib/gi18n.h>
32 #include <glib/gstdio.h>
33
34 #include <gtk/gtk.h>
35 #include <hildon/hildon.h>
36
37 #include <getopt.h>
38 #include <string>
39 #include <vector>
40 #include <memory>
41
42 #include "libwrapper.hpp"
43 #include "file.hpp"
44 #include "mstardict.hpp"
45
46 enum {
47         INDEX_COLUMN = 0,
48         BOOKNAME_COLUMN,
49         DEF_COLUMN,
50         N_COLUMNS
51 };
52
53
54 MStarDict::MStarDict ()
55 {
56         label_widget = NULL;
57         results_widget = NULL;
58         results_view = NULL;
59
60         /* create list of ressults */
61         results_list = gtk_list_store_new (N_COLUMNS,
62                                            G_TYPE_INT,          /* INDEX_COLUMN */
63                                            G_TYPE_STRING,       /* BOOKNAME_COLUMN */
64                                            G_TYPE_STRING);      /* DEF_COLUMN */
65
66         /* set sorting of resuslts */
67         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (results_list),
68                                               DEF_COLUMN,
69                                               GTK_SORT_ASCENDING);
70
71         /* initialize stardict library */
72         lib = new Library (true, true);
73 }
74
75 MStarDict::~MStarDict ()
76 {
77         /* destroy list of results */
78         g_object_unref (results_list);
79
80         /* deinitialize stardict library */
81         delete lib;
82 }
83
84 gboolean
85 MStarDict::on_results_view_selection_changed (GtkTreeSelection *selection,
86                                               MStarDict *mStarDict)
87 {
88         GtkTreeModel *model;
89         GtkTreeIter iter;
90         char *bookname, *def, *exp;
91         gint selected = 0;
92
93         if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
94                 /* unselect selected rows */
95                 gtk_tree_selection_unselect_all (selection);
96                 gtk_tree_model_get (model, &iter, INDEX_COLUMN, &selected, -1);
97
98                 bookname = g_markup_printf_escaped ("<span color=\"dimgray\" size=\"x-small\">%s</span>",
99                                                     mStarDict->result_list[selected].bookname.c_str());
100                 def = g_markup_printf_escaped ("<span color=\"darkred\" weight=\"heavy\" size=\"large\">%s</span>",
101                                                mStarDict->result_list[selected].def.c_str());
102                 exp = g_strdup (mStarDict->result_list[selected].exp.c_str());
103
104                 /* create translation window */
105                 mStarDict->create_translation_window (bookname, def, exp);
106
107                 g_free (bookname);
108                 g_free (def);
109                 g_free (exp);
110         }
111
112         /* grab focus to search entry */
113         gtk_widget_grab_focus (GTK_WIDGET (mStarDict->search));
114
115         return TRUE;
116 }
117
118 gboolean
119 MStarDict::on_search_entry_changed (GtkEditable *editable,
120                                     MStarDict *mStarDict)
121 {
122         GtkTreeSelection *selection;
123         const gchar *search;
124         GtkTreeIter iter;
125
126         search = gtk_entry_get_text (GTK_ENTRY (editable));
127
128         if (strcmp (search, "") == 0) {
129                 gtk_widget_show (mStarDict->label_widget);
130                 gtk_widget_hide (mStarDict->results_widget);
131         } else {
132                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (mStarDict->results_view));
133                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
134
135                 /* clear previous search results */
136                 mStarDict->result_list.clear();
137                 gtk_list_store_clear (mStarDict->results_list);
138
139                 /* unselect rows */
140                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (mStarDict->results_view));
141                 gtk_tree_selection_unselect_all (selection);
142
143                 /* fill list with new results */
144                 mStarDict->lib->process_phrase(search, mStarDict->result_list);
145                 if (!mStarDict->result_list.empty()) {
146                         for (size_t i = 0; i < mStarDict->result_list.size(); ++i) {
147                                 gtk_list_store_append (mStarDict->results_list, &iter);
148                                 gtk_list_store_set (mStarDict->results_list,
149                                                     &iter,
150                                                     INDEX_COLUMN, i,
151                                                     BOOKNAME_COLUMN, mStarDict->result_list[i].bookname.c_str(),
152                                                     DEF_COLUMN, mStarDict->result_list[i].def.c_str(),
153                                                     -1);
154                         }
155                 }
156
157                 /* unselect selected rows */
158                 gtk_tree_selection_unselect_all (selection);
159                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
160
161                 gtk_widget_hide (mStarDict->label_widget);
162                 gtk_widget_show (mStarDict->results_widget);
163         }
164
165         return TRUE;
166 }
167
168 class GetAllDictList {
169 public:
170         GetAllDictList(std::list<std::string> &dict_all_list_) :
171                                         dict_all_list(dict_all_list_) {}
172         void operator()(const std::string& url, bool disable) {
173                 dict_all_list.push_back(url);
174         }
175 private:
176         std::list<std::string> &dict_all_list;
177 };
178
179 void
180 MStarDict::load_dictionaries ()
181 {
182         strlist_t dicts_dir_list;
183         strlist_t order_list;
184         strlist_t disable_list;
185
186         std::list<std::string> load_list;
187
188         /* dictionary directory */
189         dicts_dir_list.push_back (std::string ("/home/user/MyDocs/mstardict"));
190
191         for_each_file(dicts_dir_list, ".ifo", order_list, disable_list, GetAllDictList(load_list));
192         lib->load(load_list);
193
194         lib->query_dictmask.clear();
195         for (std::list<std::string>::iterator i = load_list.begin(); i != load_list.end(); ++i) {
196                 size_t iLib;
197                 if (lib->find_lib_by_filename(i->c_str(), iLib)) {
198                         InstantDictIndex instance_dict_index;
199                         instance_dict_index.type = InstantDictType_LOCAL;
200                         instance_dict_index.index = iLib;
201                         lib->query_dictmask.push_back(instance_dict_index);
202                 }
203         }
204 }
205
206 void
207 MStarDict::create_translation_window (const gchar *bookname,
208                                       const gchar *def,
209                                       const gchar *exp)
210 {
211         GtkWidget *window, *alignment, *pannable, *vbox, *label;
212
213         window = hildon_stackable_window_new ();
214         gtk_window_set_title (GTK_WINDOW (window), _("Translation"));
215
216         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
217         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
218                                    HILDON_MARGIN_DEFAULT,
219                                    HILDON_MARGIN_DEFAULT,
220                                    HILDON_MARGIN_DOUBLE,
221                                    HILDON_MARGIN_DEFAULT);
222         gtk_container_add (GTK_CONTAINER (window), alignment);
223
224         pannable = hildon_pannable_area_new ();
225         g_object_set (G_OBJECT (pannable), "mov-mode", HILDON_MOVEMENT_MODE_BOTH,
226                       NULL);
227         gtk_container_add (GTK_CONTAINER (alignment), pannable);
228
229         vbox = gtk_vbox_new (FALSE, 0);
230         hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (pannable),
231                                                 vbox);
232
233         label = gtk_label_new ("Bookname");
234         gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
235         gtk_label_set_markup (GTK_LABEL (label), bookname);
236         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
237
238         label = gtk_label_new ("Definition");
239         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
240         gtk_label_set_markup (GTK_LABEL (label), def);
241         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
242
243         label = gtk_label_new ("Expresion");
244         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
245         gtk_label_set_markup (GTK_LABEL (label), exp);
246         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
247
248         gtk_widget_show_all (window);
249 }
250
251 void
252 MStarDict::create_main_window ()
253 {
254         HildonProgram *program = NULL;
255         GtkWidget *window, *alignment, *vbox, *pannable;
256         GtkCellRenderer *renderer;
257         GtkTreeSelection *selection;
258         GdkColor style_color;
259
260         /* hildon program */
261         program = hildon_program_get_instance ();
262         g_set_application_name (_("MStardict"));
263
264         /* main window */
265         window = hildon_stackable_window_new ();
266         hildon_program_add_window (program, HILDON_WINDOW (window));
267
268         /* aligment */
269         alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
270         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
271                                    HILDON_MARGIN_HALF,
272                                    0,
273                                    HILDON_MARGIN_DEFAULT,
274                                    HILDON_MARGIN_DEFAULT);
275         gtk_container_add (GTK_CONTAINER (window), alignment);
276
277         /* main vbox */
278         vbox = gtk_vbox_new (FALSE, 0);
279         gtk_container_add (GTK_CONTAINER (alignment), vbox);
280
281         /* no_search_result label */
282         label_widget = gtk_label_new (_("No search result"));
283         hildon_helper_set_logical_color (label_widget, GTK_RC_FG, 
284                                          GTK_STATE_NORMAL, "SecondaryTextColor");
285         hildon_helper_set_logical_font (label_widget, "LargeSystemFont");
286         gtk_box_pack_start (GTK_BOX (vbox), label_widget, TRUE, TRUE, 0);
287
288         /* alignment for pannable area */
289         results_widget = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
290         gtk_alignment_set_padding (GTK_ALIGNMENT (results_widget),
291                                    0,
292                                    0,
293                                    HILDON_MARGIN_DEFAULT,
294                                    HILDON_MARGIN_DEFAULT);
295         gtk_box_pack_start (GTK_BOX (vbox), results_widget, TRUE, TRUE, 0);
296
297         /* pannable for tree view */
298         pannable = hildon_pannable_area_new ();
299         gtk_container_add (GTK_CONTAINER (results_widget), pannable);
300
301         /* result tree view */
302         results_view = hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT);
303         gtk_tree_view_set_model (GTK_TREE_VIEW (results_view),
304                                  GTK_TREE_MODEL (results_list));
305         gtk_container_add (GTK_CONTAINER (pannable), results_view);
306
307         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (results_view));
308         g_signal_connect (selection, "changed",
309                           G_CALLBACK (on_results_view_selection_changed), this);
310
311         /* def column */
312         renderer = gtk_cell_renderer_text_new ();
313         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (results_view),
314                                                      -1,
315                                                      "Def", renderer,
316                                                      "text", DEF_COLUMN,
317                                                      NULL);
318         g_object_set (G_OBJECT (renderer), "xpad", 10, NULL);
319
320         /* bookname column */
321         renderer = gtk_cell_renderer_text_new ();
322         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (results_view),
323                                                      -1,
324                                                      "Bookname", renderer,
325                                                      "text", BOOKNAME_COLUMN,
326                                                      NULL);
327
328         if (!gtk_style_lookup_color (GTK_WIDGET (label_widget)->style, "SecondaryTextColor",
329                                      &style_color)) {
330                 gdk_color_parse ("grey", &style_color);
331         }
332         g_object_set (G_OBJECT (renderer),
333                       "xalign", 1.0,
334                       "width-chars", 10,
335                       "foreground-gdk", &style_color,
336                       "foreground-set", TRUE,
337                       "size", 12000,
338                       "ellipsize", PANGO_ELLIPSIZE_END,
339                       "ellipsize-set", TRUE,
340                       NULL);
341
342         /* search entry */
343         search = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
344         gtk_box_pack_end (GTK_BOX (vbox), search, FALSE, TRUE, 0);
345         g_signal_connect (search, "changed",
346                           G_CALLBACK (on_search_entry_changed), this);
347
348         /* window signals */
349         g_signal_connect (G_OBJECT (window), "destroy",
350                           G_CALLBACK (gtk_main_quit), NULL);
351
352         /* show all widget instead of alignment */
353         gtk_widget_show_all (GTK_WIDGET (window));
354         gtk_widget_hide (results_widget);
355
356         /* grab focus to search entry */
357         gtk_widget_grab_focus (GTK_WIDGET (search));
358 }
359
360 int
361 main (int argc, char **argv)
362 {
363         /* initialize hildon */
364         hildon_gtk_init (&argc, &argv);
365
366         /* initialize localization */
367         setlocale(LC_ALL, "");
368         bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
369         bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
370         textdomain(GETTEXT_PACKAGE);
371
372         /* create main window */
373         MStarDict mStarDict;
374         mStarDict.create_main_window ();
375
376         /* load all dictionaries */
377         mStarDict.load_dictionaries ();
378
379         gtk_main ();
380         return 0;
381 }