libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GtkCRNApp.cpp
Go to the documentation of this file.
1 /* Copyright 2010-2016 CoReNum, ENS-Lyon
2  *
3  * This file is part of libgtkcrnmm.
4  *
5  * libgtkcrnmm is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libgtkcrnmm is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libgtkcrnmm. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: GtkCRNApp.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <libgtkcrnmm_config.h>
23 #include <GtkCRNApp.h>
24 #include <CRN.h>
25 #include <CRNString.h>
26 #include <CRNIO/CRNIO.h>
27 #include <CRNi18n.h>
28 
29 #ifndef CRN_USING_GTKMM3
30 # define get_content_area get_vbox
31 #endif
32 
33 using namespace crn;
34 using namespace GtkCRN;
35 
36 Gtk::Window*& App::internal_main_window() { static Gtk::Window *main = nullptr; return main; }
37 
38 #ifdef CRN_USING_GTKMM3
39 
40 App::App():
41  actions(Gio::SimpleActionGroup::create())
42 {
43  actions->add_action("file-menu");
44  actions->add_action("quit", sigc::bind(sigc::hide_return(sigc::mem_fun(this, &App::ask_for_quit)), (GdkEventAny*)nullptr));
45  actions->add_action("help-menu");
46  actions->add_action("help", sigc::mem_fun(this, &App::help));
47  actions->add_action("about", sigc::mem_fun(this, &App::about));
48 
49  signal_realize().connect(sigc::bind(sigc::mem_fun(this, &Gtk::Widget::insert_action_group), "app", actions));
50 
51  signal_delete_event().connect(sigc::mem_fun(this, &App::ask_for_quit));
52 }
53 #else
54 
56  ui_manager(Gtk::UIManager::create()),
57  actions(Gtk::ActionGroup::create("GtkCRN::App actions"))
58 {
59  actions->add(Gtk::Action::create("app-file-menu", _("_File"), _("File")));
60  actions->add(Gtk::Action::create("app-quit", Gtk::Stock::QUIT), sigc::bind(sigc::hide_return(sigc::mem_fun(this, &App::ask_for_quit)), (GdkEventAny*)nullptr));
61  actions->add(Gtk::Action::create("app-help-menu", Gtk::StockID("corenum-icon-circle"), _("_?"), _("?")));
62  actions->add(Gtk::Action::create("app-help", Gtk::Stock::HELP), sigc::mem_fun(this, &App::help));
63  actions->add(Gtk::Action::create("app-about", Gtk::Stock::ABOUT), sigc::mem_fun(this, &App::about));
64 
65  ui_manager->insert_action_group(actions);
66 
67  signal_delete_event().connect(sigc::mem_fun(this, &App::ask_for_quit));
68 }
69 #endif
70 
71 #include <iostream>
76 bool App::ask_for_quit(GdkEventAny* event)
77 {
78  Gtk::MessageDialog dial(*this, _("Are you sure you want to quit?"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
79  if (dial.run() == Gtk::RESPONSE_YES)
80  {
81 #ifdef CRN_USING_GTKMM3
82  hide();
83 #else
84  Gtk::Main::quit();
85 #endif
86  return false;
87  }
88  return true;
89 }
90 
96 Glib::ustring App::ask_for_string(const Glib::ustring &msg, const Glib::ustring &defval)
97 {
98 #ifdef CRN_USING_GTKMM3
99  Gtk::Dialog dial("", *this, true);
100 #else /* CRN_USING_GTKMM3 */
101  Gtk::Dialog dial("", *this, true, false);
102 #endif /* CRN_USING_GTKMM3 */
103  dial.set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
104  Gtk::Label lab(msg);
105  lab.show();
106  dial.get_content_area()->pack_start(lab, false, true, 2);
107  Gtk::Entry ent;
108  ent.set_activates_default();
109  ent.set_text(defval);
110  ent.show();
111  dial.get_content_area()->pack_start(ent, false, true, 2);
112 #ifdef CRN_USING_GTKMM3
113  dial.add_button(_("_Cancel"), Gtk::RESPONSE_REJECT);
114  dial.add_button(_("_OK"), Gtk::RESPONSE_ACCEPT);
115 #else
116  dial.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_REJECT);
117  dial.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
118  std::vector<int> altbut;
119  altbut.push_back(Gtk::RESPONSE_ACCEPT);
120  altbut.push_back(Gtk::RESPONSE_CANCEL);
121  dial.set_alternative_button_order_from_array(altbut);
122 #endif
123  dial.set_default_response(Gtk::RESPONSE_ACCEPT);
124  if (dial.run() == Gtk::RESPONSE_ACCEPT)
125  return ent.get_text();
126  else
127  return "";
128 }
129 
131 struct mesg
132 {
133  Glib::ustring message;
134  Gtk::MessageType mtype;
135 };
136 static gboolean do_show_message(mesg *message)
137 {
138  Gtk::MessageDialog md(message->message, false, message->mtype, Gtk::BUTTONS_OK, true);
139  md.run();
140  delete message;
141  return false;
142 }
149 void App::show_message(const Glib::ustring &message, Gtk::MessageType mtype)
150 {
151  mesg *msg = new mesg;
152  msg->message = message;
153  msg->mtype = mtype;
154  g_idle_add(GSourceFunc(do_show_message), msg);
155 }
156 
158 struct exc_data
159 {
160  StringUTF8 message;
161  StringUTF8 stack;
162  bool kill;
163 };
164 gboolean display_exception(exc_data *ex)
165 {
166  Gtk::MessageDialog md(ex->message.CStr(), false, ex->kill ? Gtk::MESSAGE_ERROR : Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
167  if (ex->stack.IsNotEmpty())
168  {
169  Gtk::Expander *expd = Gtk::manage(new Gtk::Expander(_("Advanced details")));
170  md.get_content_area()->pack_start(*expd, true, true, 0);
171  Gtk::ScrolledWindow *sw = Gtk::manage(new Gtk::ScrolledWindow);
172  expd->add(*sw);
173  Gtk::TextView *lab = Gtk::manage(new Gtk::TextView);
174  lab->get_buffer()->set_text(ex->stack.CStr());
175  sw->add(*lab);
176  expd->set_expanded(false);
177  expd->show_all();
178  }
179  md.set_resizable(true);
180  md.set_default_size(500, -1);
181  md.run();
182  bool kill = false;
183  if (ex->kill)
184  kill = true;
185  delete ex;
186  if (kill)
187  std::terminate();
188  return false;
189 }
195 void App::show_exception(bool kill_app)
196 {
197  exc_data *msg = new exc_data;
198  msg->message = _("Unhandled exception caught.");
199  msg->kill = kill_app;
200  g_idle_add(GSourceFunc(display_exception), msg);
201 }
202 
207 void App::show_exception(crn::Exception &ex, bool kill_app)
208 {
209  exc_data *msg = new exc_data;
210  msg->message = ex.GetMessage();
211  msg->stack = ex.GetContext();
212  msg->kill = kill_app;
213  g_idle_add(GSourceFunc(display_exception), msg);
214 }
215 
220 void App::show_exception(std::exception &ex, bool kill_app)
221 {
222  exc_data *msg = new exc_data;
223  msg->message = ex.what();
224  msg->kill = kill_app;
225  g_idle_add(GSourceFunc(display_exception), msg);
226 }
227 
228 
Glib::RefPtr< Gtk::ActionGroup > actions
Definition: GtkCRNApp.h:84
Glib::RefPtr< Gtk::UIManager > ui_manager
Definition: GtkCRNApp.h:83
const std::string & GetMessage() const noexcept
String containing a description of the exception.
#define _(String)
Definition: CRNi18n.h:51
Glib::ustring ask_for_string(const Glib::ustring &msg, const Glib::ustring &defval="")
Shows a dialog asking for a single string.
Definition: GtkCRNApp.cpp:96
const std::string & GetContext() const noexcept
String containing the call stack at the moment of throw.
virtual void help()
Displays help (overloadable)
Definition: GtkCRNApp.h:74
static void show_message(const Glib::ustring &message, Gtk::MessageType mtype)
Displays a message.
Definition: GtkCRNApp.cpp:149
virtual void about()
Displays credits (overloadable)
Definition: GtkCRNApp.h:76
static void show_exception(crn::Exception &ex, bool kill_app=true)
Displays an exception.
Definition: GtkCRNApp.cpp:207
App()
Constructor. Creates Actions and adds them to UI manager.
Definition: GtkCRNApp.cpp:55
A character string class.
Definition: CRNStringUTF8.h:49
Base class for exceptions.
Definition: CRNException.h:39
virtual bool ask_for_quit(GdkEventAny *event)
Callback for application quit event (overloadable)
Definition: GtkCRNApp.cpp:76