00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kitlistgui.hpp"
00024 #include <cassert>
00025
00026
00027 #ifdef MAEMO
00028 #include <hildon/hildon-help.h>
00029 #endif
00030 #include <glibmm/i18n.h>
00031 #include <glibmm/refptr.h>
00032 #include <glibmm/ustring.h>
00033 #include <gtkmm/aboutdialog.h>
00034 #include <gtkmm/cellrenderertoggle.h>
00035 #include <gtkmm/clipboard.h>
00036 #include <gtkmm/filechooserdialog.h>
00037 #include <gtkmm/menuitem.h>
00038 #include <gtkmm/messagedialog.h>
00039 #include <gtkmm/stock.h>
00040 #include <gtkmm/targetentry.h>
00041 #include <gtkmm/window.h>
00042 #include <libglademm/xml.h>
00043 #include <libxml++/libxml++.h>
00044 #include <string>
00045 #include <sstream>
00046 #include <sys/stat.h>
00047 #include <config.h>
00048
00050 #define KITLIST_SERVICE_NAME "com.nokia."PACKAGE_NAME
00052 #define KITLIST_SERVICE_OBJECT "/com/nokia/"PACKAGE_NAME
00054 #define KITLIST_SERVICE_IFACE "com.nokia."PACKAGE_NAME
00055
00056
00057 using namespace std;
00058
00059 namespace {
00060
00061 #ifdef MAEMO
00063 const string GLADE_APP_FILE = "maemo.glade";
00064 #else
00066 const string GLADE_APP_FILE = "kitlist.glade";
00067 #endif
00069 const guint SB_ITEM_COUNT = 1000;
00071 const guint SB_SAVE = SB_ITEM_COUNT + 1;
00073 const guint SB_MSG = SB_SAVE + 1;
00074
00076 const char item_target_custom[] = "kitlistclipboard";
00078 const char item_target_text[] = "text/plain";
00079
00081 const char XML_ELEMENT_ID[] = "id";
00082
00084 const Glib::ustring DEFAULT_FILENAME_EXTENSION = ".kit";
00085
00087 const Glib::ustring DEFAULT_FILENAME = "kitlist" + DEFAULT_FILENAME_EXTENSION;
00088
00090 #ifdef MAEMO
00091 const Glib::ustring GCONF_KEY = "/apps/maemo/kitlist";
00092 #else
00093 const Glib::ustring GCONF_KEY = "/apps/kitlist";
00094 #endif
00095
00097 const Glib::ustring GCONF_KEY_CURRENT_FILENAME = GCONF_KEY + "/current_filename";
00098
00100 const gint DEFAULT_MAX_RECENT_FILES = 4;
00101
00103 const Glib::ustring GCONF_KEY_RECENT_FILES = GCONF_KEY + "/recent_files";
00104
00106 const Glib::ustring GCONF_KEY_MAX_RECENT_FILES = GCONF_KEY + "/max_recent_files";
00107
00108 }
00109
00110
00111 #ifdef KITLIST_DEBUG
00112 void my_log_handler(const gchar *log_domain,
00113 GLogLevelFlags log_level,
00114 const gchar *message,
00115 gpointer data) {
00116 g_print("KITLIST: %s\n", message);
00117 #ifdef MAEMO
00118 syslog(LOG_DEBUG, message);
00119 #endif
00120 ofstream* fout = (ofstream*) data;
00121 if (fout) {
00122 *fout << message << endl;
00123 }
00124 }
00125
00126 #endif
00127
00128
00129 typedef Gtk::TreeModel::Children type_children;
00130
00140 const bool file_exists(const Glib::ustring& filename) {
00141 struct stat fileinfo;
00142 bool retval;
00143 retval = !(stat(filename.c_str(), &fileinfo));
00144
00145 return retval;
00146 }
00147
00148
00150 const string load_resource_glade_file(const Glib::ustring& filename) {
00151 vector<string> locs;
00152 locs.push_back(filename);
00153 locs.push_back("../" + filename);
00154 locs.push_back("./src/" + filename);
00155 locs.push_back(string(PACKAGE_DATA_DIR) + "/glade/" + filename);
00156 for (std::vector<string>::iterator i = locs.begin(); i != locs.end(); ++i) {
00157 if (file_exists(*i))
00158 return *i;
00159 }
00160 return "";
00161 }
00162
00169 Glib::RefPtr<Gnome::Glade::Xml> get_glade_ref_ptr(const string& filename,
00170 const Glib::ustring& root = Glib::ustring(),
00171 const Glib::ustring& domain = Glib::ustring()) {
00172 Glib::RefPtr<Gnome::Glade::Xml> refXml;
00173 try {
00174 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00175 refXml = Gnome::Glade::Xml::create(load_resource_glade_file(filename), root, domain);
00176 #else
00177 std::auto_ptr<Gnome::Glade::XmlError> ex;
00178 refXml = Gnome::Glade::Xml::create(load_resource_glade_file(filename), root, domain, ex);
00179 if (ex.get())
00180 g_error(_("Error loading Glade file: %s"), ex->what().c_str());
00181 #endif
00182 } catch (const Gnome::Glade::XmlError& ex) {
00183 g_error(_("Error loading Glade file: %s"), ex.what().c_str());
00184 throw ex;
00185 }
00186 return refXml;
00187 }
00188
00189
00190 #ifdef MAEMO
00191
00192 void dump_osso_rpc_value(osso_rpc_t* retval) {
00193 switch (retval->type) {
00194 case (DBUS_TYPE_INVALID) :
00195 g_debug("invalid/void");
00196 break;
00197 case (DBUS_TYPE_STRING) :
00198 g_debug("string :'%s'", retval->value.s);
00199 break;
00200 case (DBUS_TYPE_UINT32) :
00201 g_debug("uint32 :%u", retval->value.u);
00202 break;
00203 case (DBUS_TYPE_INT32) :
00204 g_debug("int32 :%d", retval->value.i);
00205 break;
00206 case (DBUS_TYPE_BOOLEAN) :
00207 g_debug("boolean :%s", (retval->value.b == TRUE)?"TRUE":"FALSE ");
00208 break;
00209 case (DBUS_TYPE_DOUBLE) :
00210 g_debug("double :%.3f", retval->value.d);
00211 break;
00212 case (DBUS_TYPE_OBJECT_PATH) :
00213 break;
00214 default:
00215 g_debug("unknown(type=%d)", retval->type);
00216 break;
00217 }
00218 }
00219
00221 static gint dbus_req_handler(const gchar* interface, const gchar* method,
00222 GArray* arguments, gpointer data,
00223 osso_rpc_t* retval) {
00224 KitListGui* gui = (KitListGui*) data;
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 Glib::ustring smethod = method;
00239 if (smethod.compare("mime_open") == 0 && arguments->len > 0) {
00240 if (arguments->len > 0) {
00241 osso_rpc_t arg = g_array_index(arguments, osso_rpc_t, 0);
00242 if (arg.type == DBUS_TYPE_STRING) {
00243 Glib::ustring filename = arg.value.s;
00244 if (filename.find("file://") >= 0)
00245 filename.erase(0, 7);
00246 gui->raise();
00247 gui->safe_open_file(filename);
00248 }
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 dump_osso_rpc_value(retval);
00262 osso_rpc_free_val(retval);
00263
00264 return OSSO_OK;
00265 }
00266 #endif
00267
00268
00277 KitListGui::KitListGui(int argc, char **argv, Service& service)
00278 : m_kit(argc, argv),
00279 m_ignore_list_events(false),
00280 m_window(0),
00281 m_window_add_item(0),
00282 m_window_add_category(0),
00283 m_entry_add_item(0),
00284 m_entry_add_category(0),
00285 m_file_save_menu_item(0),
00286 m_file_save_tool_button(0),
00287 m_paste_menu_item(0),
00288 m_checkbutton_add_item(0),
00289 m_category_combo(0),
00290 m_item_tree_view(0),
00291 m_ref_item_tree_model(0),
00292 m_service(service),
00293 m_status_bar(0),
00294 m_state(ADD_CATEGORY),
00295 #ifdef MAEMO
00296 m_full_screen(false),
00297 #endif
00298 m_current_cat_id(-1) {
00299 init();
00300 }
00301
00302
00303 KitListGui::~KitListGui() {
00304 #ifdef KITLIST_DEBUG
00305 if (m_slog) {
00306 m_slog->close();
00307 delete m_slog;
00308 }
00309 #endif
00310 }
00311
00312
00314 void KitListGui::run() {
00315 m_kit.run(*m_window);
00316 #ifdef MAEMO
00317 if (m_osso_context != NULL)
00318 osso_deinitialize(m_osso_context);
00319 #endif
00320 if (m_service.is_model_dirty()) {
00321 #ifdef MAEMO
00322
00323
00324
00325
00326 if (m_filename.length() > 0) {
00327 m_service.save_as_xml(m_filename);
00328 }
00329 #else
00330 g_warning("WARNING: Application is closing with unsaved changes");
00331 #endif //MAEMO
00332 }
00333 }
00334
00335
00336 gint KitListGui::get_max_recent_files() {
00337 gint retval = DEFAULT_MAX_RECENT_FILES;
00338 #ifdef MAEMO
00339 Gnome::Conf::Value value;
00340 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00341 value = m_ref_gconf_client->get_int(GCONF_KEY_MAX_RECENT_FILES);
00342 #else
00343 std::auto_ptr<Glib::Error> error;
00344 value = m_ref_gconf_client->get(GCONF_KEY_MAX_RECENT_FILES, error);
00345 if (error.get())
00346 g_warning(_("GConf error: %s"), error->what().c_str());
00347 #endif //GLIBMM_EXCEPTIONS_ENABLED
00348 if (value.get_type() == Gnome::Conf::VALUE_INT) {
00349 retval = value.get_int();
00350
00351
00352
00353
00354
00355
00356
00357
00358 }
00359 #endif
00360 return retval;
00361 }
00362
00363 #ifdef MAEMO
00365 bool KitListGui::on_window_state_event(GdkEventWindowState* event) {
00366 m_full_screen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN);
00367 }
00368
00369
00371 bool KitListGui::on_key_pressed(GdkEventKey* key) {
00372 if (key->keyval == GDK_F6) {
00373 if (!m_full_screen) {
00374 m_window->fullscreen();
00375 } else {
00376 m_window->unfullscreen();
00377 }
00378 return true;
00379 }
00380 return false ;
00381 };
00382
00383
00385 void KitListGui::show_banner(const Glib::ustring& msg) {
00386 Hildon::Banner::show_information(*m_window, msg);
00387 }
00388
00389 #endif
00390
00391
00393 bool KitListGui::confirm_lose_changes(const Glib::ustring& message) {
00394
00395 Gtk::MessageDialog dialog(*m_window,
00396 message,
00397 false,
00398 Gtk::MESSAGE_WARNING,
00399 Gtk::BUTTONS_NONE);
00400 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
00401 dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_APPLY);
00402 dialog.add_button(_("_Discard Changes"), Gtk::RESPONSE_CLOSE);
00403 int result = dialog.run();
00404 switch (result) {
00405 case (Gtk::RESPONSE_CANCEL) :
00406 return false;
00407 case (Gtk::RESPONSE_APPLY) :
00408 #ifdef XML_DAO
00409 if (m_filename.length() > 0) {
00410 m_service.save_as_xml(m_filename);
00411 m_service.set_model_dirty(false);
00412 return true;
00413 }
00414 return false;
00415 #else
00416 m_service.save();
00417 m_service.set_model_dirty(false);
00418 return true;
00419 #endif
00420 case (Gtk::RESPONSE_CLOSE) :
00421 return true;
00422 default :
00423 return false;
00424 }
00425 }
00426
00427
00431 void KitListGui::update_recent_files_menu() {
00432 #ifdef GCONF
00433
00434 std::deque<Glib::ustring> mru =
00435 m_ref_gconf_client->get_string_list(GCONF_KEY_RECENT_FILES);
00436
00437 if (m_recent_files_menu_item) {
00438 if (m_recent_files_menu_item->has_submenu()) {
00439 m_recent_files_menu_item->remove_submenu();
00440 }
00441 Gtk::Menu* recent_menu = Gtk::manage(new Gtk::Menu);
00442
00443 m_recent_files_menu_item->set_submenu(*recent_menu);
00444 for (std::deque<Glib::ustring>::iterator i = mru.begin();
00445 i != mru.end();
00446 ++i) {
00447 Gtk::MenuItem* m = Gtk::manage(new Gtk::MenuItem(*i));
00448 m->signal_activate().connect(
00449 sigc::bind<Glib::ustring>(
00450 sigc::mem_fun(*this, &KitListGui::on_menu_recent_file), *i)
00451 );
00452 recent_menu->add(*m);
00453 recent_menu->show_all_children();
00454 }
00455 } else {
00456 g_warning("Couldn't find recent files menu item");
00457 }
00458 #endif // GCONF
00459 }
00460
00461
00468 void KitListGui::update_recent_files(const Glib::ustring& filename) {
00469 #ifdef GCONF
00470
00471
00472 std::deque<Glib::ustring> mru =
00473 m_ref_gconf_client->get_string_list(GCONF_KEY_RECENT_FILES);
00474
00475 for (std::deque<Glib::ustring>::iterator i = mru.begin(); i != mru.end(); ++i) {
00476 if (*i == filename) {
00477 mru.erase(i);
00478 break;
00479 }
00480 }
00481
00482 mru.push_front(filename);
00483 while (mru.size() > get_max_recent_files()) {
00484 mru.pop_back();
00485 }
00486
00487
00488 m_ref_gconf_client->set_string_list(GCONF_KEY_RECENT_FILES, mru);
00489
00490
00491 update_recent_files_menu();
00492 #endif // GCONF
00493 }
00494
00495
00497 bool KitListGui::on_delete_event(GdkEventAny* event) {
00498 if (m_service.is_model_dirty() &&
00499 !confirm_lose_changes(_("Your changes will be lost if you quit now"))) {
00500 return true;
00501 }
00502
00503
00504
00505 m_service.set_model_dirty(false);
00506 return false;
00507 }
00508
00509
00511 void KitListGui::on_menu_quit() {
00512 if (m_service.is_model_dirty() &&
00513 !confirm_lose_changes(_("Your changes will be lost if you quit now"))) {
00514 return;
00515 }
00516
00517
00518
00519 m_service.set_model_dirty(false);
00520 m_window->hide();
00521 }
00522
00523
00528 void KitListGui::on_menu_file_new() {
00529 if (m_status_bar)
00530 m_status_bar->pop(SB_SAVE);
00531 if (m_service.is_model_dirty() &&
00532 !confirm_lose_changes(_("Your changes will be lost if you continue"))) {
00533 return;
00534 }
00535 #ifndef TRANSITION_DAO
00536 if (m_service.require_filename()) {
00537 #endif
00538 m_filename.clear();
00539 #ifdef GCONF
00540 if (m_ref_gconf_client) {
00541 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00542 m_ref_gconf_client->unset(GCONF_KEY_CURRENT_FILENAME);
00543 #else
00544 std::auto_ptr<Glib::Error> error;
00545 m_ref_gconf_client->unset(GCONF_KEY_CURRENT_FILENAME, error);
00546 if (error.get())
00547 g_warning(_("GConf error: %s"), error->what().c_str());
00548 #endif //GLIBMM_EXCEPTIONS_ENABLED
00549 }
00550 #endif // GCONF
00551 m_service.create_default_model();
00552
00553
00554 refresh_category_list(-1);
00555 refresh_item_list();
00556 #ifndef TRANSITION_DAO
00557 } else {
00558 #ifdef MAEMO
00559 show_banner(_("New databases must be created manually"));
00560 #else
00561 if (m_status_bar)
00562 m_status_bar->push(_("New databases must be created manually"), SB_SAVE);
00563 #endif
00564 }
00565 #endif
00566 }
00567
00568
00575 void KitListGui::on_menu_file_open() {
00576 if (m_status_bar)
00577 m_status_bar->pop(SB_SAVE);
00578 if (m_service.is_model_dirty() &&
00579 !confirm_lose_changes(_("Your changes will be lost if you continue"))) {
00580 return;
00581 }
00582 #ifdef MAEMO
00583 Hildon::FileChooserDialog dialog(*m_window, Gtk::FILE_CHOOSER_ACTION_OPEN);
00584 #else
00585
00586 Gtk::FileChooserDialog dialog(_("Open File"), Gtk::FILE_CHOOSER_ACTION_OPEN);
00587 dialog.set_transient_for(*m_window);
00588
00589 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
00590 dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
00591 #endif
00592 Gtk::FileFilter filter_xml;
00593 filter_xml.set_name(_("Kit files"));
00594 #ifdef WIN32
00595 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
00596 #elif MAEMO
00597
00598
00599
00600 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
00601
00602 #else
00603 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
00604
00605 #endif
00606 dialog.add_filter(filter_xml);
00607
00608 Gtk::FileFilter filter_any;
00609 filter_any.set_name(_("Any files"));
00610 filter_any.add_pattern("*");
00611 dialog.add_filter(filter_any);
00612
00613 int result = dialog.run();
00614 dialog.hide();
00615 Glib::ustring filename;
00616 switch(result) {
00617 case(Gtk::RESPONSE_OK):
00618 filename = dialog.get_filename();
00619 break;
00620 case(Gtk::RESPONSE_CANCEL):
00621 return;
00622 default:
00623 return;
00624 }
00625 open_file(filename);
00626 }
00627
00628
00633 void KitListGui::open_file(const Glib::ustring& filename) {
00634 m_service.open_as_xml(filename);
00635 m_filename = filename;
00636 update_recent_files(m_filename);
00637
00638 #ifdef GCONF
00639 if (m_ref_gconf_client) {
00640 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00641 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename);
00642 #else
00643 std::auto_ptr<Glib::Error> error;
00644 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename, error);
00645 if (error.get())
00646 g_warning(_("GConf error: %s"), error->what().c_str());
00647 #endif //GLIBMM_EXCEPTIONS_ENABLED
00648 }
00649 #endif
00650
00651
00652
00653 refresh_category_list(-1);
00654 refresh_item_list();
00655 }
00656
00657
00664 void KitListGui::safe_open_file(const Glib::ustring& filename) {
00665 if (m_status_bar)
00666 m_status_bar->pop(SB_SAVE);
00667 if (m_service.is_model_dirty() &&
00668 !confirm_lose_changes(_("Your changes will be lost if you continue"))) {
00669 return;
00670 }
00671 open_file(filename);
00672 }
00673
00674
00678 void KitListGui::on_menu_save() {
00679 if (m_status_bar)
00680 m_status_bar->pop(SB_SAVE);
00681 if (m_service.is_model_dirty()) {
00682
00683
00684
00685
00686 if (m_service.require_filename() && m_filename.size() == 0) {
00687 on_menu_save_as();
00688 } else {
00689 Glib::ustring msg = _("Saving changes...");
00690 if (m_status_bar)
00691 m_status_bar->push(msg, SB_SAVE);
00692 #ifndef XML_DAO
00693 m_service.save();
00694 #else
00695 m_service.save_as_xml(m_filename);
00696 update_recent_files(m_filename);
00697 #ifdef GCONF
00698 if (m_ref_gconf_client) {
00699 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00700 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME,
00701 m_filename);
00702 #else
00703 std::auto_ptr<Glib::Error> error;
00704 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename, error);
00705 if (error.get())
00706 g_warning(_("GConf error: %s"), error->what().c_str());
00707 #endif //GLIBMM_EXCEPTIONS_ENABLED
00708 }
00709 #endif // GCONF
00710 #endif // !XML_DAO
00711 if (m_status_bar)
00712 m_status_bar->pop(SB_SAVE);
00713 msg = _("Saved");
00714 if (m_status_bar)
00715 m_status_bar->push(msg, SB_SAVE);
00716 }
00717 } else {
00718 #ifdef MAEMO
00719 show_banner(_("Nothing to save"));
00720 #else
00721 if (m_status_bar)
00722 m_status_bar->push(Glib::ustring(_("Nothing to save")), SB_SAVE);
00723 #endif
00724 }
00725 }
00726
00727
00731 void KitListGui::on_menu_save_as() {
00732 if (m_status_bar) {
00733 m_status_bar->pop(SB_SAVE);
00734 m_status_bar->push(_("Choosing target filename"), SB_SAVE);
00735 }
00736 if (choose_filename(m_filename)) {
00737 if (m_status_bar) {
00738 m_status_bar->pop(SB_SAVE);
00739 m_status_bar->push(_("Saving..."), SB_SAVE);
00740 }
00741
00742 m_service.save_as_xml(m_filename);
00743 update_recent_files(m_filename);
00744
00745 if (m_status_bar) {
00746 m_status_bar->pop(SB_SAVE);
00747 m_status_bar->push(_("Saved"), SB_SAVE);
00748 }
00749 #ifdef GCONF
00750 if (m_ref_gconf_client) {
00751 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00752 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename);
00753 #else
00754 std::auto_ptr<Glib::Error> error;
00755 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename, error);
00756 if (error.get())
00757 g_warning(_("GConf error: %s"), error->what().c_str());
00758 #endif //GLIBMM_EXCEPTIONS_ENABLED
00759 }
00760 #endif // GCONF
00761 #ifdef MAEMO
00762 show_banner(_("Saved"));
00763 #endif
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 } else {
00775 if (m_status_bar) {
00776 m_status_bar->pop(SB_SAVE);
00777 m_status_bar->push(_("Save cancelled"), SB_SAVE);
00778 }
00779 #ifdef MAEMO
00780 show_banner(_("Save cancelled"));
00781 #endif
00782 }
00783 }
00784
00785
00789 void KitListGui::on_menu_recent_file(const Glib::ustring& filename) {
00790
00791 if (m_service.is_model_dirty() &&
00792 !confirm_lose_changes(_("Your changes will be lost if you continue"))) {
00793 return;
00794 }
00795 m_service.open_as_xml(filename);
00796 m_filename = filename;
00797 update_recent_files(m_filename);
00798
00799 #ifdef GCONF
00800 if (m_ref_gconf_client) {
00801 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00802 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename);
00803 #else
00804 std::auto_ptr<Glib::Error> error;
00805 m_ref_gconf_client->set(GCONF_KEY_CURRENT_FILENAME, m_filename, error);
00806 if (error.get())
00807 g_warning(_("GConf error: %s"), error->what().c_str());
00808 #endif //GLIBMM_EXCEPTIONS_ENABLED
00809 }
00810 #endif // GCONF
00811
00812
00813
00814 refresh_category_list(-1);
00815 refresh_item_list();
00816 }
00817
00818
00822 ModelItemContainer* KitListGui::get_selected_items() {
00823 ModelItemContainer* retval = new ModelItemContainer;
00824 Glib::RefPtr<Gtk::TreeSelection> ref_tree_selection =
00825 m_item_tree_view->get_selection();
00826 if (ref_tree_selection) {
00827 if (ref_tree_selection->get_mode() == Gtk::SELECTION_MULTIPLE) {
00828 Gtk::TreeSelection::ListHandle_Path rows = ref_tree_selection->get_selected_rows();
00829 for (Glib::Container_Helpers::ListHandleIterator<Gtk::TreePath_Traits> path = rows.begin(); path != rows.end(); ++path) {
00830 Gtk::TreeModel::iterator iter = m_ref_item_tree_model->get_iter(*path);
00831 Gtk::TreeModel::Row row = *iter;
00832 int id = row[m_item_cols.m_col_num];
00833 ModelItem* item = m_service.find_item(id);
00834 if (item) {
00835 retval->push_back(item);
00836 } else {
00837 g_warning(_("Failed to find item to delete in model"));
00838 }
00839 }
00840 } else {
00841 Gtk::TreeModel::iterator iter = ref_tree_selection->get_selected();
00842 if (iter) {
00843 Gtk::TreeModel::Row row = *iter;
00844 int id = row[m_item_cols.m_col_num];
00845 ModelItem* item = m_service.find_item(id);
00846 if (item) {
00847 retval->push_back(item);
00848 } else {
00849 g_warning(_("Failed to find item to delete in model"));
00850 }
00851 } else {
00852 g_warning(_("Couldn't find the selected item or items"));
00853 }
00854 }
00855 } else {
00856 g_warning(_("Couldn't identify selection"));
00857 }
00858 return retval;
00859 }
00860
00861
00868 void KitListGui::delete_selected_items() {
00869 Glib::RefPtr<Gtk::TreeSelection> ref_tree_selection =
00870 m_item_tree_view->get_selection();
00871 if (ref_tree_selection) {
00872 if (ref_tree_selection->get_mode() == Gtk::SELECTION_MULTIPLE) {
00873 ref_tree_selection->selected_foreach_iter( sigc::mem_fun(*this, &KitListGui::selected_row_callback));
00874 refresh_item_list();
00875 } else {
00876 Gtk::TreeModel::iterator iter = ref_tree_selection->get_selected();
00877 if (iter) {
00878 Gtk::TreeModel::Row row = *iter;
00879 int id = row[m_item_cols.m_col_num];
00880 m_ref_item_tree_model->erase(iter);
00881 if (!m_service.delete_item(id))
00882 g_warning(_("Failed to find the item to delete in the model"));
00883 } else {
00884 g_warning(_("Couldn't find the selected item or items"));
00885 }
00886 }
00887 } else {
00888 g_warning(_("Couldn't identify selection"));
00889 }
00890 }
00891
00892
00900 void KitListGui::on_menu_delete() {
00901 Gtk::MessageDialog dialog(*m_window,
00902 _("Delete the selected items?"),
00903 false,
00904 Gtk::MESSAGE_QUESTION,
00905 Gtk::BUTTONS_YES_NO);
00906 int result = dialog.run();
00907 switch (result) {
00908 case (Gtk::RESPONSE_YES) :
00909 delete_selected_items();
00910 break;
00911 case (Gtk::RESPONSE_NO) :
00912 break;
00913 default:
00914 g_warning(_("Unexpected button"));
00915 break;
00916 }
00917 }
00918
00919
00923 ModelItemContainer* KitListGui::copy_selected_items_to_clipboard() {
00924 xmlpp::Document document;
00925 xmlpp::Element* nodeRoot = document.create_root_node("kitlist");
00926 assert(nodeRoot);
00927 nodeRoot->add_child_text("\n");
00928 ModelItemContainer* items = get_selected_items();
00929 for (ModelItemIter i = items->begin(); i != items->end(); ++i) {
00930 xmlpp::Element* nodeChild = nodeRoot->add_child("item");
00931 ostringstream os;
00932 os << (*i)->get_id();
00933 nodeChild->set_attribute(XML_ELEMENT_ID, os.str());
00934
00935 nodeChild->set_child_text((*i)->get_description());
00936 nodeRoot->add_child_text("\n");
00937 }
00938 m_clipboard_items = document.write_to_string();
00939
00940 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
00941 std::list<Gtk::TargetEntry> listTargets;
00942 listTargets.push_back( Gtk::TargetEntry(item_target_custom) );
00943 listTargets.push_back( Gtk::TargetEntry(item_target_text) );
00944 refClipboard->set( listTargets,
00945 sigc::mem_fun(*this, &KitListGui::on_clipboard_get),
00946 sigc::mem_fun(*this, &KitListGui::on_clipboard_clear) );
00947 update_paste_status();
00948 return items;
00949 }
00950
00951
00956 void KitListGui::on_menu_cut() {
00957 long cat_id = get_selected_category();
00958 if (cat_id != -1) {
00959 ModelItemContainer* items = copy_selected_items_to_clipboard();
00960 if (items) {
00961 ModelCategory* category = m_service.find_category(cat_id);
00962 if (category) {
00963 m_service.set_model_dirty();
00964 category->remove_items(items);
00965 category->set_dirty(true);
00966 }
00967 refresh_item_list();
00968 }
00969 delete items;
00970 } else {
00971 if (m_status_bar) {
00972 m_status_bar->pop(SB_MSG);
00973 m_status_bar->push(_("Items can only be cut when a category is selected"), SB_MSG);
00974 }
00975 #ifdef MAEMO
00976 show_banner(_("Select a category before copying items"));
00977 #endif
00978 }
00979 }
00980
00981
00985 void KitListGui::on_menu_copy() {
00986 ModelItemContainer* items = copy_selected_items_to_clipboard();
00987 delete items;
00988 }
00989
00990
00994 void KitListGui::on_menu_paste() {
00995
00996 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
00997 refClipboard->request_contents(item_target_text, sigc::mem_fun(
00998 *this,
00999 &KitListGui::on_clipboard_received) );
01000 paste_from_xml(m_clipboard_items);
01001 update_paste_status();
01002 }
01003
01004
01008 void KitListGui::on_menu_select_all() {
01009
01010 Glib::RefPtr<Gtk::TreeSelection> selection =
01011 m_item_tree_view->get_selection();
01012 if (selection)
01013 selection->select_all();
01014 m_item_tree_view->grab_focus();
01015 }
01016
01017
01019 void KitListGui::on_menu_create_category() {
01020 m_state = ADD_CATEGORY;
01021 m_current_cat_id = -1;
01022 #ifdef MAEMO
01023 Gtk::Dialog::Dialog dialog(_("Add Category"), *m_window, true, true);
01024
01025 Gtk::VBox* vbox = dialog.get_vbox();
01026
01027 Glib::RefPtr<Gtk::SizeGroup> group = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_VERTICAL);
01028 Gtk::Entry name;
01029
01030 Hildon::Caption* caption = Gtk::manage(new Hildon::Caption(
01031 _("Name"),
01032 name));
01033 vbox->pack_start(*caption);
01034
01035 dialog.set_size_request(500);
01036
01037 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
01038 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
01039 dialog.show_all_children();
01040 int result = dialog.run();
01041 dialog.hide();
01042 switch (result) {
01043 case (Gtk::RESPONSE_CANCEL) :
01044 break;
01045 case (Gtk::RESPONSE_OK) :
01046
01047 Category* category = m_service.create_category();
01048
01049
01050
01051 if (category != NULL) {
01052 category->set_name(name.get_text());
01053 m_service.set_model_dirty();
01054 ((ModelCategory*) category)->set_dirty(true);
01055 refresh_category_list(category->get_id());
01056 refresh_item_list();
01057 }
01058 break;
01059 default :
01060 break;
01061 }
01062
01063
01064 #else
01065 if (m_window_add_category) {
01066 m_window_add_category->set_title(_("Add Category"));
01067 if (m_entry_add_category) {
01068 m_entry_add_category->set_text("");
01069 }
01070 m_entry_add_category->grab_focus();
01071 m_window_add_category->show();
01072 } else {
01073 g_warning(_("\"window_add_category\" resource is missing"));
01074 }
01075 #endif
01076 }
01077
01078
01089 void KitListGui::close_add_category_window() {
01090 m_window_add_category->hide();
01091 if (m_entry_add_category) {
01092 Category* category = NULL;
01093 if (m_state == ADD_CATEGORY) {
01094 category = m_service.create_category();
01095 } else {
01096 category = m_service.find_category(m_current_cat_id);
01097 }
01098 if (category != NULL) {
01099 category->set_name(m_entry_add_category->get_text());
01100 m_service.set_model_dirty();
01101 ((ModelCategory*) category)->set_dirty(true);
01102 refresh_category_list(category->get_id());
01103 refresh_item_list();
01104 }
01105 }
01106 }
01107
01108
01109
01114 void KitListGui::cancel_add_category_window() {
01115 m_window_add_category->hide();
01116 }
01117
01118
01125 void KitListGui::on_menu_delete_category() {
01126 long cat_id = get_selected_category();
01127 if (cat_id == -1) {
01128 if (m_status_bar) {
01129 m_status_bar->pop(SB_MSG);
01130 m_status_bar->push(_("No category selected"), SB_MSG);
01131 }
01132 #ifdef MAEMO
01133 show_banner(_("No category selected"));
01134 #endif
01135
01136 } else {
01137 Gtk::MessageDialog dialog(*m_window,
01138 _("Delete the current category?"),
01139 false,
01140 Gtk::MESSAGE_QUESTION,
01141 Gtk::BUTTONS_YES_NO);
01142 int result = dialog.run();
01143 switch (result) {
01144 case (Gtk::RESPONSE_YES) :
01145 m_service.delete_category(cat_id);
01146 refresh_category_list();
01147 refresh_item_list();
01148 break;
01149 case (Gtk::RESPONSE_NO) :
01150 break;
01151 default:
01152 g_warning(_("Unexpected button"));
01153 break;
01154 }
01155 }
01156 }
01157
01158
01162 void KitListGui::on_menu_rename_category() {
01163 m_state = RENAME_CATEGORY;
01164 m_current_cat_id = get_selected_category();
01165 #ifdef MAEMO
01166 if (m_current_cat_id != -1) {
01167
01168 ModelCategory* category = m_service.find_category(m_current_cat_id);
01169 if (category) {
01170
01171 Gtk::Dialog::Dialog dialog(_("Rename Category"), *m_window, true, true);
01172
01173 Gtk::VBox* vbox = dialog.get_vbox();
01174
01175 Glib::RefPtr<Gtk::SizeGroup> group = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_VERTICAL);
01176 Gtk::Entry name;
01177 name.set_text(category->get_name());
01178
01179 Hildon::Caption* caption = Gtk::manage(new Hildon::Caption(
01180 _("Name"),
01181 name));
01182 vbox->pack_start(*caption);
01183
01184 dialog.set_size_request(500);
01185
01186 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
01187 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
01188 dialog.show_all_children();
01189 int result = dialog.run();
01190 dialog.hide();
01191 switch (result) {
01192 case (Gtk::RESPONSE_CANCEL) :
01193 break;
01194 case (Gtk::RESPONSE_OK) :
01195
01196
01197
01198
01199
01200
01201 category->set_name(name.get_text());
01202 m_service.set_model_dirty();
01203 ((ModelCategory*) category)->set_dirty(true);
01204 refresh_category_list(category->get_id());
01205 refresh_item_list();
01206
01207 break;
01208 default :
01209 break;
01210 }
01211 }
01212
01213 } else {
01214 show_banner(_("No category selected"));
01215 }
01216 #else
01217 if (m_window_add_category) {
01218 m_window_add_category->set_title(_("Rename Category"));
01219 if (m_current_cat_id != -1) {
01220 ModelCategory* category = m_service.find_category(m_current_cat_id);
01221 if (category != NULL && m_entry_add_category) {
01222 m_entry_add_category->set_text(category->get_name());
01223 }
01224 m_entry_add_category->grab_focus();
01225 m_window_add_category->show();
01226 } else {
01227 if (m_status_bar) {
01228 m_status_bar->pop(SB_MSG);
01229 m_status_bar->push(_("No category selected"), SB_MSG);
01230 }
01231 }
01232 } else {
01233 g_warning(_("\"window_add_category\" resource is missing"));
01234 }
01235 #endif
01236 }
01237
01238
01242 void KitListGui::on_menu_help_contents() {
01243
01244
01245
01246
01247 #ifdef MAEMO
01248 hildon_help_show(m_osso_context, "contents_kitlist_help", 0 );
01249 #endif
01250 }
01251
01252
01256 void KitListGui::on_menu_help_about() {
01257 Gtk::AboutDialog dialog;
01258 dialog.set_name(PACKAGE_NAME);
01259 dialog.set_copyright("(c) 2008-2009 Frank Dean");
01260 dialog.set_version(PACKAGE_VERSION);
01261 std::vector<Glib::ustring> authors;
01262 authors.push_back("frank.dean@smartpixie.com");
01263 dialog.set_authors(authors);
01264 dialog.run();
01265 }
01266
01267
01271 void KitListGui::set_selected(bool checked) {
01272 ModelItemContainer* items = get_selected_items();
01273 m_service.select_items(items, checked);
01274 refresh_item_list();
01275 delete items;
01276 }
01277
01278
01282 void KitListGui::toggle_selected() {
01283 ModelItemContainer* items = get_selected_items();
01284 m_service.toggle_selected_items(items);
01285 refresh_item_list();
01286 delete items;
01287 }
01288
01289
01293 void KitListGui::on_clipboard_get(Gtk::SelectionData& selection_data, guint) {
01294 const std::string target = selection_data.get_target();
01295
01296 if (target == item_target_custom) {
01297 selection_data.set_text(m_clipboard_items);
01298 } else if (target == item_target_text) {
01299 selection_data.set_text(m_clipboard_items);
01300 } else {
01301 g_warning("KitList::on_clipboard_get(): Unexpected clipboard target format");
01302 }
01303 }
01304
01305
01324 void KitListGui::on_clipboard_clear() {
01325 }
01326
01327
01335 void KitListGui::add_items(const ModelItemContainer& items) {
01336 long cat_id = get_selected_category();
01337 if (cat_id != -1) {
01338 m_service.copy_items(items, cat_id);
01339 refresh_item_list();
01340 }
01341 }
01342
01343
01347 void KitListGui::paste_from_xml(const Glib::ustring& document) {
01348 try {
01349 if (document.length() > 0) {
01350 xmlpp::DomParser parser;
01351 parser.set_substitute_entities();
01352 parser.parse_memory(document);
01353 const xmlpp::Node* nodeRoot = parser.get_document()->get_root_node();
01354 ModelItemContainer items;
01355 xmlpp::Node::NodeList nodes = nodeRoot->get_children();
01356 for (xmlpp::Node::NodeList::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
01357 const xmlpp::Node* node = (*iter);
01358
01359 const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::Element*>(node);
01360 if (nodeElement && node->get_name() == "item") {
01361 xmlpp::Attribute* attribute = nodeElement->get_attribute(XML_ELEMENT_ID);
01362 if (attribute) {
01363 Glib::ustring s = attribute->get_value();
01364 long id = atol(s.c_str());
01365 ModelItem* item = m_service.find_item(id);
01366 if (item) {
01367 items.push_back(item);
01368 }
01369 }
01370 }
01371 }
01372 add_items(items);
01373 }
01374 } catch (std::exception ex) {
01375 g_warning("Error pasting clipboard - perhaps it was empty");
01376 }
01377 }
01378
01379
01383 void KitListGui::on_clipboard_received(const Gtk::SelectionData& selection_data) {
01384 const std::string target = selection_data.get_target();
01385 Glib::ustring s;
01386 if (target == item_target_custom || target == item_target_text) {
01387 m_clipboard_items = selection_data.get_data_as_string();
01388 } else {
01389 g_warning("KitList::on_clipboard_get(): Unexpected clipboard target format");
01390 }
01391 }
01392
01393
01397 void KitListGui::update_item_count(size_t n) {
01398
01399 ostringstream os;
01400 os.imbue(std::locale(""));
01401 os << n << " " << (n == 1 ? _("item") : _("items"));
01402 if (m_status_bar) {
01403 m_status_bar->pop(SB_ITEM_COUNT);
01404 #ifdef GLIBMM_EXCEPTIONS_ENABLED
01405 m_status_bar->push(Glib::locale_to_utf8(os.str()), SB_ITEM_COUNT);
01406 #else
01407 std::auto_ptr<Glib::Error> ex;
01408 m_status_bar->push(Glib::locale_to_utf8(os.str(), ex), SB_ITEM_COUNT);
01409
01410 if (ex.get())
01411 g_warning(_("Error updating the status bar: %s"), ex->what().c_str());
01412 #endif // GLIBMM_EXCEPTIONS_ENABLED
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 }
01426
01427
01433 void KitListGui::on_cell_edit(const Glib::ustring s) {
01434 if (m_ignore_list_events)
01435 return;
01436 m_service.set_model_dirty(true);
01437 }
01438
01439
01450 bool KitListGui::choose_filename(Glib::ustring& filename) {
01451 bool retval = false;
01452 bool loop = true;
01453 while (loop) {
01454 #ifdef MAEMO
01455 Hildon::FileChooserDialog dialog(*m_window, Gtk::FILE_CHOOSER_ACTION_SAVE);
01456 #else
01457 Gtk::FileChooserDialog dialog(_("Save File"), Gtk::FILE_CHOOSER_ACTION_SAVE);
01458 dialog.set_transient_for(*m_window);
01459
01460 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
01461 dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
01462 #endif
01463
01464 Gtk::FileFilter filter_xml;
01465 filter_xml.set_name(_("XML files"));
01466
01467 #ifdef WIN32
01468 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
01469 #elif MAEMO
01470 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
01471 #else
01472 filter_xml.add_pattern("*" + DEFAULT_FILENAME_EXTENSION);
01473
01474 #endif
01475
01476 dialog.add_filter(filter_xml);
01477
01478 Gtk::FileFilter filter_any;
01479 filter_any.set_name(_("Any files"));
01480 filter_any.add_pattern("*");
01481 dialog.add_filter(filter_any);
01482
01483 int result = dialog.run();
01484 dialog.hide();
01485
01486 switch(result) {
01487 case(Gtk::RESPONSE_OK):
01488
01489 filename = dialog.get_filename();
01490
01491 retval = true;
01492 break;
01493 case(Gtk::RESPONSE_CANCEL):
01494 break;
01495 default:
01496 break;
01497 }
01498 if (retval) {
01499
01500 Glib::ustring::size_type i = filename.find(".");
01501 if (i < 0 || i > filename.length()) {
01502 filename += DEFAULT_FILENAME_EXTENSION;
01503
01504 }
01505
01506 if (file_exists(filename)) {
01507 Gtk::MessageDialog dialog(*m_window,
01508 _("Overwrite existing file?"),
01509 false,
01510 Gtk::MESSAGE_WARNING,
01511 Gtk::BUTTONS_NONE);
01512 dialog.add_button(Gtk::Stock::NO, Gtk::RESPONSE_NO);
01513 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
01514 dialog.add_button(Gtk::Stock::YES, Gtk::RESPONSE_YES);
01515 dialog.set_default_response(Gtk::RESPONSE_NO);
01516 int result = dialog.run();
01517 switch (result) {
01518 case (Gtk::RESPONSE_CANCEL) :
01519 retval = false;
01520 loop = false;
01521 break;
01522 case (Gtk::RESPONSE_NO) :
01523 retval = false;
01524 loop = true;
01525 break;
01526 case (Gtk::RESPONSE_YES) :
01527 loop = false;
01528 break;
01529 default :
01530 retval = false;
01531 loop = false;
01532 break;
01533 }
01534
01535 } else {
01536 loop = false;
01537 }
01538 } else {
01539 loop = false;
01540 }
01541 }
01542 return retval;
01543 }
01544
01545
01549 void KitListGui::update_paste_status() {
01550 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
01551 refClipboard->request_targets( sigc::mem_fun(*this, &KitListGui::paste_status_received) );
01552 }
01553
01554
01561 void KitListGui::paste_status_received(const Glib::StringArrayHandle& targets_array) {
01562 std::list<std::string> targets = targets_array;
01563 bool can_paste = false;
01564 for (std::list<std::string>::iterator i = targets.begin(); i != targets.end(); ++i) {
01565 if ( *i == item_target_custom || *i == item_target_text) {
01566 can_paste = true;
01567 break;
01568 }
01569 }
01570
01571 if (m_paste_menu_item)
01572 m_paste_menu_item->set_sensitive(can_paste);
01573
01574 #ifdef MAEMO
01575 if (m_paste_tool_button)
01576 m_paste_tool_button->set_sensitive(can_paste);
01577 #endif
01578 }
01579
01580
01581
01590 void KitListGui::on_row_changed(const Gtk::TreeModel::Path path, const Gtk::TreeModel::iterator iter) {
01591 if (m_ignore_list_events)
01592 return;
01593 m_service.set_model_dirty(true);
01594 Gtk::TreeModel::Row row = *iter;
01595 int id = row[m_item_cols.m_col_num];
01596 Glib::ustring us = row[m_item_cols.m_col_text];
01597 string s(us);
01598 if (!m_service.update_item(id, s, row[m_item_cols.m_col_checked]))
01599 g_warning(_("Unable to find the item in the model: %d"), id);
01600 }
01601
01602
01606 void KitListGui::selected_row_callback(const Gtk::TreeModel::iterator& iter) {
01607 Gtk::TreeModel::Row row = *iter;
01608 int id = row[m_item_cols.m_col_num];
01609 if (!m_service.delete_item(id))
01610 g_warning(_("Failed to find item to delete in model"));
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01636 void KitListGui::refresh_item_list() {
01637 m_ignore_list_events = true;
01638 int cat_id = get_selected_category();
01639
01640 m_ref_item_tree_model->clear();
01641 ItemContainer *items = m_service.get_items(cat_id);
01642 if (items)
01643 sort(items->begin(), items->end(), ItemCompareName());
01644
01645
01646 size_t count = 0;
01647 if (items && !items->empty()) {
01648 for (ItemIter i = items->begin(); i != items->end(); ++i) {
01649 if (m_service.filter((*i)->get_checked())) {
01650
01651 count++;
01652 Gtk::TreeModel::iterator item_iter = m_ref_item_tree_model->append();
01653 Gtk::TreeModel::Row row = *item_iter;
01654 row[m_item_cols.m_col_text] = (*i)->get_description();
01655 row[m_item_cols.m_col_num] = (*i)->get_id();
01656 row[m_item_cols.m_col_checked] = (*i)->get_checked();
01657 }
01658 }
01659 }
01660 if (items)
01661 delete items;
01662 update_item_count(count);
01663 m_ignore_list_events = false;
01664 }
01665
01666
01675 void KitListGui::refresh_category_list(long cat_id) {
01676 m_ignore_list_events = true;
01677
01678 if (cat_id == -2)
01679 cat_id = get_selected_category();
01680 CategoryContainer* c = m_service.get_categories();
01681 sort(c->begin(), c->end(), CategoryCompareName());
01682 m_ref_category_list_store->clear();
01683 Gtk::TreeModel::iterator iter = m_ref_category_list_store->append();
01684 Gtk::TreeModel::iterator active;
01685 Gtk::TreeModel::Row row = *iter;
01686 ostringstream os;
01687
01688 os.imbue(std::locale(""));
01689 #ifdef MAEMO
01690 os << "[" << _("All") << "]";
01691 #else
01692 os << "-- " << _("Show all items") << " --";
01693 #endif
01694 #ifdef GLIBMM_EXCEPTIONS_ENABLED
01695 row[m_category_cols.m_col_text] = Glib::locale_to_utf8(os.str());
01696 #else
01697 std::auto_ptr<Glib::Error> ex;
01698 row[m_category_cols.m_col_text] = Glib::locale_to_utf8(os.str(), ex);
01699 if (ex.get()) {
01700 g_warning("Failed to add item to category combo model: %s", ex->what().c_str());
01701 }
01702 #endif
01703 row[m_category_cols.m_col_num] = -1;
01704 if (!c->empty()) {
01705 for (CategoryIter i = c->begin(); i != c->end(); ++i) {
01706 ModelCategory* category = (ModelCategory*) *i;
01707 if ( !category->is_deleted() ) {
01708
01709 iter = m_ref_category_list_store->append();
01710 row = *iter;
01711 row[m_category_cols.m_col_text] = category->get_name();
01712 row[m_category_cols.m_col_num] = category->get_id();
01713 if (category->get_id() == cat_id)
01714 active = iter;
01715 }
01716 }
01717 }
01718 delete c;
01719 if (!active || cat_id == -1)
01720 m_category_combo->set_active(0);
01721 else
01722 m_category_combo->set_active(active);
01723 m_ignore_list_events = false;
01724 }
01725
01726
01730 void KitListGui::on_menu_add() {
01731 #ifdef MAEMO
01732 Gtk::Dialog::Dialog dialog(_("Add Item"), *m_window, true, true);
01733
01734 Gtk::VBox* vbox = dialog.get_vbox();
01735
01736 Glib::RefPtr<Gtk::SizeGroup> group = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_VERTICAL);
01737 Gtk::Entry description;
01738
01739 Hildon::Caption* caption = Gtk::manage(new Hildon::Caption(
01740 _("Description"),
01741 description));
01742 vbox->pack_start(*caption);
01743 Gtk::CheckButton checkbutton(_("Chec_ked"), true);
01744 checkbutton.set_active(false);
01745 vbox->pack_start(checkbutton);
01746
01747 dialog.set_size_request(500);
01748
01749 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
01750 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
01751 dialog.show_all_children();
01752 int result = dialog.run();
01753 dialog.hide();
01754 switch (result) {
01755 case (Gtk::RESPONSE_CANCEL) :
01756 break;
01757 case (Gtk::RESPONSE_OK) :
01758
01759 long cat_id = get_selected_category();
01760 Item* item = m_service.create_item(cat_id);
01761 item->set_description(description.get_text());
01762 item->set_checked(checkbutton.get_active());
01763 refresh_item_list();
01764 break;
01765 default :
01766 break;
01767 }
01768
01769 #else
01770 if (m_window_add_item) {
01771 init_add_item_window();
01772 m_entry_add_item->grab_focus();
01773 m_window_add_item->show();
01774 } else {
01775 g_warning(_("\"window_add_item\" resource is missing"));
01776 }
01777 #endif
01778 }
01779
01780
01784 void KitListGui::init_add_item_window() {
01785 if (m_entry_add_item) {
01786 m_entry_add_item->set_text("");
01787 }
01788 }
01789
01790
01797 long KitListGui::get_selected_category() {
01798 long retval = -1;
01799 Gtk::TreeModel::iterator iter = m_category_combo->get_active();
01800 if (iter) {
01801 Gtk::TreeModel::Row row = *iter;
01802 if (row) {
01803 retval = row[m_category_cols.m_col_num];
01804 }
01805 }
01806 return retval;
01807 }
01808
01809
01814 void KitListGui::close_add_item_window() {
01815 m_window_add_item->hide();
01816
01817
01818 long cat_id = get_selected_category();
01819
01820 Item* item = m_service.create_item(cat_id);
01821 if (m_entry_add_item)
01822 item->set_description(m_entry_add_item->get_text());
01823 if (m_checkbutton_add_item)
01824 item->set_checked(m_checkbutton_add_item->get_active());
01825
01826 refresh_item_list();
01827 }
01828
01829
01834 void KitListGui::cancel_add_item_window() {
01835 m_window_add_item->hide();
01836 }
01837
01838
01842 void KitListGui::on_category_change() {
01843 if (m_ignore_list_events)
01844 return;
01845 refresh_item_list();
01846 }
01847
01848
01850 void KitListGui::raise() {
01851 m_window->present();
01852 }
01853
01854
01859 void KitListGui::init() {
01860
01861
01862 #ifdef XML_DAO
01863 Glib::ustring filename;
01864 #endif //XML_DAO
01865
01866 #ifdef GCONF
01867 #ifdef GLIBMM_EXCEPTIONS_ENABLED
01868 try {
01869 #endif //GLIBMM_EXCEPTIONS_ENABLED
01870 Gnome::Conf::init();
01871 m_ref_gconf_client = Gnome::Conf::Client::get_default_client();
01872
01873 #ifdef XML_DAO
01874 Gnome::Conf::Value value = Gnome::Conf::VALUE_INVALID;
01875 #ifdef GLIBMM_EXCEPTIONS_ENABLED
01876 m_ref_gconf_client->add_dir(GCONF_KEY);
01877 value = m_ref_gconf_client->get(GCONF_KEY_CURRENT_FILENAME);
01878 #else
01879 std::auto_ptr<Glib::Error> error;
01880 m_ref_gconf_client->add_dir(GCONF_KEY,
01881 Gnome::Conf::CLIENT_PRELOAD_NONE,
01882 error);
01883 if (error.get())
01884 g_warning(_("GConf error: %s"), error->what().c_str());
01885 value = m_ref_gconf_client->get(GCONF_KEY_CURRENT_FILENAME, error);
01886 if (error.get())
01887 g_warning(_("GConf error getting current filename: %s"),
01888 error->what().c_str());
01889 #endif //GLIBMM_EXCEPTIONS_ENABLED
01890 if (value.get_type() == Gnome::Conf::VALUE_STRING) {
01891 filename = value.to_string();
01892 }
01893 #endif //XML_DAO
01894
01895 #ifdef GLIBMM_EXCEPTIONS_ENABLED
01896 } catch (const Glib::Error& ex) {
01897 g_warning(_("GConf error: %s"), ex.what().c_str());
01898 }
01899 #endif //GLIBMM_EXCEPTIONS_ENABLED
01900 #endif // GCONF
01901
01902 #ifdef KITLIST_DEBUG
01903
01904 m_slog = new ofstream("/tmp/kitlist.log", ios_base::trunc);
01905 g_log_set_handler(NULL, (GLogLevelFlags) (G_LOG_LEVEL_MASK |
01906 G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION),
01907 my_log_handler, m_slog);
01908 #endif
01909 #ifdef MAEMO
01910 Hildon::init();
01911 Hildon::fm_init();
01912 m_osso_context = osso_initialize(KITLIST_SERVICE_NAME, PACKAGE_VERSION, TRUE , NULL );
01913 if(!m_osso_context) {
01914 g_error("osso_initialize() failed.");
01915 }
01916
01917
01918
01919
01920
01921 osso_return_t result = osso_rpc_set_cb_f(m_osso_context,
01922 KITLIST_SERVICE_NAME,
01923 KITLIST_SERVICE_OBJECT,
01924 KITLIST_SERVICE_IFACE,
01925 dbus_req_handler,
01926 this);
01927 Glib::set_application_name(_("Kit List"));
01928 Gtk::Widget* container;
01929 Glib::RefPtr<Gnome::Glade::Xml> refXml = get_glade_ref_ptr(GLADE_APP_FILE);
01930 refXml->get_widget("main", container);
01931 m_window = new Hildon::Window;
01932 Hildon::Program::get_instance()->add_window(*m_window);
01933 m_window->add(*container);
01934
01935 m_window->signal_key_press_event().connect( sigc::mem_fun(*this, &KitListGui::on_key_pressed) );
01936 m_window->signal_window_state_event().connect( sigc::mem_fun(*this, &KitListGui::on_window_state_event) );
01937
01938 m_refActionGroup = Gtk::ActionGroup::create();
01939
01940
01941 m_refActionGroup->add(
01942 Gtk::Action::create("FileNewStandard", Gtk::Stock::NEW, _("New")),
01943 sigc::mem_fun(*this, &KitListGui::on_menu_file_new)
01944 );
01945
01946
01947 m_refActionGroup->add(
01948 Gtk::Action::create("FileOpenStandard", Gtk::Stock::OPEN, _("Open")),
01949 sigc::mem_fun(*this, &KitListGui::on_menu_file_open)
01950 );
01951
01952 m_refActionGroup->add(
01953 Gtk::Action::create("FileSaveStandard", Gtk::Stock::SAVE, _("Save")),
01954 sigc::mem_fun(*this, &KitListGui::on_menu_save)
01955 );
01956
01957 m_refActionGroup->add(
01958 Gtk::Action::create("FileSaveAsStandard", Gtk::Stock::SAVE_AS, _("Save As")),
01959 sigc::mem_fun(*this, &KitListGui::on_menu_save_as)
01960 );
01961
01962 m_refActionGroup->add(Gtk::Action::create("FileRecent", _("Recent")));
01963
01964
01965 m_refActionGroup->add(
01966 Gtk::Action::create("EditSelectAll", Gtk::Stock::JUSTIFY_FILL, _("Select All")),
01967 sigc::mem_fun(*this, &KitListGui::on_menu_select_all)
01968 );
01969
01970
01971 m_refActionGroup->add(
01972 Gtk::Action::create("EditAdd", Gtk::Stock::ADD, _("Add")),
01973 sigc::mem_fun(*this, &KitListGui::on_menu_add)
01974 );
01975
01976
01977 m_refActionGroup->add(
01978 Gtk::Action::create("EditDelete", Gtk::Stock::DELETE, _("Delete")),
01979 sigc::mem_fun(*this, &KitListGui::on_menu_delete)
01980 );
01981
01982
01983 m_refActionGroup->add(
01984 Gtk::Action::create("EditCheckSelected", Gtk::Stock::APPLY, _("Check Selected")),
01985 sigc::mem_fun(*this, &KitListGui::on_menu_check_selected)
01986 );
01987
01988
01989 m_refActionGroup->add(
01990 Gtk::Action::create("EditUncheckSelected", Gtk::Stock::CLEAR, _("Uncheck Selected")),
01991 sigc::mem_fun(*this, &KitListGui::on_menu_uncheck_selected)
01992 );
01993
01994
01995 m_refActionGroup->add(
01996 Gtk::Action::create("EditToggleSelected", Gtk::Stock::CONVERT, _("Toggle Selected")),
01997 sigc::mem_fun(*this, &KitListGui::toggle_selected)
01998 );
01999
02000
02001 m_refActionGroup->add(
02002 Gtk::Action::create("EditCut", Gtk::Stock::CUT, _("Cut")),
02003 sigc::mem_fun(*this, &KitListGui::on_menu_cut)
02004 );
02005
02006
02007 m_refActionGroup->add(
02008 Gtk::Action::create("EditCopy", Gtk::Stock::COPY, _("Copy")),
02009 sigc::mem_fun(*this, &KitListGui::on_menu_copy)
02010 );
02011
02012
02013 m_refActionGroup->add(
02014 Gtk::Action::create("EditPaste", Gtk::Stock::PASTE, _("Paste")),
02015 sigc::mem_fun(*this, &KitListGui::on_menu_paste)
02016 );
02017
02018
02019 m_refActionGroup->add(
02020 Gtk::Action::create("ViewShowAll", Gtk::Stock::FIND, _("Show All")),
02021 sigc::mem_fun(*this, &KitListGui::on_menu_show_all)
02022 );
02023
02024
02025 m_refActionGroup->add(
02026 Gtk::Action::create("ViewShowChecked", Gtk::Stock::YES, _("Show Checked")),
02027 sigc::mem_fun(*this, &KitListGui::on_menu_show_checked)
02028 );
02029
02030
02031 m_refActionGroup->add(
02032 Gtk::Action::create("ViewShowUnchecked", Gtk::Stock::NO, _("Show Unchecked")),
02033 sigc::mem_fun(*this, &KitListGui::on_menu_show_unchecked)
02034 );
02035
02036
02037 m_refActionGroup->add(
02038 Gtk::Action::create("ViewRefresh", Gtk::Stock::REFRESH, _("Refresh")),
02039 sigc::mem_fun(*this, &KitListGui::refresh_item_list)
02040 );
02041
02042
02043 m_refActionGroup->add(
02044 Gtk::Action::create("CategoryAdd", Gtk::Stock::ADD, _("New")),
02045 sigc::mem_fun(*this, &KitListGui::on_menu_create_category)
02046 );
02047
02048
02049 m_refActionGroup->add(
02050 Gtk::Action::create("CategoryRename", Gtk::Stock::EDIT, _("Rename")),
02051 sigc::mem_fun(*this, &KitListGui::on_menu_rename_category)
02052 );
02053
02054
02055 m_refActionGroup->add(
02056 Gtk::Action::create("CategoryDelete", Gtk::Stock::DELETE, _("Delete")),
02057 sigc::mem_fun(*this, &KitListGui::on_menu_delete_category)
02058 );
02059
02060
02061 m_refActionGroup->add(
02062 Gtk::Action::create("HelpContents", Gtk::Stock::HELP, _("Help")),
02063 sigc::mem_fun(*this, &KitListGui::on_menu_help_contents)
02064 );
02065
02066
02067 m_refActionGroup->add(
02068 Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT, _("About")),
02069 sigc::mem_fun(*this, &KitListGui::on_menu_help_about)
02070 );
02071
02072
02073 m_refActionGroup->add( Gtk::Action::create("FileMenu", _("File")) );
02074 m_refActionGroup->add( Gtk::Action::create("FileNew", _("File")) );
02075 m_refActionGroup->add( Gtk::Action::create("EditMenu", _("Edit")) );
02076 m_refActionGroup->add( Gtk::Action::create("EditSubMenu", _("Edit")) );
02077 m_refActionGroup->add( Gtk::Action::create("ViewMenu", _("View")) );
02078 m_refActionGroup->add( Gtk::Action::create("ViewSubMenu", _("View")) );
02079 m_refActionGroup->add( Gtk::Action::create("CategoryMenu", _("Category")) );
02080 m_refActionGroup->add( Gtk::Action::create("CategorySubMenu", _("Category")) );
02081 m_refActionGroup->add( Gtk::Action::create("HelpMenu", _("Help")) );
02082 m_refActionGroup->add( Gtk::Action::create("HelpSubMenu", _("Help")) );
02083 m_refActionGroup->add(
02084 Gtk::Action::create("FileQuit", _("Close")),
02085 sigc::mem_fun(*this, &KitListGui::on_menu_quit)
02086 );
02087 m_refUIManager = Gtk::UIManager::create();
02088 m_refUIManager->insert_action_group(m_refActionGroup);
02089
02090 m_window->add_accel_group(m_refUIManager->get_accel_group());
02091
02092 Glib::ustring ui_info =
02093 "<ui>"
02094 " <popup action='FileMenu'>"
02095 " <menu action='FileNew'>"
02096 " <menuitem action='FileNewStandard'/>"
02097 " <menuitem action='FileOpenStandard'/>"
02098 " <menuitem action='FileSaveStandard'/>"
02099 " <menuitem action='FileSaveAsStandard'/>"
02100 " <menuitem action='FileRecent'/>"
02101 " </menu>"
02102 " <menu action='EditSubMenu'>"
02103 " <menuitem action='EditSelectAll'/>"
02104 " <menuitem action='EditAdd'/>"
02105 " <menuitem action='EditDelete'/>"
02106 " <separator/>"
02107 " <menuitem action='EditCheckSelected'/>"
02108 " <menuitem action='EditUncheckSelected'/>"
02109 " <menuitem action='EditToggleSelected'/>"
02110 " <separator/>"
02111 " <menuitem action='EditCut'/>"
02112 " <menuitem action='EditCopy'/>"
02113 " <menuitem action='EditPaste'/>"
02114 " </menu>"
02115 " <menu action='ViewSubMenu'>"
02116 " <menuitem action='ViewShowAll'/>"
02117 " <menuitem action='ViewShowChecked'/>"
02118 " <menuitem action='ViewShowUnchecked'/>"
02119 " <separator/>"
02120 " <menuitem action='ViewRefresh'/>"
02121 " </menu>"
02122 " <menu action='CategorySubMenu'>"
02123 " <menuitem action='CategoryAdd'/>"
02124 " <menuitem action='CategoryRename'/>"
02125 " <menuitem action='CategoryDelete'/>"
02126 " </menu>"
02127 " <menu action='HelpSubMenu'>"
02128 " <menuitem action='HelpContents'/>"
02129 " <menuitem action='HelpAbout'/>"
02130 " </menu>"
02131 " <menuitem action='FileQuit'/>"
02132 " </popup>"
02133 " <toolbar name='ToolBar'>"
02134
02135
02136
02137
02138 " <toolitem action='EditAdd'/>"
02139
02140
02141 " <toolitem action='EditSelectAll'/>"
02142 " <toolitem action='EditCut'/>"
02143 " <toolitem action='EditCopy'/>"
02144 " <toolitem action='EditPaste'/>"
02145 " <toolitem action='EditCheckSelected'/>"
02146 " <toolitem action='EditUncheckSelected'/>"
02147 " <toolitem action='EditToggleSelected'/>"
02148 " <toolitem action='ViewShowAll'/>"
02149 " <toolitem action='ViewShowChecked'/>"
02150 " <toolitem action='ViewShowUnchecked'/>"
02151 " <toolitem action='ViewRefresh'/>"
02152
02153
02154 " </toolbar>"
02155 "</ui>";
02156
02157 std::auto_ptr<Glib::Error> ex;
02158 m_refUIManager->add_ui_from_string(ui_info, ex);
02159 if (ex.get()) {
02160 g_warning("building menus failed: %s", ex->what().c_str());
02161 }
02162 Gtk::Menu* pMenu = dynamic_cast<Gtk::Menu*>(m_refUIManager->get_widget("/FileMenu"));
02163 if (pMenu) {
02164 m_window->set_main_menu(*pMenu);
02165 }
02166
02167 m_recent_files_menu_item = dynamic_cast<Gtk::MenuItem*>(m_refUIManager->get_widget("/FileMenu/FileNew/FileRecent"));
02168
02169 m_paste_menu_item = dynamic_cast<Gtk::ImageMenuItem*>(m_refUIManager->get_widget("/FileMenu/EditSubMenu/EditPaste"));
02170 if (m_paste_menu_item)
02171 m_paste_menu_item->set_sensitive(false);
02172
02173 m_paste_tool_button = dynamic_cast<Gtk::ToolButton*>(m_refUIManager->get_widget("/ToolBar/EditPaste"));
02174 if (m_paste_tool_button)
02175 m_paste_tool_button->set_sensitive(false);
02176
02177 Gtk::Toolbar* pToolbar = dynamic_cast<Gtk::Toolbar*>(m_refUIManager->get_widget("/ToolBar"));
02178 if(pToolbar)
02179 m_window->add_toolbar(*pToolbar);
02180
02181
02182
02183
02184
02185 refXml->get_widget("window_add_item", m_window_add_item);
02186 if (m_window_add_item == NULL) {
02187 g_warning("Cannot find window_add_item");
02188 }
02189
02190
02191 #else
02192 Glib::RefPtr<Gnome::Glade::Xml> refXml = get_glade_ref_ptr(GLADE_APP_FILE);
02193 refXml->get_widget("main", m_window);
02194 refXml->get_widget("statusbar", m_status_bar);
02195 #endif // MAEMO
02196 refXml->get_widget("window_add_item", m_window_add_item);
02197 refXml->get_widget("window_add_category", m_window_add_category);
02198 m_window->signal_delete_event().connect( sigc::mem_fun(*this, &KitListGui::on_delete_event) );
02199
02200 #ifndef MAEMO
02201
02202 Gtk::MenuItem* p_menu_item = 0;
02203 refXml->get_widget("menu_file_quit", p_menu_item);
02204 if (p_menu_item)
02205 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_quit) );
02206 Gtk::ToolButton* p_tool_button = 0;
02207 refXml->get_widget("tool_button_quit", p_tool_button);
02208 if (p_tool_button)
02209 p_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_quit) );
02210
02211
02212 p_menu_item = 0;
02213 refXml->get_widget("menu_delete_item", p_menu_item);
02214 if (p_menu_item)
02215 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_delete) );
02216 p_tool_button = 0;
02217 refXml->get_widget("tool_button_delete", p_tool_button);
02218 if (p_tool_button)
02219 p_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_delete) );
02220
02221
02222 p_menu_item = 0;
02223 refXml->get_widget("menu_add_item", p_menu_item);
02224 if (p_menu_item)
02225 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_add) );
02226 p_tool_button = 0;
02227 refXml->get_widget("tool_button_add", p_tool_button);
02228 if (p_tool_button)
02229 p_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_add) );
02230 #endif
02231 Gtk::Button* p_button = 0;
02232 refXml->get_widget("add_item_ok_button", p_button);
02233 if (p_button)
02234 p_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::close_add_item_window) );
02235 p_button = 0;
02236 refXml->get_widget("add_item_cancel_button", p_button);
02237 if (p_button)
02238 p_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::cancel_add_item_window) );
02239 refXml->get_widget("entry_item_desc", m_entry_add_item);
02240 assert(m_entry_add_item);
02241 refXml->get_widget("item_checkbutton", m_checkbutton_add_item);
02242 assert(m_checkbutton_add_item);
02243
02244 #ifndef MAEMO
02245
02246 p_menu_item = 0;
02247 refXml->get_widget("menu_new", p_menu_item);
02248 if (p_menu_item) {
02249 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_file_new) );
02250 p_menu_item->set_sensitive(m_service.require_filename());
02251 }
02252 p_tool_button = 0;
02253 refXml->get_widget("tool_button_new", p_tool_button);
02254 if (p_tool_button) {
02255 p_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_file_new) );
02256 p_tool_button->set_sensitive(m_service.require_filename());
02257 }
02258
02259
02260 p_menu_item = 0;
02261 refXml->get_widget("menu_open", p_menu_item);
02262 if (p_menu_item) {
02263 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_file_open) );
02264 p_menu_item->set_sensitive(m_service.require_filename());
02265 }
02266 p_tool_button = 0;
02267 refXml->get_widget("tool_button_open", p_tool_button);
02268 if (p_tool_button) {
02269 p_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_file_open) );
02270 p_tool_button->set_sensitive(m_service.require_filename());
02271 }
02272
02273
02274 refXml->get_widget("menu_save", m_file_save_menu_item);
02275 if (m_file_save_menu_item)
02276 m_file_save_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_save) );
02277 refXml->get_widget("tool_button_save", m_file_save_tool_button);
02278 if (m_file_save_tool_button) {
02279 m_file_save_tool_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::on_menu_save) );
02280 }
02281
02282
02283 p_menu_item = 0;
02284 refXml->get_widget("menu_save_as", p_menu_item);
02285 if (p_menu_item) {
02286 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_save_as) );
02287 #ifdef TRANSITION_DAO
02288 p_menu_item->set_sensitive(true);
02289 #else
02290 p_menu_item->set_sensitive(m_service.require_filename());
02291 #endif
02292 }
02293
02294 refXml->get_widget("menu_recent", m_recent_files_menu_item);
02295
02296
02297 p_menu_item = 0;
02298 refXml->get_widget("menu_cut", p_menu_item);
02299 if (p_menu_item)
02300 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_cut) );
02301
02302
02303 p_menu_item = 0;
02304 refXml->get_widget("menu_copy", p_menu_item);
02305 if (p_menu_item)
02306 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_copy) );
02307
02308
02309 refXml->get_widget("menu_paste", m_paste_menu_item);
02310 if (m_paste_menu_item)
02311 m_paste_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_paste) );
02312
02313
02314 p_menu_item = 0;
02315 refXml->get_widget("show_all", p_menu_item);
02316 if (p_menu_item)
02317 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_show_all) );
02318
02319
02320 p_menu_item = 0;
02321 refXml->get_widget("show_checked", p_menu_item);
02322 if (p_menu_item)
02323 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_show_checked) );
02324
02325
02326 p_menu_item = 0;
02327 refXml->get_widget("show_unchecked", p_menu_item);
02328 if (p_menu_item)
02329 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_show_unchecked) );
02330
02331
02332 p_menu_item = 0;
02333 refXml->get_widget("refresh_view", p_menu_item);
02334 if (p_menu_item)
02335 p_menu_item->signal_activate().connect ( sigc::mem_fun(*this, &KitListGui::refresh_item_list) );
02336
02337
02338 p_menu_item = 0;
02339 refXml->get_widget("select_all", p_menu_item);
02340 if (p_menu_item)
02341 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_select_all) );
02342
02343
02344 p_menu_item = 0;
02345 refXml->get_widget("check_selected", p_menu_item);
02346 if (p_menu_item)
02347 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_check_selected) );
02348
02349
02350 p_menu_item = 0;
02351 refXml->get_widget("uncheck_selected", p_menu_item);
02352 if (p_menu_item)
02353 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_uncheck_selected) );
02354
02355
02356 p_menu_item = 0;
02357 refXml->get_widget("toggle_selected", p_menu_item);
02358 if (p_menu_item)
02359 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::toggle_selected) );
02360
02361
02362 p_menu_item = 0;
02363 refXml->get_widget("create_category", p_menu_item);
02364 if (p_menu_item)
02365 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_create_category) );
02366 #endif // ifndef MAEMO
02367
02368 #ifdef XML_DAO
02369 update_recent_files_menu();
02370 #else
02371 m_recent_files_menu_item->set_sensitive(false);
02372 #endif
02373
02374 p_button = 0;
02375 refXml->get_widget("add_category_ok_button", p_button);
02376 if (p_button)
02377 p_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::close_add_category_window) );
02378 p_button = 0;
02379 refXml->get_widget("add_category_cancel_button", p_button);
02380 if (p_button)
02381 p_button->signal_clicked().connect( sigc::mem_fun(*this, &KitListGui::cancel_add_category_window) );
02382 refXml->get_widget("entry_category_name", m_entry_add_category);
02383 assert(m_entry_add_category);
02384
02385 #ifndef MAEMO
02386
02387 p_menu_item = 0;
02388 refXml->get_widget("delete_category", p_menu_item);
02389 if (p_menu_item)
02390 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_delete_category) );
02391
02392
02393 p_menu_item = 0;
02394 refXml->get_widget("rename_category", p_menu_item);
02395 if (p_menu_item)
02396 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_rename_category) );
02397
02398
02399 p_menu_item = 0;
02400 refXml->get_widget("help_about", p_menu_item);
02401 if (p_menu_item)
02402 p_menu_item->signal_activate().connect( sigc::mem_fun(*this, &KitListGui::on_menu_help_about) );
02403 #endif
02404
02405 m_ref_category_list_store = Gtk::ListStore::create(m_category_cols);
02406 #ifdef MAEMO
02407
02408
02409 Gtk::ToolItem* ti = new Gtk::ToolItem;
02410 m_category_combo = new Gtk::ComboBox(m_ref_category_list_store);
02411 m_category_combo->pack_start(m_category_cols.m_col_text);
02412 m_category_combo->set_column_span_column(1);
02413 ti->add(*m_category_combo);
02414 ti->set_expand();
02415 m_category_combo->set_size_request(40, 10);
02416 pToolbar->append(*ti);
02417 pToolbar->show_all();
02418 #else
02419
02420 refXml->get_widget("categoryCombo", m_category_combo);
02421 m_category_combo->set_model(m_ref_category_list_store);
02422 #endif
02423 refresh_category_list();
02424 m_category_combo->signal_changed().connect( sigc::mem_fun(*this, &KitListGui::on_category_change) );
02425
02426
02427 m_ref_item_tree_model = Gtk::ListStore::create(m_item_cols);
02428 refXml->get_widget("item_treeview", m_item_tree_view);
02429
02430 m_item_tree_view->set_model(m_ref_item_tree_model);
02431 ItemContainer* items = m_service.get_items();
02432 if (!items->empty()) {
02433 sort(items->begin(), items->end(), ItemCompareName());
02434 for (ItemIter i = items->begin(); i != items->end(); ++i) {
02435
02436 Gtk::TreeModel::iterator itemIter = m_ref_item_tree_model->append();
02437 Gtk::TreeModel::Row row = *itemIter;
02438 row[m_item_cols.m_col_text] = (*i)->get_description();
02439 row[m_item_cols.m_col_num] = (*i)->get_id();
02440 row[m_item_cols.m_col_checked] = (*i)->get_checked();
02441 }
02442 }
02443 m_ref_item_tree_model->signal_row_changed().connect( sigc::mem_fun(*this, &KitListGui::on_row_changed) );
02444
02445 update_item_count(items->size());
02446 delete items;
02447
02448 m_item_tree_view->append_column_editable(_("Checked"), m_item_cols.m_col_checked);
02449
02450 m_item_tree_view->append_column_editable(_("Item"), m_item_cols.m_col_text);
02451 #ifdef MAEMO
02452 m_item_tree_view->set_headers_visible(false);
02453 #endif
02454
02455
02456
02457
02458
02459
02460
02461 Glib::RefPtr<Gtk::TreeSelection> ref_tree_selection =
02462 m_item_tree_view->get_selection();
02463 ref_tree_selection->set_mode(Gtk::SELECTION_MULTIPLE);
02464 m_ignore_list_events = false;
02465 m_service.set_model_dirty(false);
02466 #ifdef XML_DAO
02467 if (filename.length() == 0 || !file_exists(filename)) {
02468
02469 filename = Glib::build_filename(
02470 Glib::get_home_dir(),
02471 DEFAULT_FILENAME);
02472
02473 m_filename = filename;
02474 }
02475 if (filename.length() > 0 && file_exists(filename)) {
02476
02477 m_filename = filename;
02478 m_service.open_as_xml(m_filename);
02479 refresh_category_list(-1);
02480 refresh_item_list();
02481 }
02482 #endif
02483 }