1 // PreferencesDialog.cc --- Preferences dialog
2 //
3 // Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Raymond Penners <raymond@dotsphinx.com>
4 // All rights reserved.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 //
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "preinclude.h"
25 
26 #include "nls.h"
27 #include "debug.hh"
28 
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <assert.h>
33 
34 #include <gtkmm/notebook.h>
35 #include <gtkmm/stock.h>
36 #include <gtkmm/menu.h>
37 #include <gtkmm/combobox.h>
38 #include <gtkmm/cellrenderer.h>
39 #include <gtkmm/scale.h>
40 #include <gtkmm/scrolledwindow.h>
41 #include <gtkmm/filechooserbutton.h>
42 
43 #include "StringUtil.hh"
44 #include "Locale.hh"
45 
46 #include "GtkUtil.hh"
47 #include "Hig.hh"
48 #include "PreferencesDialog.hh"
49 #include "TimeEntry.hh"
50 #include "TimerBoxPreferencePage.hh"
51 #include "TimerPreferencesPanel.hh"
52 #include "Util.hh"
53 #include "GUI.hh"
54 #include "GUIConfig.hh"
55 #include "DataConnector.hh"
56 
57 #include "CoreFactory.hh"
58 #include "CoreConfig.hh"
59 #include "IConfigurator.hh"
60 
61 #ifdef HAVE_DISTRIBUTION
62 #include "NetworkPreferencePage.hh"
63 #endif
64 
65 #ifndef WR_CHECK_VERSION
66 #define WR_CHECK_VERSION(comp,major,minor,micro)   \
67     (comp##_MAJOR_VERSION > (major) || \
68      (comp##_MAJOR_VERSION == (major) && comp##_MINOR_VERSION > (minor)) || \
69      (comp##_MAJOR_VERSION == (major) && comp##_MINOR_VERSION == (minor) && \
70       comp##_MICRO_VERSION >= (micro)))
71 #endif
72 
73 
74 #define RUNKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
75 
76 using namespace std;
77 
PreferencesDialog()78 PreferencesDialog::PreferencesDialog()
79   : HigDialog(_("Preferences"), false, false),
80     sound_button(NULL),
81     block_button(NULL),
82     sound_theme_button(NULL),
83     connector(NULL),
84     sound_volume_scale(NULL),
85     sound_play_button(NULL),
86     fsbutton(NULL),
87     filefilter(NULL)
88 #ifdef PLATFORM_OS_WIN32
89     ,
90     sensitivity_adjustment(3, 0, 100),
91     sensitivity_box(NULL)
92 #endif
93 {
94   TRACE_ENTER("PreferencesDialog::PreferencesDialog");
95 
96   connector = new DataConnector();
97   inhibit_events = 0;
98 
99   // Pages
100   Gtk::Widget *timer_page = Gtk::manage(create_timer_page());
101   Gtk::Notebook *gui_page = Gtk::manage(new Gtk::Notebook());
102 
103 #if !defined(PLATFORM_OS_OSX)
104   Gtk::Widget *gui_general_page = Gtk::manage(create_gui_page());
105   gui_page->append_page(*gui_general_page, _("General"));
106 #endif
107 
108 #if 1
109   Gtk::Widget *gui_sounds_page = Gtk::manage(create_sounds_page());
110   gui_page->append_page(*gui_sounds_page, _("Sounds"));
111 #endif
112 
113   Gtk::Widget *gui_mainwindow_page = Gtk::manage(create_mainwindow_page());
114   gui_page->append_page(*gui_mainwindow_page, _("Status Window"));
115 
116 #if !defined(PLATFORM_OS_OSX)
117   Gtk::Widget *gui_applet_page = Gtk::manage(create_applet_page());
118   gui_page->append_page(*gui_applet_page, _("Applet"));
119 #endif
120 
121 #ifdef HAVE_DISTRIBUTION
122   Gtk::Widget *network_page = Gtk::manage(create_network_page());
123 #endif
124 
125   // Notebook
126   add_page(_("Timers"), "time.png", *timer_page);
127   add_page(_("User interface"), "display.png", *gui_page);
128 #ifdef HAVE_DISTRIBUTION
129   add_page(_("Network"), "network.png", *network_page);
130 #endif
131 
132   // Gtk::Widget *plugins_page = Gtk::manage( new PluginsPreferencePage() );
133   // add_page( _("Plugins"), "workrave-icon-huge.png", *plugins_page );
134 
135   // Dialog
136   get_vbox()->pack_start(notebook, true, true, 0);
137   add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
138 
139   show_all();
140 
141   TRACE_EXIT();
142 }
143 
144 
145 //! Destructor.
~PreferencesDialog()146 PreferencesDialog::~PreferencesDialog()
147 {
148   TRACE_ENTER("PreferencesDialog::~PreferencesDialog");
149 
150 #if defined(HAVE_LANGUAGE_SELECTION)
151   const Gtk::TreeModel::iterator& iter = languages_combo.get_active();
152   const Gtk::TreeModel::Row row = *iter;
153   const Glib::ustring code = row[languages_columns.code];
154 
155   GUIConfig::set_locale(code);
156 #endif
157 
158   ICore *core = CoreFactory::get_core();
159   core->remove_operation_mode_override( "preferences" );
160 
161   delete connector;
162 #ifndef HAVE_GTK3
163   delete filefilter;
164 #endif
165   TRACE_EXIT();
166 }
167 
168 
169 
170 Gtk::Widget *
create_gui_page()171 PreferencesDialog::create_gui_page()
172 {
173   // Block types
174   block_button = Gtk::manage(new Gtk::ComboBoxText());
175 #if GTKMM_CHECK_VERSION(2, 24, 0)
176   block_button->append(_("No blocking"));
177   block_button->append(_("Block input"));
178   block_button->append(_("Block input and screen"));
179 #else
180   block_button->append_text(_("No blocking"));
181   block_button->append_text(_("Block input"));
182   block_button->append_text(_("Block input and screen"));
183 #endif
184 
185   int block_idx;
186   switch (GUIConfig::get_block_mode())
187     {
188     case GUIConfig::BLOCK_MODE_NONE:
189       block_idx = 0;
190       break;
191     case GUIConfig::BLOCK_MODE_INPUT:
192       block_idx = 1;
193       break;
194     default:
195       block_idx = 2;
196     }
197   block_button->set_active(block_idx);
198   block_button->signal_changed()
199     .connect(sigc::mem_fun(*this, &PreferencesDialog::on_block_changed));
200 
201   // Options
202   HigCategoryPanel *panel = Gtk::manage(new HigCategoryPanel(_("Options")));
203 
204   panel->add_label(_("Block mode:"), *block_button);
205 
206 #if defined(HAVE_LANGUAGE_SELECTION)
207   string current_locale = GUIConfig::get_locale();
208 
209   languages_model = Gtk::ListStore::create(languages_columns);
210   languages_combo.set_model(languages_model);
211 
212   std::vector<std::string> all_linguas;
213   StringUtil::split(string(ALL_LINGUAS), ' ', all_linguas);
214   all_linguas.push_back("en");
215 
216   Locale::LanguageMap languages_current_locale;
217   Locale::LanguageMap languages_native_locale;
218 
219   Locale::get_all_languages_in_current_locale(languages_current_locale);
220   Locale::get_all_languages_in_native_locale(languages_native_locale);
221 
222   Gtk::TreeModel::iterator iter = languages_model->append();
223   Gtk::TreeModel::Row row = *iter;
224   row[languages_columns.current] = _("System default");
225   row[languages_columns.native] = "";
226   row[languages_columns.code] = "";
227   row[languages_columns.enabled] = true;
228 
229   Gtk::TreeModel::iterator selected = iter;
230 
231   for (vector<std::string>::iterator i = all_linguas.begin(); i != all_linguas.end(); i++)
232     {
233       string code = *i;
234 
235       iter = languages_model->append();
236       row = *iter;
237       row[languages_columns.code] = code;
238       row[languages_columns.enabled] = true;
239 
240       if (current_locale == code)
241         {
242           selected = iter;
243         }
244 
245       string txt = languages_current_locale[code].language_name;
246       if( txt.empty() )
247       {
248           txt = "Unrecognized language: (" + code + ")";
249       }
250       else if (languages_current_locale[code].country_name != "")
251         {
252           txt += " (" + languages_current_locale[code].country_name + ")";
253         }
254       row[languages_columns.current] = txt;
255 
256       if (languages_current_locale[code].language_name !=
257           languages_native_locale[code].language_name)
258         {
259           txt = languages_native_locale[code].language_name;
260           if (languages_native_locale[code].country_name != "")
261             {
262               txt += " (" + languages_native_locale[code].country_name + ")";
263             }
264 
265           Glib::RefPtr<Pango::Layout> pl = create_pango_layout(txt);
266           if (pl->get_unknown_glyphs_count() > 0)
267             {
268               txt = _("(font not available)");
269               row[languages_columns.enabled] = false;
270             }
271 
272           row[languages_columns.native] = txt;
273         }
274     }
275 
276   languages_model->set_sort_column(languages_columns.current, Gtk::SORT_ASCENDING);
277  	languages_model->set_sort_func (languages_columns.current,
278                                   sigc::mem_fun(*this,
279                                                 &PreferencesDialog::on_cell_data_compare));
280 
281   languages_combo.pack_start(current_cellrenderer, true);
282   languages_combo.pack_start(native_cellrenderer, false);
283 
284   languages_combo.set_cell_data_func(native_cellrenderer,
285                                      sigc::mem_fun(*this,
286                                                    &PreferencesDialog::on_native_cell_data));
287   languages_combo.set_cell_data_func(current_cellrenderer,
288                                      sigc::mem_fun(*this,
289                                                    &PreferencesDialog::on_current_cell_data));
290 
291   languages_combo.set_active(selected);
292 
293   panel->add_label(_("Language:"), languages_combo);
294 #endif
295 
296   bool show_autostart = false;
297 
298 #if defined(PLATFORM_OS_WIN32)
299   show_autostart = true;
300 #elif defined(PLATFORM_OS_UNIX)
301   const char *desktop = g_getenv("XDG_CURRENT_DESKTOP");
302   show_autostart = (g_strcmp0(desktop, "Unity") == 0);
303 #endif
304 
305   if (show_autostart)
306     {
307       Gtk::Label *autostart_lab = Gtk::manage(GtkUtil::create_label(_("Start Workrave on logon"), false));
308       autostart_cb = Gtk::manage(new Gtk::CheckButton());
309       autostart_cb->add(*autostart_lab);
310       autostart_cb->signal_toggled().connect(sigc::mem_fun(*this, &PreferencesDialog::on_autostart_toggled));
311       panel->add_widget(*autostart_cb);
312 
313       connector->connect(GUIConfig::CFG_KEY_AUTOSTART, dc::wrap(autostart_cb));
314 
315 #if defined(PLATFORM_OS_WIN32)
316       char value[MAX_PATH];
317       bool rc = Util::registry_get_value(RUNKEY, "Workrave", value);
318       autostart_cb->set_active(rc);
319 #endif
320     }
321 
322   Gtk::Label *trayicon_lab = Gtk::manage(GtkUtil::create_label(_("Show system tray icon"), false));
323   trayicon_cb = Gtk::manage(new Gtk::CheckButton());
324   trayicon_cb->add(*trayicon_lab);
325   connector->connect(GUIConfig::CFG_KEY_TRAYICON_ENABLED, dc::wrap(trayicon_cb));
326 
327   panel->add_widget(*trayicon_cb, false, false);
328 
329   panel->set_border_width(12);
330   return panel;
331 }
332 
333 
334 Gtk::Widget *
create_sounds_page()335 PreferencesDialog::create_sounds_page()
336 {
337   Gtk::VBox *panel = Gtk::manage(new Gtk::VBox(false, 6));
338 
339   // Options
340   HigCategoryPanel *hig = Gtk::manage(new HigCategoryPanel(_("Sound Options")));
341   panel->pack_start(*hig, false, false, 0);
342 
343   // Sound types
344   sound_button  = Gtk::manage(new Gtk::ComboBoxText());
345 #if GTKMM_CHECK_VERSION(2, 24, 0)
346   sound_button->append(_("No sounds"));
347   sound_button->append(_("Play sounds using sound card"));
348   sound_button->append(_("Play sounds using built-in speaker"));
349 #else
350   sound_button->append_text(_("No sounds"));
351   sound_button->append_text(_("Play sounds using sound card"));
352   sound_button->append_text(_("Play sounds using built-in speaker"));
353 #endif
354   int idx;
355   if (! SoundPlayer::is_enabled())
356     idx = 0;
357   else
358     {
359       if (SoundPlayer::DEVICE_SPEAKER == SoundPlayer::get_device())
360         idx = 2;
361       else
362         idx = 1;
363     }
364   sound_button->set_active(idx);
365   sound_button->signal_changed().connect(sigc::mem_fun(*this, &PreferencesDialog::on_sound_changed));
366 
367   IGUI *gui = GUI::get_instance();
368   SoundPlayer *snd = gui->get_sound_player();
369 
370   if (snd->capability(SOUND_CAP_VOLUME))
371     {
372       // Volume
373       sound_volume_scale =  Gtk::manage(new Gtk:: HScale(0.0, 100.0, 0.0));
374       sound_volume_scale->set_increments(1.0, 5.0);
375       connector->connect(SoundPlayer::CFG_KEY_SOUND_VOLUME, dc::wrap(sound_volume_scale->get_adjustment()));
376 
377       hig->add_label(_("Volume:"), *sound_volume_scale, true, true);
378     }
379 
380   hig->add_label(_("Sound:"), *sound_button);
381 
382   if (snd->capability(SOUND_CAP_MUTE))
383     {
384       // Volume
385       mute_cb = Gtk::manage(new Gtk::CheckButton
386                             (_("Mute sounds during rest break and daily limit")));
387 
388       connector->connect(SoundPlayer::CFG_KEY_SOUND_MUTE, dc::wrap(mute_cb));
389 
390       hig->add_widget(*mute_cb, true, true);
391     }
392 
393   if (snd->capability(SOUND_CAP_EDIT))
394     {
395       // Sound themes
396       hig = Gtk::manage(new HigCategoryPanel(_("Sound Events"), true));
397       panel->pack_start(*hig, true, true, 0);
398 
399       sound_theme_button  = Gtk::manage(new Gtk::ComboBoxText());
400 
401       update_theme_selection();
402 
403       sound_theme_button->signal_changed().connect(sigc::mem_fun(*this, &PreferencesDialog::on_sound_theme_changed));
404       hig->add_label(_("Sound Theme:"), *sound_theme_button);
405 
406       sound_store = Gtk::ListStore::create(sound_model);
407       sound_treeview.set_model(sound_store);
408 
409       for (unsigned int i = 0; i < SOUND_MAX; i++)
410         {
411           Gtk::TreeModel::iterator iter = sound_store->append();
412           Gtk::TreeModel::Row row = *iter;
413 
414           bool sound_enabled = false;
415           snd->get_sound_enabled((SoundEvent)i, sound_enabled);
416 
417           row[sound_model.enabled] = sound_enabled;
418           row[sound_model.selectable] = true;
419           row[sound_model.description] = _(SoundPlayer::sound_registry[i].friendly_name);
420           row[sound_model.label] = SoundPlayer::sound_registry[i].id;
421           row[sound_model.event] = i;
422         }
423 
424       sound_treeview.set_rules_hint();
425       sound_treeview.set_search_column(sound_model.description.index());
426 
427       int cols_count = sound_treeview.append_column_editable(_("Play"), sound_model.enabled);
428       Gtk::TreeViewColumn *column = sound_treeview.get_column(cols_count - 1);
429 
430       Gtk::CellRendererToggle *cell = dynamic_cast<Gtk::CellRendererToggle*>(sound_treeview.get_column_cell_renderer(cols_count - 1));
431 
432       cols_count = sound_treeview.append_column(_("Event"), sound_model.description);
433       column = sound_treeview.get_column(cols_count - 1);
434       column->set_fixed_width(40);
435 
436       Gtk::ScrolledWindow *sound_scroll = Gtk::manage(new Gtk::ScrolledWindow());
437       sound_scroll->add(sound_treeview);
438       sound_scroll->set_size_request(-1, 200);
439       sound_treeview.set_size_request(-1, 200);
440 
441       hig->add_widget(*sound_scroll, true, true);
442 
443       Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, 6));
444 
445       sound_play_button = Gtk::manage(new Gtk::Button(_("Play")));
446       hbox->pack_start(*sound_play_button, false, false, 0);
447 
448       fsbutton = Gtk::manage(new Gtk::FileChooserButton(_("Choose a sound"),
449                                                    Gtk::FILE_CHOOSER_ACTION_OPEN
450                                                    ));
451 
452       hbox->pack_start(*fsbutton, true, true, 0);
453 
454 #ifdef HAVE_GTK3
455       filefilter = Gtk::FileFilter::create();
456 #else
457       filefilter = new Gtk::FileFilter();
458 #endif
459 
460       filefilter->set_name(_("Wavefiles"));
461 #ifdef PLATFORM_OS_WIN32
462       filefilter->add_pattern("*.wav");
463 #else
464       filefilter->add_mime_type("audio/x-wav");
465 #endif
466 #ifdef HAVE_GTK3
467       fsbutton->add_filter(filefilter);
468 #else
469       fsbutton->add_filter(*filefilter);
470 #endif
471 
472       hig->add_widget(*hbox);
473 
474       Gtk::HBox *selector_hbox = Gtk::manage(new Gtk::HBox(false, 0));
475       Gtk::Button *selector_playbutton = Gtk::manage(new Gtk::Button(_("Play")));
476 
477       selector_hbox->pack_end(*selector_playbutton, false, false, 0);
478       selector_playbutton->show();
479       fsbutton->set_extra_widget(*selector_hbox);
480 
481       cell->signal_toggled().connect(sigc::mem_fun(*this,
482                                                    &PreferencesDialog::on_sound_enabled));
483 
484       sound_play_button->signal_clicked().connect(sigc::mem_fun(*this,
485                                                                 &PreferencesDialog::on_sound_play));
486 
487       selector_playbutton->signal_clicked().connect(sigc::mem_fun(*this,
488                                                                   &PreferencesDialog::on_sound_filechooser_play));
489 
490 #if WR_CHECK_VERSION(GTKMM,2,22,0)
491       fsbutton->signal_file_set().connect(sigc::mem_fun(*this,
492                                                                  &PreferencesDialog::on_sound_filechooser_select));
493 #else
494       fsbutton->signal_selection_changed().connect(sigc::mem_fun(*this,
495                                                                  &PreferencesDialog::on_sound_filechooser_select));
496 #endif
497 
498       Glib::RefPtr<Gtk::TreeSelection> selection = sound_treeview.get_selection();
499       selection->signal_changed().connect(sigc::mem_fun(*this,
500                                                         &PreferencesDialog::on_sound_events_changed));
501 
502       Gtk::TreeModel::iterator iter = sound_store->children().begin();
503       if (iter)
504         {
505           selection->select(iter);
506         }
507 
508       update_senstives();
509     }
510 
511   panel->set_border_width(12);
512   return panel;
513 }
514 
515 
516 Gtk::Widget *
create_timer_page()517 PreferencesDialog::create_timer_page()
518 {
519   // Timers page
520   Gtk::Notebook *tnotebook = Gtk::manage(new Gtk::Notebook());
521   tnotebook->set_tab_pos (Gtk::POS_TOP);
522   Glib::RefPtr<Gtk::SizeGroup> hsize_group
523     = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
524   Glib::RefPtr<Gtk::SizeGroup> vsize_group
525     = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_VERTICAL);
526   for (int i = 0; i < BREAK_ID_SIZEOF; i++)
527     {
528       // Label
529       Gtk::Widget *box = Gtk::manage(GtkUtil::create_label_for_break
530                                 ((BreakId) i));
531       TimerPreferencesPanel *tp = Gtk::manage(new TimerPreferencesPanel(BreakId(i), hsize_group, vsize_group));
532       box->show_all();
533 #ifdef HAVE_GTK3
534       tnotebook->append_page(*tp, *box);
535 #else
536       tnotebook->pages().push_back(Gtk::Notebook_Helpers::TabElem(*tp, *box));
537 #endif
538     }
539 
540 #if defined(PLATFORM_OS_WIN32)
541   Gtk::Widget *box = Gtk::manage(GtkUtil::create_label("Monitoring", false));
542   Gtk::Widget *monitoring_page = create_monitoring_page();
543 
544 #ifdef HAVE_GTK3
545   tnotebook->append_page(*monitoring_page , *box);
546 #else
547   tnotebook->pages().push_back(Gtk::Notebook_Helpers::TabElem(*monitoring_page, *box));
548 #endif
549 #endif
550 
551   return tnotebook;
552 }
553 
554 #if defined(PLATFORM_OS_WIN32)
555 Gtk::Widget *
create_monitoring_page()556 PreferencesDialog::create_monitoring_page()
557 {
558   Gtk::VBox *panel = Gtk::manage(new Gtk::VBox(false, 6));
559   panel->set_border_width(12);
560 
561   Gtk::Label *monitor_type_lab = Gtk::manage(GtkUtil::create_label(_("Use alternate monitor"), false));
562   monitor_type_cb = Gtk::manage(new Gtk::CheckButton());
563   monitor_type_cb->add(*monitor_type_lab);
564   monitor_type_cb->signal_toggled().connect(sigc::mem_fun(*this, &PreferencesDialog::on_monitor_type_toggled));
565   panel->pack_start(*monitor_type_cb, false, false, 0);
566 
567   Gtk::Label *monitor_type_help = Gtk::manage(GtkUtil::create_label(_("Enable this option if Workrave fails to detect when you are using your computer"), false));
568   panel->pack_start(*monitor_type_help, false, false, 0);
569 
570   sensitivity_box = Gtk::manage(new Gtk::HBox());
571   Gtk::Widget *sensitivity_lab = Gtk::manage(GtkUtil::create_label_with_tooltip(_("Mouse sensitivity:"), _("Number of pixels the mouse should move before it is considered activity.")));
572   Gtk::SpinButton *sensitivity_spin = Gtk::manage(new Gtk::SpinButton(sensitivity_adjustment));
573   sensitivity_box->pack_start(*sensitivity_lab, false, false, 0);
574   sensitivity_box->pack_start(*sensitivity_spin, false, false, 0);
575   panel->pack_start(*sensitivity_box, false, false, 0);
576 
577   connector->connect(CoreConfig::CFG_KEY_MONITOR_SENSITIVITY, dc::wrap(&sensitivity_adjustment));
578 
579   string monitor_type;
580   CoreFactory::get_configurator()->get_value_with_default("advanced/monitor",
581                                                           monitor_type,
582                                                           "default");
583 
584   monitor_type_cb->set_active(monitor_type != "default");
585 
586   sensitivity_box->set_sensitive(monitor_type != "default");
587 
588   return panel;
589 }
590 
591 #endif
592 
593 Gtk::Widget *
create_mainwindow_page()594 PreferencesDialog::create_mainwindow_page()
595 {
596   // Timers page
597   return new TimerBoxPreferencePage("main_window");
598 }
599 
600 
601 Gtk::Widget *
create_applet_page()602 PreferencesDialog::create_applet_page()
603 {
604   // Timers page
605   return new TimerBoxPreferencePage("applet");
606 }
607 
608 
609 #ifdef HAVE_DISTRIBUTION
610 Gtk::Widget *
create_network_page()611 PreferencesDialog::create_network_page()
612 {
613   return new NetworkPreferencePage();
614 }
615 #endif
616 
617 void
add_page(const char * label,const char * image,Gtk::Widget & widget)618 PreferencesDialog::add_page(const char *label, const char *image,
619                             Gtk::Widget &widget)
620 {
621   string icon = Util::complete_directory(image, Util::SEARCH_PATH_IMAGES);
622   Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file(icon);
623   notebook.add_page(label, pixbuf, widget);
624 }
625 
626 void
on_sound_changed()627 PreferencesDialog::on_sound_changed()
628 {
629   int idx = sound_button->get_active_row_number();
630   SoundPlayer::set_enabled(idx > 0);
631   if (idx > 0)
632     {
633       SoundPlayer::Device dev = idx == 1
634         ? SoundPlayer::DEVICE_SOUNDCARD
635         : SoundPlayer::DEVICE_SPEAKER;
636       SoundPlayer::set_device(dev);
637     }
638 
639   update_senstives();
640 }
641 
642 void
update_senstives()643 PreferencesDialog::update_senstives()
644 {
645   int idx = sound_button->get_active_row_number();
646   if (idx > 0)
647     {
648       SoundPlayer::Device dev = idx == 1
649         ? SoundPlayer::DEVICE_SOUNDCARD
650         : SoundPlayer::DEVICE_SPEAKER;
651 
652       sound_treeview.set_sensitive(dev == SoundPlayer::DEVICE_SOUNDCARD);
653       if (sound_theme_button != NULL)
654         {
655           sound_theme_button->set_sensitive(dev == SoundPlayer::DEVICE_SOUNDCARD);
656         }
657       if (sound_volume_scale != NULL)
658         {
659           sound_volume_scale->set_sensitive(dev == SoundPlayer::DEVICE_SOUNDCARD);
660         }
661       if (sound_play_button != NULL)
662         {
663           sound_play_button->set_sensitive(dev == SoundPlayer::DEVICE_SOUNDCARD);
664         }
665       if (fsbutton != NULL)
666         {
667           fsbutton->set_sensitive(dev == SoundPlayer::DEVICE_SOUNDCARD);
668         }
669     }
670 }
671 
672 void
on_block_changed()673 PreferencesDialog::on_block_changed()
674 {
675   int idx = block_button->get_active_row_number();
676   GUIConfig::BlockMode m;
677   switch (idx)
678     {
679     case 0:
680       m = GUIConfig::BLOCK_MODE_NONE;
681       break;
682     case 1:
683       m = GUIConfig::BLOCK_MODE_INPUT;
684       break;
685     default:
686       m = GUIConfig::BLOCK_MODE_ALL;
687     }
688   GUIConfig::set_block_mode(m);
689 }
690 
691 
692 int
run()693 PreferencesDialog::run()
694 {
695   show_all();
696   return 0;
697 }
698 
699 
700 bool
on_focus_in_event(GdkEventFocus * event)701 PreferencesDialog::on_focus_in_event(GdkEventFocus *event)
702 {
703   TRACE_ENTER("PreferencesDialog::focus_in");
704 
705   GUIConfig::BlockMode block_mode = GUIConfig::get_block_mode();
706   if (block_mode != GUIConfig::BLOCK_MODE_NONE)
707     {
708       ICore *core = CoreFactory::get_core();
709 
710       OperationMode mode = core->get_operation_mode();
711       if (mode == OPERATION_MODE_NORMAL)
712         {
713           core->set_operation_mode_override( OPERATION_MODE_QUIET, "preferences" );
714         }
715     }
716   TRACE_EXIT();
717   return HigDialog::on_focus_in_event(event);
718 }
719 
720 
721 bool
on_focus_out_event(GdkEventFocus * event)722 PreferencesDialog::on_focus_out_event(GdkEventFocus *event)
723 {
724   TRACE_ENTER("PreferencesDialog::focus_out");
725   ICore *core = CoreFactory::get_core();
726 
727   core->remove_operation_mode_override( "preferences" );
728   TRACE_EXIT();
729   return HigDialog::on_focus_out_event(event);
730 }
731 
732 
733 #if defined(HAVE_LANGUAGE_SELECTION)
734 void
on_current_cell_data(const Gtk::TreeModel::const_iterator & iter)735 PreferencesDialog::on_current_cell_data(const Gtk::TreeModel::const_iterator& iter)
736 {
737   if (iter)
738   {
739     Gtk::TreeModel::Row row = *iter;
740     Glib::ustring name = row[languages_columns.current];
741     bool enabled = row[languages_columns.enabled];
742 
743     current_cellrenderer.set_property("text", name);
744     current_cellrenderer.set_property("sensitive", enabled);
745   }
746 }
747 
748 void
on_native_cell_data(const Gtk::TreeModel::const_iterator & iter)749 PreferencesDialog::on_native_cell_data(const Gtk::TreeModel::const_iterator& iter)
750 {
751   if (iter)
752   {
753     Gtk::TreeModel::Row row = *iter;
754     Glib::ustring name = row[languages_columns.native];
755     bool enabled = row[languages_columns.enabled];
756 
757     native_cellrenderer.set_property("text", name);
758     native_cellrenderer.set_property("sensitive", enabled);
759   }
760 }
761 
762 int
on_cell_data_compare(const Gtk::TreeModel::iterator & iter1,const Gtk::TreeModel::iterator & iter2)763 PreferencesDialog::on_cell_data_compare(const Gtk::TreeModel::iterator& iter1,
764                                         const Gtk::TreeModel::iterator& iter2)
765 {
766   Gtk::TreeModel::Row row1 = *iter1;
767   Gtk::TreeModel::Row row2 = *iter2;
768   Glib::ustring name1 = row1[languages_columns.current];
769   Glib::ustring name2 = row2[languages_columns.current];
770   Glib::ustring code1 = row1[languages_columns.code];
771   Glib::ustring code2 = row2[languages_columns.code];
772 
773   if (code1 == "")
774     {
775       return -1;
776     }
777   else if (code2 == "")
778     {
779       return 1;
780     }
781   else
782     {
783       return g_utf8_collate(name1.c_str(), name2.c_str());
784     }
785 }
786 #endif
787 
788 void
on_autostart_toggled()789 PreferencesDialog::on_autostart_toggled()
790 {
791 #if defined(PLATFORM_OS_WIN32)
792   bool on = autostart_cb->get_active();
793 
794   gchar *value = NULL;
795 
796   if (on)
797     {
798       string appdir = Util::get_application_directory();
799       value = g_strdup_printf("%s" G_DIR_SEPARATOR_S "lib" G_DIR_SEPARATOR_S "workrave.exe", appdir.c_str());
800     }
801 
802   Util::registry_set_value(RUNKEY, "Workrave", value);
803 #endif
804 }
805 
806 #if defined(PLATFORM_OS_WIN32)
807 void
on_monitor_type_toggled()808 PreferencesDialog::on_monitor_type_toggled()
809 {
810   bool on = monitor_type_cb->get_active();
811   CoreFactory::get_configurator()->set_value("advanced/monitor", on ? "lowlevel" : "default");
812   sensitivity_box->set_sensitive(on);
813 }
814 #endif
815 
816 void
on_sound_enabled(const Glib::ustring & path_string)817 PreferencesDialog::on_sound_enabled(const Glib::ustring &path_string)
818 {
819   Gtk::TreePath path(path_string);
820   const Gtk::TreeModel::iterator iter = sound_store->get_iter(path);
821 
822   if (iter)
823     {
824       Gtk::TreeRow row = *iter;
825 
826       IGUI *gui = GUI::get_instance();
827       SoundPlayer *snd = gui->get_sound_player();
828 
829       snd->set_sound_enabled((SoundEvent)(int)row[sound_model.event],
830                              row[sound_model.enabled]);
831     }
832 }
833 
834 
835 void
on_sound_play()836 PreferencesDialog::on_sound_play()
837 {
838   Glib::RefPtr<Gtk::TreeSelection> selection = sound_treeview.get_selection();
839   Gtk::TreeModel::iterator iter = selection->get_selected();
840 
841   if (iter)
842     {
843       Gtk::TreeModel::Row row = *iter;
844 
845       string filename;
846       bool valid = CoreFactory::get_configurator()->get_value(string(SoundPlayer::CFG_KEY_SOUND_EVENTS) +
847                                                               row[sound_model.label],
848                                                               filename);
849 
850       if (valid && filename != "")
851         {
852           IGUI *gui = GUI::get_instance();
853           SoundPlayer *snd = gui->get_sound_player();
854           snd->play_sound(filename);
855         }
856     }
857 }
858 
859 void
on_sound_filechooser_play()860 PreferencesDialog::on_sound_filechooser_play()
861 {
862   string filename = fsbutton->get_filename();
863 
864   IGUI *gui = GUI::get_instance();
865   SoundPlayer *snd = gui->get_sound_player();
866   snd->play_sound(filename);
867 }
868 
869 
870 void
on_sound_filechooser_select()871 PreferencesDialog::on_sound_filechooser_select()
872 {
873   TRACE_ENTER("PreferencesDialog::on_sound_filechooser_select");
874   string filename = fsbutton->get_filename();
875 
876   TRACE_MSG(filename << " " << fsbutton_filename << " " << inhibit_events);
877 
878   if (inhibit_events == 0 && filename != "" && fsbutton_filename != filename)
879     {
880       TRACE_MSG("ok");
881 
882       Glib::RefPtr<Gtk::TreeSelection> selection = sound_treeview.get_selection();
883       Gtk::TreeModel::iterator iter = selection->get_selected();
884 
885       if (iter) {
886         Gtk::TreeModel::Row row = *iter;
887 
888         TRACE_MSG(row[sound_model.label]);
889 
890         IGUI *gui = GUI::get_instance();
891         SoundPlayer *snd = gui->get_sound_player();
892         snd->set_sound_wav_file( (SoundEvent)(int)row[sound_model.event], filename);
893         TRACE_MSG(filename);
894         update_theme_selection();
895       }
896 
897       fsbutton_filename = filename;
898       TRACE_EXIT();
899     }
900 }
901 
902 
903 void
on_sound_events_changed()904 PreferencesDialog::on_sound_events_changed()
905 {
906   TRACE_ENTER("PreferencesDialog::on_sound_events_changed");
907   Glib::RefPtr<Gtk::TreeSelection> selection = sound_treeview.get_selection();
908   Gtk::TreeModel::iterator iter = selection->get_selected();
909 
910   if (iter)
911     {
912       Gtk::TreeModel::Row row = *iter;
913 
914       string event = (Glib::ustring) row[sound_model.label];
915       string filename;
916       bool valid = CoreFactory::get_configurator()->get_value(string(SoundPlayer::CFG_KEY_SOUND_EVENTS) +
917                                                               row[sound_model.label],
918                                                               filename);
919 
920       TRACE_MSG(filename);
921 
922       if (valid && filename != "")
923         {
924           inhibit_events++;
925           fsbutton_filename = filename;
926           fsbutton->set_filename(filename);
927           inhibit_events--;
928         }
929     }
930   TRACE_EXIT();
931 }
932 
933 
934 void
on_sound_theme_changed()935 PreferencesDialog::on_sound_theme_changed()
936 {
937   TRACE_ENTER("PreferencesDialog::on_sound_theme_changed");
938   int idx = sound_theme_button->get_active_row_number();
939 
940   if (idx >= 0 && idx < (int)sound_themes.size())
941     {
942       SoundPlayer::Theme &theme = sound_themes[idx];
943 
944       IGUI *gui = GUI::get_instance();
945       SoundPlayer *snd = gui->get_sound_player();
946       snd->activate_theme(theme);
947 
948       Glib::RefPtr<Gtk::TreeSelection> selection = sound_treeview.get_selection();
949       Gtk::TreeModel::iterator iter = selection->get_selected();
950 
951       if (iter)
952         {
953           Gtk::TreeModel::Row row = *iter;
954           string event = (Glib::ustring) row[sound_model.label];
955           string filename;
956 
957           bool valid = CoreFactory::get_configurator()->get_value(string(SoundPlayer::CFG_KEY_SOUND_EVENTS) +
958                                                                   row[sound_model.label],
959                                                                   filename);
960 
961           if (valid && filename != "")
962             {
963               TRACE_MSG(filename << " " <<row[sound_model.label]);
964               inhibit_events++;
965               fsbutton_filename = filename;
966               fsbutton->set_filename(filename);
967               inhibit_events--;
968             }
969         }
970     }
971   TRACE_EXIT();
972 }
973 
974 
975 void
update_theme_selection()976 PreferencesDialog::update_theme_selection()
977 {
978   TRACE_ENTER("PreferencesDialog::update_theme_selection");
979   sound_themes.erase(sound_themes.begin(), sound_themes.end());
980 
981   IGUI *gui = GUI::get_instance();
982   SoundPlayer *snd = gui->get_sound_player();
983   snd->get_sound_themes(sound_themes);
984 
985 #if GTKMM_CHECK_VERSION(2, 24, 0)
986   sound_theme_button->remove_all();
987 #else
988   sound_theme_button->clear_items();
989 #endif
990 
991   int idx = 0;
992   for (vector<SoundPlayer::Theme>::iterator it = sound_themes.begin(); it != sound_themes.end(); it++)
993     {
994 #if GTKMM_CHECK_VERSION(2, 24, 0)
995       sound_theme_button->append(it->description);
996 #else
997       sound_theme_button->append_text(it->description);
998 #endif
999 
1000       if (it->active)
1001        {
1002           sound_theme_button->set_active(idx);
1003         }
1004       idx++;
1005     }
1006   TRACE_EXIT();
1007 }
1008