libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GtkCRNMain.cpp
Go to the documentation of this file.
1 /* Copyright 2010-2016 CoReNum, INSA-Lyon, 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: GtkCRNMain.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <libgtkcrnmm_config.h>
23 #include <CRN.h>
24 #include <CRNConfig.h>
25 #include <GtkCRNMain.h>
26 #include <CRNString.h>
27 #include <CRNIO/CRNIO.h>
28 #include <GdkCRNPixbuf.h>
29 #include <iostream>
30 #ifdef __GNUG__
31 # include <cxxabi.h>
32 #endif
33 #include <CRNi18n.h>
34 
35 #include "logo64trans.hpp"
36 #include "icon64trans.hpp"
37 #include "icon64circletrans.hpp"
38 
39 using namespace crn;
40 using namespace GtkCRN;
41 
42 #ifdef _MSC_VER
43 const char *HOMEPATH = "APPDATA";
44 #else
45 const char *HOMEPATH = "HOME";
46 #endif
47 
48 bool Main::init_done(false);
49 
50 Main::Main(int &argc, char **&argv):
51 #ifdef CRN_USING_GTKMM3
52  Gtk::Application(argc, argv)
53 #else
54  Gtk::Main(argc, argv),
55  iconfac(Gtk::IconFactory::create())
56 #endif
57 {
58  if (!init_done)
59  {
60  // init
61  if (!Glib::thread_supported())
62  Glib::thread_init();
63 
64  Glib::init();
65  //Gio::init(); // XXX TODO symbole non export� // locales char *loc = getenv("LANG"); CRNdout << GETTEXT_PACKAGE << " LANG environment var: " << (loc == nullptr ? "none" : loc) << std::endl; #if !defined(CRN_USING_GLIB_INTL) && !defined(CRN_USING_LIBINTL) loc = setlocale(LC_ALL, "C"); #else loc = setlocale(LC_ALL, ""); #endif if (!loc) CRNdout << GETTEXT_PACKAGE << " setlocale failed" << std::endl; else CRNdout << GETTEXT_PACKAGE << " locale = " << loc << std::endl; CRNdout << GETTEXT_PACKAGE << " gettext package = " << GETTEXT_PACKAGE << std::endl; CRNdout << "setting path to " << Config::GetLocalePath().CStr() << std::endl; loc = CRNbindtextdomain(GETTEXT_PACKAGE, Config::GetLocalePath().CStr()); if (!loc) CRNdout << GETTEXT_PACKAGE << " no bound path. should be " << Config::GetLocalePath().CStr() << std::endl; else CRNdout << GETTEXT_PACKAGE << " path = " << loc << std::endl; loc = CRNbind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); if (!loc) CRNdout << GETTEXT_PACKAGE << " no bound codeset. should be " << "UTF-8" << std::endl; else CRNdout << GETTEXT_PACKAGE << " Codeset = " << loc << std::endl; loc = CRNtextdomain(GETTEXT_PACKAGE); if (!loc) CRNdout << GETTEXT_PACKAGE << " textdomain failed" << std::endl; else CRNdout << GETTEXT_PACKAGE << " text domain = " << loc << std::endl; CRNdout << _("Using default language.") << std::endl; init_done = true; } #ifdef CRN_USING_GTKMM3 //Gtk::IconTheme::get_default()->add_ressource_path(Config::GetStaticDataPath().CStr()); #else // icons struct {const char *file; const char *name;} iconlist[] = { {"addblock.png", "gtk-crn-add-block"}, {"addview.png", "gtk-crn-add-view"}, {"block.png", "gtk-crn-block"}, {"document.png", "gtk-crn-document"}, {"eraser.png", "gtk-crn-eraser"}, {"even.png", "gtk-crn-even"}, {"eye.png", "gtk-crn-eye"}, {"filter.png", "gtk-crn-filter"}, {"find.png", "gtk-crn-find"}, {"find_from_file.png", "gtk-crn-find-from-file"}, {"findpencil.png", "gtk-crn-findpencil"}, {"image.png", "gtk-crn-image"}, {"inkpen.png", "gtk-crn-inkpen"}, {"invert.png", "gtk-crn-invert"}, {"key.png", "gtk-crn-key"}, {"keyboard.png", "gtk-crn-keyboard"}, {"lens.png", "gtk-crn-lens"}, {"line05.png", "gtk-crn-line-0.5"}, {"line1.png", "gtk-crn-line-1"}, {"line2.png", "gtk-crn-line-2"}, {"line3.png", "gtk-crn-line-3"}, {"log.png", "gtk-crn-log"}, {"merge.png", "gtk-crn-merge"}, {"mouse.png", "gtk-crn-mouse"}, {"odd.png", "gtk-crn-odd"}, {"paintbrush.png", "gtk-crn-paintbrush"}, {"pencil.png", "gtk-crn-pencil"}, {"remblock.png", "gtk-crn-delete-block"}, {"remview.png", "gtk-crn-delete-view"}, {"rotate_180.png", "gtk-crn-rotate-180"}, {"rotate_left.png", "gtk-crn-rotate-left"}, {"rotate_right.png", "gtk-crn-rotate-right"}, {"script.png", "gtk-crn-script"}, {"size_plus.png", "gtk-crn-size-plus"}, {"size_minus.png", "gtk-crn-size-minus"}, {"square1.png", "gtk-crn-square-1"}, {"square2.png", "gtk-crn-square-2"}, {"square3.png", "gtk-crn-square-3"}, {"square4.png", "gtk-crn-square-4"}, {"view.png", "gtk-crn-view"}, {"rgb.png", "gtk-crn-rgb"}, {"gray.png", "gtk-crn-gray"}, {"bw.png", "gtk-crn-bw"}, {"cmyk.png", "gtk-crn-cmyk"}, {"twopages.png", "gtk-crn-two-pages"}, {"paragraph.png", "gtk-crn-paragraph"}, }; crn::Path basedir(Config::GetStaticDataPath() + crn::Path::Separator()); for (size_t tmp = 0; tmp < sizeof(iconlist) / (2 * sizeof(const char*)); tmp++) { try { Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_file((basedir + iconlist[tmp].file).CStr()); if (pb) { icons.push_back(Gtk::IconSet(pb)); iconfac->add(Gtk::StockID(iconlist[tmp].name), icons.back()); } } catch (...) { CRNError("libgtkcrnmm: Missing file: " + basedir + iconlist[tmp].file); } } Glib::RefPtr<Gdk::Pixbuf> pb(Gdk::Pixbuf::create_from_inline(sizeof(logo64), logo64)); if (pb) { icons.push_back(Gtk::IconSet(pb)); iconfac->add(Gtk::StockID("corenum-logo"), icons.back()); } pb = Gdk::Pixbuf::create_from_inline(sizeof(icon64), icon64); if (pb) { icons.push_back(Gtk::IconSet(pb)); iconfac->add(Gtk::StockID("corenum-icon"), icons.back()); } pb = Gdk::Pixbuf::create_from_inline(sizeof(icon64circle), icon64circle); if (pb) { icons.push_back(Gtk::IconSet(pb)); iconfac->add(Gtk::StockID("corenum-icon-circle"), icons.back()); } iconfac->add_default(); Gtk::IconTheme::get_default()->append_search_path(Config::GetStaticDataPath().CStr()); #endif } void Main::run_thread_safe() { #ifdef CRN_USING_GTKMM3 #else /* CRN_USING_GTKMM3 */ gdk_threads_enter(); #endif /* CRN_USING_GTKMM3 */ try { run(); } catch (crn::Exception &ex) { CRNdout << ex.GetMessage().c_str() << std::endl; CRNdout << ex.GetContext().c_str() << std::endl; } catch (std::exception &ex) { CRNdout << ex.what() << std::endl; } catch (...) { CRNdout << "unknown error" << std::endl; } #ifdef CRN_USING_GTKMM3 #else /* CRN_USING_GTKMM3 */ gdk_threads_leave(); #endif /* CRN_USING_GTKMM3 */ } static void gtkcrnmmterminate() { try { throw; } catch (const Exception &ex) { const char *exname = typeid(ex).name(); #ifdef __GNUG__ int status = -1; char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status); if (status == 0) { exname = ret; } #endif std::cerr << "Unhandled <" << exname << ">: " << std::endl; #ifdef __GNUG__ free(ret); #endif std::cerr << "what: " << ex.what() << std::endl; std::cerr << "context: " << ex.GetContext().c_str() << std::endl; } catch (const Glib::Exception &ex) { const char *exname = typeid(ex).name(); #ifdef __GNUG__ int status = -1; char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status); if (status == 0) { exname = ret; } #endif std::cerr << "Unhandled <" << exname << ">: " << std::endl; #ifdef __GNUG__ free(ret); #endif std::cerr << "what: " << ex.what().c_str() << std::endl; } catch (const std::exception &ex) { const char *exname = typeid(ex).name(); #ifdef __GNUG__ int status = -1; char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status); if (status == 0) { exname = ret; } #endif std::cerr << "Unhandled <" << exname << ">: " << std::endl; #ifdef __GNUG__ free(ret); #endif std::cerr << "what: " << ex.what() << std::endl; } catch (...) { std::cerr << "Unexpected exception!" << std::endl; } abort(); } /*! Sets the default exception handler to print message and context to the standard error */ void Main::SetDefaultExceptionHandler() { Glib::add_exception_handler(sigc::ptr_fun(gtkcrnmmterminate)); crn::Exception::SetDefaultHandler(); }
66 
67  // locales
68  char *loc = getenv("LANG");
69  CRNdout << GETTEXT_PACKAGE << " LANG environment var: " << (loc == nullptr ? "none" : loc) << std::endl;
70 
71 #if !defined(CRN_USING_GLIB_INTL) && !defined(CRN_USING_LIBINTL)
72  loc = setlocale(LC_ALL, "C");
73 #else
74  loc = setlocale(LC_ALL, "");
75 #endif
76  if (!loc)
77  CRNdout << GETTEXT_PACKAGE << " setlocale failed" << std::endl;
78  else
79  CRNdout << GETTEXT_PACKAGE << " locale = " << loc << std::endl;
80 
81  CRNdout << GETTEXT_PACKAGE << " gettext package = " << GETTEXT_PACKAGE << std::endl;
82 
83  CRNdout << "setting path to " << Config::GetLocalePath().CStr() << std::endl;
84  loc = CRNbindtextdomain(GETTEXT_PACKAGE, Config::GetLocalePath().CStr());
85  if (!loc)
86  CRNdout << GETTEXT_PACKAGE << " no bound path. should be " << Config::GetLocalePath().CStr() << std::endl;
87  else
88  CRNdout << GETTEXT_PACKAGE << " path = " << loc << std::endl;
89  loc = CRNbind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
90  if (!loc)
91  CRNdout << GETTEXT_PACKAGE << " no bound codeset. should be " << "UTF-8" << std::endl;
92  else
93  CRNdout << GETTEXT_PACKAGE << " Codeset = " << loc << std::endl;
94  loc = CRNtextdomain(GETTEXT_PACKAGE);
95  if (!loc)
96  CRNdout << GETTEXT_PACKAGE << " textdomain failed" << std::endl;
97  else
98  CRNdout << GETTEXT_PACKAGE << " text domain = " << loc << std::endl;
99 
100  CRNdout << _("Using default language.") << std::endl;
101 
102  init_done = true;
103  }
104 
105 #ifdef CRN_USING_GTKMM3
106  //Gtk::IconTheme::get_default()->add_ressource_path(Config::GetStaticDataPath().CStr());
107 #else
108  // icons
109  struct {const char *file; const char *name;} iconlist[] =
110  {
111  {"addblock.png", "gtk-crn-add-block"},
112  {"addview.png", "gtk-crn-add-view"},
113  {"block.png", "gtk-crn-block"},
114  {"document.png", "gtk-crn-document"},
115  {"eraser.png", "gtk-crn-eraser"},
116  {"even.png", "gtk-crn-even"},
117  {"eye.png", "gtk-crn-eye"},
118  {"filter.png", "gtk-crn-filter"},
119  {"find.png", "gtk-crn-find"},
120  {"find_from_file.png", "gtk-crn-find-from-file"},
121  {"findpencil.png", "gtk-crn-findpencil"},
122  {"image.png", "gtk-crn-image"},
123  {"inkpen.png", "gtk-crn-inkpen"},
124  {"invert.png", "gtk-crn-invert"},
125  {"key.png", "gtk-crn-key"},
126  {"keyboard.png", "gtk-crn-keyboard"},
127  {"lens.png", "gtk-crn-lens"},
128  {"line05.png", "gtk-crn-line-0.5"},
129  {"line1.png", "gtk-crn-line-1"},
130  {"line2.png", "gtk-crn-line-2"},
131  {"line3.png", "gtk-crn-line-3"},
132  {"log.png", "gtk-crn-log"},
133  {"merge.png", "gtk-crn-merge"},
134  {"mouse.png", "gtk-crn-mouse"},
135  {"odd.png", "gtk-crn-odd"},
136  {"paintbrush.png", "gtk-crn-paintbrush"},
137  {"pencil.png", "gtk-crn-pencil"},
138  {"remblock.png", "gtk-crn-delete-block"},
139  {"remview.png", "gtk-crn-delete-view"},
140  {"rotate_180.png", "gtk-crn-rotate-180"},
141  {"rotate_left.png", "gtk-crn-rotate-left"},
142  {"rotate_right.png", "gtk-crn-rotate-right"},
143  {"script.png", "gtk-crn-script"},
144  {"size_plus.png", "gtk-crn-size-plus"},
145  {"size_minus.png", "gtk-crn-size-minus"},
146  {"square1.png", "gtk-crn-square-1"},
147  {"square2.png", "gtk-crn-square-2"},
148  {"square3.png", "gtk-crn-square-3"},
149  {"square4.png", "gtk-crn-square-4"},
150  {"view.png", "gtk-crn-view"},
151  {"rgb.png", "gtk-crn-rgb"},
152  {"gray.png", "gtk-crn-gray"},
153  {"bw.png", "gtk-crn-bw"},
154  {"cmyk.png", "gtk-crn-cmyk"},
155  {"twopages.png", "gtk-crn-two-pages"},
156  {"paragraph.png", "gtk-crn-paragraph"},
157  };
158  crn::Path basedir(Config::GetStaticDataPath() + crn::Path::Separator());
159  for (size_t tmp = 0; tmp < sizeof(iconlist) / (2 * sizeof(const char*)); tmp++)
160  {
161  try
162  {
163  Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_file((basedir + iconlist[tmp].file).CStr());
164  if (pb)
165  {
166  icons.push_back(Gtk::IconSet(pb));
167  iconfac->add(Gtk::StockID(iconlist[tmp].name), icons.back());
168  }
169  }
170  catch (...)
171  {
172  CRNError("libgtkcrnmm: Missing file: " + basedir + iconlist[tmp].file);
173  }
174  }
175  Glib::RefPtr<Gdk::Pixbuf> pb(Gdk::Pixbuf::create_from_inline(sizeof(logo64), logo64));
176  if (pb)
177  {
178  icons.push_back(Gtk::IconSet(pb));
179  iconfac->add(Gtk::StockID("corenum-logo"), icons.back());
180  }
181  pb = Gdk::Pixbuf::create_from_inline(sizeof(icon64), icon64);
182  if (pb)
183  {
184  icons.push_back(Gtk::IconSet(pb));
185  iconfac->add(Gtk::StockID("corenum-icon"), icons.back());
186  }
187  pb = Gdk::Pixbuf::create_from_inline(sizeof(icon64circle), icon64circle);
188  if (pb)
189  {
190  icons.push_back(Gtk::IconSet(pb));
191  iconfac->add(Gtk::StockID("corenum-icon-circle"), icons.back());
192  }
193  iconfac->add_default();
194  Gtk::IconTheme::get_default()->append_search_path(Config::GetStaticDataPath().CStr());
195 #endif
196 }
197 
199 {
200 #ifdef CRN_USING_GTKMM3
201 #else /* CRN_USING_GTKMM3 */
202  gdk_threads_enter();
203 #endif /* CRN_USING_GTKMM3 */
204  try
205  {
206  run();
207  }
208  catch (crn::Exception &ex)
209  {
210  CRNdout << ex.GetMessage().c_str() << std::endl;
211  CRNdout << ex.GetContext().c_str() << std::endl;
212  }
213  catch (std::exception &ex)
214  {
215  CRNdout << ex.what() << std::endl;
216  }
217  catch (...)
218  {
219  CRNdout << "unknown error" << std::endl;
220  }
221 #ifdef CRN_USING_GTKMM3
222 #else /* CRN_USING_GTKMM3 */
223  gdk_threads_leave();
224 #endif /* CRN_USING_GTKMM3 */
225 }
226 
227 static void gtkcrnmmterminate()
228 {
229  try
230  {
231  throw;
232  }
233  catch (const Exception &ex)
234  {
235  const char *exname = typeid(ex).name();
236 #ifdef __GNUG__
237  int status = -1;
238  char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status);
239  if (status == 0)
240  {
241  exname = ret;
242  }
243 #endif
244  std::cerr << "Unhandled <" << exname << ">: " << std::endl;
245 #ifdef __GNUG__
246  free(ret);
247 #endif
248  std::cerr << "what: " << ex.what() << std::endl;
249  std::cerr << "context: " << ex.GetContext().c_str() << std::endl;
250  }
251  catch (const Glib::Exception &ex)
252  {
253  const char *exname = typeid(ex).name();
254 #ifdef __GNUG__
255  int status = -1;
256  char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status);
257  if (status == 0)
258  {
259  exname = ret;
260  }
261 #endif
262  std::cerr << "Unhandled <" << exname << ">: " << std::endl;
263 #ifdef __GNUG__
264  free(ret);
265 #endif
266  std::cerr << "what: " << ex.what().c_str() << std::endl;
267  }
268  catch (const std::exception &ex)
269  {
270  const char *exname = typeid(ex).name();
271 #ifdef __GNUG__
272  int status = -1;
273  char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status);
274  if (status == 0)
275  {
276  exname = ret;
277  }
278 #endif
279  std::cerr << "Unhandled <" << exname << ">: " << std::endl;
280 #ifdef __GNUG__
281  free(ret);
282 #endif
283  std::cerr << "what: " << ex.what() << std::endl;
284  }
285  catch (...)
286  {
287  std::cerr << "Unexpected exception!" << std::endl;
288  }
289  abort();
290 }
291 
294 {
295  Glib::add_exception_handler(sigc::ptr_fun(gtkcrnmmterminate));
297 }
298 
299 
const char * HOMEPATH
Definition: GtkCRNMain.cpp:45
static void SetDefaultExceptionHandler()
Sets the default exception handler to print message and context to the standard error.
Definition: GtkCRNMain.cpp:293
const std::string & GetMessage() const noexcept
String containing a description of the exception.
void run_thread_safe()
Launches the application.
Definition: GtkCRNMain.cpp:198
#define _(String)
Definition: CRNi18n.h:51
static char Separator() noexcept
Local directory separator.
Definition: CRNPath.cpp:42
char * CRNbindtextdomain(const char *, const char *)
Definition: CRNi18n.h:54
#define CRNdout
Definition: CRNIO.h:143
const std::string & GetContext() const noexcept
String containing the call stack at the moment of throw.
A convenience class for file paths.
Definition: CRNPath.h:39
static void SetDefaultHandler()
Sets the default exception handler to print message and context to the standard error.
#define CRNError(x)
Definition: CRNIO.h:147
char * CRNtextdomain(const char *)
Definition: CRNi18n.h:53
Main loop and context.
Definition: GtkCRNMain.h:38
virtual const char * what() const noexceptoverride
String containing a description of the exception.
char * CRNbind_textdomain_codeset(const char *, const char *)
Definition: CRNi18n.h:55
Base class for exceptions.
Definition: CRNException.h:39