c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

application.h
Go to the documentation of this file.
1 /* Copyright (C) 2011 and 2013 Chris Vine
2
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License, version 2.1, for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License, version 2.1, along with this library (see the file LGPL.TXT
19 which came with this source code package in the c++-gtk-utils
20 sub-directory); if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 */
24
25 #ifndef CGU_APPLICATION_H
26 #define CGU_APPLICATION_H
27
28 #include <list>
29 #include <exception>
30 #include <utility>
31
32 #include <c++-gtk-utils/cgu_config.h>
33
34 #ifdef CGU_USE_GTK
35 #include <gtk/gtk.h>
36 #endif
37
38 #include <gio/gio.h>
39
40 #include <c++-gtk-utils/gobj_handle.h>
41 #include <c++-gtk-utils/window.h>
42 #include <c++-gtk-utils/emitter.h>
43
44 namespace Cgu {
45
46 #if defined(DOXYGEN_PARSING) || defined(CGU_USE_GTK)
47 #if defined(DOXYGEN_PARSING) || GTK_CHECK_VERSION(2,99,0)
48
49 /**
50 * @class Cgu::ApplicationNameError application.h c++-gtk-utils/application.h
51 * @brief This class is thrown when the program id name passed to the
52 * constructor of Cgu::Application is invalid.
53 */
54 struct ApplicationNameError: public std::exception {
55 virtual const char* what() const throw() {return "ApplicationNameError\n";}
56 };
57
58 /**
59 * @class Cgu::Application application.h c++-gtk-utils/application.h
60 * @brief This is a class for constructing and managing GtkApplication
61 * objects.
62 *
63 * @details It is available since version 2.0.0-rc2. It is only
64 * compiled in with a GTK-3 or GTK-4 installation, and if the library
65 * is not configured with the \--without-gtk option.
66 *
67 * In typical usage, a Cgu::Application object is created in main(),
68 * and then a callback is attached to the 'activate', 'command_line'
69 * or 'open' emitter, depending on the flag passed to the Application
70 * object's constructor. The run() method of the Application object
71 * is then called, and a window deriving from Cgu::WinBase is
72 * constructed in the callback and added to the Application object or,
73 * if the program is a single instance program with only one main
74 * window and an instance is already running, a function is called to
75 * present that window.
76 *
77 * Here is a brief explanation of how the flag options passed to the
78 * Cgu::Application object (and so to the underlying GApplication
79 * object) work:
80 *
81 * @par
82 * (a) If a Cgu::Application object is constructed with the
83 * G_APPLICATION_FLAGS_NONE flag set, then calling the
84 * Cgu::Application::run() method (which hands off to
85 * g_application_run()) will cause the 'activate' emitter to emit. No
86 * command line parameter should be passed to the run method (argc
87 * should be 0 or 1), otherwise GtkApplication will cause the start-up
88 * to abort, except that from glib >=2.40 and gtk >=3.12 recognised
89 * gtk command line options can be passed in for stripping out and
90 * consumption by gtk. g_application_run(), and so
91 * Cgu::Application::run(), can be called with argc and argv set to 0
92 * where such aborting must be avoided.
93 * @par
94 * (b) If a Cgu::Application object is constructed with the
95 * G_APPLICATION_HANDLES_OPEN flag set, then calling the
96 * Cgu::Application::run() method will cause the 'activate' emitter to
97 * emit if no command line parameters were provided when the program
98 * was started, or cause the 'open' emitter to emit if parameters are
99 * passed. Such parameters will be construed as files/uris, and will
100 * be passed to the 'open' emitter by array of GFile*'s.
101 * @par
102 * (c) If a Cgu::Application object is constructed with the
103 * G_APPLICATION_HANDLES_COMMAND_LINE flag set, then calling the
104 * Cgu::Application::run() method will cause the 'command_line'
105 * emitter to emit. All the command line parameters not handled
106 * locally in the new instance will be passed on, and they can be
107 * obtained via the GApplicationCommandLine argument of the
108 * 'command_line' emitter.
109 *
110 * Prior to glib-2.40/gtk-3.12 g_application_run() (and so
111 * Cgu::Application::run()) does not consume any recognised glib/gtk
112 * options such as \--display. Such options can be stripped out (and
113 * acted on by gtk) by calling gtk_init() before constructing the
114 * Cgu::Application object (but gtk_init() does not need to be called
115 * for any other purpose), or by using the GOptionGroup/GOptionEntry
116 * interface.
117 *
118 * There is no emitter provided for GApplication's 'shutdown' and
119 * 'handle-local-options' signals ('handle-local-options' is provided
120 * from glib-2.40 onwards). There is only very rarely a need to use
121 * the 'shutdown' signal in C++ code, which should not normally keep
122 * naked resources (the question whether clean-up on shutdown is
123 * needed is usually not just answered by whether we are in the first
124 * instance of the program to start, but whether particular state has
125 * accumulated in consequence of the program running, which is a
126 * question best answered by the object(s) managing the state, say on
127 * destruction on stack unwinding); but where the 'shutdown' signal is
128 * useful, GApplication's C level API is available via
129 * Cgu::Application::get_g_app(). If using 'handle-local-options' you
130 * will normally have hooked into local option handling using
131 * g_application_add_main_option_entries() or
132 * g_application_add_option_group(). In that case the option
133 * handling, including connecting where relevent to
134 * 'handle-local-options', is also best done at GApplication's C level
135 * by obtaining the GApplication object with
136 * Cgu::Application::get_g_app().
137 *
138 * There is little in this class that cannot also be done using the
139 * @ref prog_presenterAnchor "Cgu::prog_present" interface, which has
140 * the advantage of being more portable (@ref prog_presenterAnchor
141 * "Cgu::prog_present" does not depend on GTK-3 or GTK-4), but this
142 * class is more convenient to use where a program requires multiple
143 * main application windows which can be independently opened and any
144 * of which are to keep the program alive until the last one is
145 * closed, or if an application menu is to be provided for, say, the
146 * gnome shell.
147 *
148 * Cgu::Application objects are not singletons. It is possible to
149 * drop an Application object out of scope or destroy it in some other
150 * way after closing or removing all its windows, then construct
151 * another with a different flag and then call run() on the second one
152 * (although it would be a curious application that wanted to do so).
153 * It is also possible, but even more off-the-wall, to have two
154 * Application objects in existence in the same process at the same
155 * time provided different dbus identifiers are supplied to the
156 * constructor for each, although run() may only be called on one of
157 * them at any one time. However, this is something of a curiosity:
158 * in nearly all cases an application will only have one
159 * Cgu::Application object, since the main purpose of Cgu::Application
160 * is to facilitate single instance programs.
161 *
162 * Cgu::WinBase objects, and so Cgu::Application, can be used with
163 * widget heirarchies or top level windows created using GtkBuilder.
164 * See @ref GtkBuilder for particulars about that.
165 *
166 * Here is a compilable example, demonstrating the use of the
167 * GApplicationFlags options. It uses a GtkApplicationWindow object,
168 * as provided by GTK >= 3.4, so that it can provide an application
169 * menu for, say, the gnome shell. For earlier versions of GTK-3, the
170 * Message class can be constructed from a standard GtkWindow object,
171 * and the application and window menu code in the startup() callback
172 * can be omitted.
173 *
174 * @code
175 * #include <iostream>
176 * #include <ostream>
177 * #include <string>
178 * #include <list>
179 *
180 * #include <gtk/gtk.h>
181 *
182 * #include <c++-gtk-utils/callback.h>
183 * #include <c++-gtk-utils/application.h>
184 * #include <c++-gtk-utils/window.h>
185 * #include <c++-gtk-utils/shared_handle.h>
186 * #include <c++-gtk-utils/gobj_handle.h>
187 *
188 * // SETUP HERE: uncomment the flag to be tested:
189 *
190 * //const GApplicationFlags app_flag = G_APPLICATION_FLAGS_NONE;
191 * const GApplicationFlags app_flag = G_APPLICATION_HANDLES_OPEN;
192 * //const GApplicationFlags app_flag = G_APPLICATION_HANDLES_COMMAND_LINE;
193 *
194 * using namespace Cgu;
195 *
196 * // *** Demonstration Message class ***
197 *
198 * extern "C" void message_button_clicked(GtkWidget*, void*);
199 *
200 * class Message: public Cgu::WinBase {
201 * public:
202 * friend void message_button_clicked(GtkWidget*, void*);
203 * Message(const char* text, GApplication* app);
204 * };
205 *
206 * // *** for Message menu actions ***
207 *
208 * namespace {
209 * extern "C" {
210 * void win_beep(GSimpleAction*, GVariant*, void*) {
211 * gdk_beep();
212 * }
213 *
214 * GActionEntry win_entries[] = {
215 * { "beep", win_beep, NULL, NULL, NULL },
216 * };
217 * } // extern "C"
218 * } // unnamed namespace
219 *
220 * // *** Message callbacks ***
221 *
222 * void message_button_clicked(GtkWidget* w, void*) {
223 * std::cout << "Clicked" << std::endl;
224 * }
225 *
226 * // *** Message implementation ***
227 *
228 * Message::Message(const char* text, GApplication* app):
229 * WinBase{"Message", 0, false, 0,
230 * GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(app)))} {
231 * g_action_map_add_action_entries(G_ACTION_MAP(get_win()),
232 * win_entries,
233 * G_N_ELEMENTS(win_entries),
234 * static_cast<void*>(0));
235 * GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
236 * gtk_box_set_homogeneous(GTK_BOX(box), false);
237 * gtk_container_add(GTK_CONTAINER(get_win()), box);
238 * GtkWidget* label = gtk_label_new(text);
239 * gtk_box_pack_start(GTK_BOX(box), label,
240 * true, false, 0);
241 * GtkWidget* button_box = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
242 * gtk_box_pack_start(GTK_BOX(box), button_box,
243 * false, false, 0);
244 * GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_OK);
245 * gtk_container_add(GTK_CONTAINER(button_box), button);
246 * g_signal_connect(G_OBJECT(button), "clicked",
247 * G_CALLBACK(message_button_clicked), 0);
248 * gtk_widget_set_can_default(button, true);
249 * }
250 *
251 * namespace {
252 *
253 * // *** for application actions ***
254 *
255 * extern "C" {
256 * void app_beep(GSimpleAction*, GVariant*, void*) {
257 * gdk_beep();
258 * }
259 *
260 * void app_quit(GSimpleAction*, GVariant*, void* data) {
261 * Cgu::Application* app = static_cast<Cgu::Application*>(data);
262 * std::list<Cgu::WinBase*> wins = app->get_windows();
263 * for (auto iter = wins.begin(); iter != wins.end(); ++iter) {
264 * delete *iter; // this will also remove the Message object from
265 * // the Cgu::Application object
266 * }
267 * }
268 *
269 * GActionEntry app_entries[] = {
270 * { "beep", app_beep, NULL, NULL, NULL },
271 * { "quit", app_quit, NULL, NULL, NULL },
272 * };
273 * } // extern "C"
274 *
275 * // *** application callbacks ***
276 *
277 * void startup(Cgu::Application* app) {
278 * std::cout << "startup() called" << std::endl;
279 *
280 * g_action_map_add_action_entries(G_ACTION_MAP(app->get_g_app()),
281 * app_entries,
282 * G_N_ELEMENTS(app_entries),
283 * app);
284 * Cgu::GobjHandle<GMenu> app_menu{g_menu_new()};
285 * g_menu_append(app_menu, "Beep", "app.beep");
286 * g_menu_append(app_menu, "_Quit", "app.quit");
287 * gtk_application_set_app_menu(GTK_APPLICATION(app->get_g_app()),
288 * G_MENU_MODEL(app_menu.get()));
289 *
290 * Cgu::GobjHandle<GMenu> win_menu{g_menu_new()};
291 * Cgu::GobjHandle<GMenu> sub_menu{g_menu_new()};
292 * g_menu_append_submenu(win_menu, "Menu1", G_MENU_MODEL(sub_menu.get()));
293 * g_menu_append(sub_menu, "More beep", "win.beep"); // see Message::Message() for actions
294 * gtk_application_set_menubar(GTK_APPLICATION(app->get_g_app()),
295 * G_MENU_MODEL(win_menu.get()));
296 * }
297 *
298 * void activate(Cgu::Application* app) {
299 * std::cout << "activate() called" << std::endl;
300 *
301 * // probably if no arguments are passed, only one window is wanted,
302 * // which is now to present itself if it already exists: comment this
303 * // 'if' block out if a new window is to be added on each occasion
304 * // the program is started
305 * if (app->get_win_count() > 0) {
306 * gtk_window_present(app->get_windows().front()->get_win());
307 * return;
308 * }
309 * WinBase* dialog = new Message("This is a message", app->get_g_app());
310 * app->add(dialog);
311 * dialog->show_all();
312 * }
313 *
314 * void command_line(Cgu::Application* app, GApplicationCommandLine* cl, gint&) {
315 * std::cout << "command_line() called" << std::endl;
316 *
317 * // probably if the G_APPLICATION_HANDLES_COMMAND_LINE flag is set,
318 * // only one window is wanted, which is now to present itself if it
319 * // already exists: comment this 'if' block out if a new window is to
320 * // be added on each occasion the program is started
321 * if (app->get_win_count() > 0) {
322 * gtk_window_present(app->get_windows().front()->get_win());
323 * return;
324 * }
325 * std::string text("Command line options are:\n");
326 * int argc = 0;
327 * gchar** argv = g_application_command_line_get_arguments(cl, &argc);
328 * for (int count = 0; count < argc; ++count) {
329 * try {
330 * text += argv[count];
331 * text += '\n';
332 * }
333 * catch (...) {
334 * g_strfreev(argv);
335 * throw; // exceptions will be consumed by the callback handler and
336 * // a g_critical warning issued, but let's not leak memory
337 * }
338 * }
339 * g_strfreev(argv);
340 * WinBase* dialog = new Message(text.c_str(), app->get_g_app());
341 * app->add(dialog);
342 * dialog->show_all();
343 * }
344 *
345 * void open(Cgu::Application* app, std::pair<GFile**, gint> files, gchar*) {
346 * std::cout << "open() called" << std::endl;
347 *
348 * // probably if the G_APPLICATION_HANDLES_OPEN flag is set and an
349 * // argument is passed, the adding of a new window is wanted on each
350 * // occasion the program is started
351 * std::string text("Files are:\n");
352 * for (int count = 0; count < files.second; ++count) {
353 * GcharScopedHandle uri(g_file_get_uri(files.first[count]));
354 * text += uri;
355 * text += '\n';
356 * }
357 * WinBase* dialog = new Message(text.c_str(), app->get_g_app());
358 * app->add(dialog);
359 * dialog->show_all();
360 * }
361 *
362 * } // unnamed namespace
363 *
364 * // *** main() ***
365 *
366 * int main(int argc, char* argv[]) {
367 *
368 * // gtk_init() is only relevant for the purposes of stripping out
369 * // and acting on glib/gtk recognised options, either where
370 * // glib < 2.40 and gtk < 3.12 are used or where you want to pass
371 * // no arguments to Cgu::Application::run() when
372 * // G_APPLICATION_FLAGS_NONE is set in order to ensure that the
373 * // program does not abort with unrecognised options -
374 * // gtk_application_new() (and so the Cgu::Application constructor)
375 * // will call g_type_init() if the type system needs initialization
376 * gtk_init(&argc, &argv);
377 *
378 * Application app{"my_prog", app_flag};
379 * app.startup.connect(Callback::make(startup));
380 * app.activate.connect(Callback::make(activate));
381 * app.command_line.connect(Callback::make(command_line));
382 * app.open.connect(Callback::make(open));
383 * if (app_flag == G_APPLICATION_FLAGS_NONE)
384 * return app.run(0, 0);
385 * else
386 * return app.run(argc, argv);
387 * }
388 * @endcode
389 *
390 * One thing to note about this example is that the callbacks
391 * connected to the Cgu::Application object execute in the first
392 * instance of the program to be started (the instance in which
393 * Cgu::Application::run() blocks). If the program is then restarted,
394 * Cgu::Application::run() returns in the new program instance as soon
395 * as it has invoked the existing instance via dbus, following which
396 * the new program instance exits, so immediately disposing of the
397 * Cgu::Application object and callbacks which were constructed on the
398 * restart. This is a feature of GApplication/GtkApplication: given
399 * the overhead of starting a new process, and that restarting a
400 * single-instance program is in any event an exceptional event, any
401 * additional overhead created by constructing and then destroying the
402 * Cgu::Application object and callbacks in the new instance is
403 * trivial. (As mentioned above, from glib-2.40 the
404 * 'handle-local-options' signal can be used to hook into the
405 * GApplication object constructed in the new program instance, but
406 * this is intended to assist option parsing in the new instance.)
407 */
408
409 class Application {
410
411 std::list<WinBase*> win_list;
412 GobjHandle<GtkApplication> app;
413
414 void* reserved; // for future use
415 public:
416
417 typedef std::list<WinBase*>::size_type size_type;
418
419 /**
420 * This class cannot be copied. The copy constructor is deleted.
421 */
422 Application(const Application&) = delete;
423
424 /**
425 * This class cannot be copied. The assignment operator is deleted.
426 */
427 Application& operator=(const Application&) = delete;
428
429 /**
430 * This SafeEmitterArg object emits (and so executes any connected
431 * callback) when the underlying GApplication object emits its
432 * @a activate signal. The argument passed to the emitter's
433 * callback(s) is a pointer to the Cgu::Application object.
434 * @note When the callback executes, thread cancellation is blocked,
435 * and any exceptions are consumed with a g_critical message issued.
436 * The callback will always execute in the main GUI thread when
437 * executed in response to the run() method. Because a SafeEmitterArg
438 * object is used, the emitter object itself is thread safe.
439 *
440 * Since 2.0.0-rc2
441 */
442 Cgu::SafeEmitterArg<Cgu::Application*> activate;
443
444 /**
445 * This SafeEmitterArg object emits (and so executes any connected
446 * callback) when the underlying GApplication object emits its @a
447 * startup signal (which, unless the G_APPLICATION_NON_UNIQUE flag has
448 * been set in the Cgu::Application object's constructor, it will
449 * normally do once, on the first occasion that run() is called). The
450 * argument passed to the emitter's callback(s) is a pointer to the
451 * Cgu::Application object. This signal can be used to set up a
452 * desktop application menu, or a menu bar for WinBase objects
453 * constructed from a GtkApplicationWindow object.
454 * @note When the callback executes, thread cancellation is blocked,
455 * and any exceptions are consumed with a g_critical message issued.
456 * The callback will always execute in the main GUI thread when
457 * executed in response to the run() method. Because a SafeEmitterArg
458 * object is used, the emitter object itself is thread safe.
459 *
460 * Since 2.0.0-rc2
461 */
462 Cgu::SafeEmitterArg<Cgu::Application*> startup;
463
464 /**
465 * This SafeEmitterArg object emits (and so executes any connected
466 * callback) when the underlying GApplication object emits its
467 * @a command-line signal. The second argument passed to the
468 * emitter's callback(s) is the one passed by that signal, that is to
469 * say the arguments are:
470 *
471 * first: a pointer to the Cgu::Application object.
472 *
473 * second: a pointer to a GApplicationCommandLine object representing
474 * the passed command line (this is owned by gio and should not be
475 * unref'ed unless it has previously been explicitly ref'ed to keep
476 * the GApplicationCommandLine object alive even after the connected
477 * callback has returned).
478 *
479 * third: a gint& reference to which the value to be returned to the
480 * GApplication's command-line signal can be passed: if no value is
481 * assigned to it or no callback has been attached to the signal, 0
482 * will be returned, except that if an exception from a callback is
483 * consumed, -1 will be returned. If more than one callback is
484 * attached to the signal and no exception is consumed, the last one
485 * to assign a value will be have its value returned.
486 *
487 * @note When the callback executes, thread cancellation is blocked,
488 * and any exceptions are consumed with a g_critical message issued
489 * and a return value of -1 set. The callback will always execute in
490 * the main GUI thread when executed in response to the run() method.
491 * Because a SafeEmitterArg object is used, the emitter object itself
492 * is thread safe.
493 *
494 * Since 2.0.0-rc2
495 */
496 Cgu::SafeEmitterArg<Cgu::Application*, GApplicationCommandLine*, gint&> command_line;
497
498 /**
499 * This SafeEmitterArg object emits (and so executes any connected
500 * callback) when the underlying GApplication object emits its @a open
501 * signal. The second and third arguments passed to the emitter's
502 * callback(s) are those passed by that signal, that is to say the
503 * arguments are:
504 *
505 * first: a pointer to the Cgu::Application object.
506 *
507 * second: a std::pair object where the first member is an array of
508 * GFile*'s representing the files/uris passed as arguments, and the
509 * second member is the length of that array (the array is owned by
510 * gio and should not be freed).
511 *
512 * third: a gchar* argument comprising the text of the "hint" (this is
513 * owned by gio and should not be freed).
514 *
515 * @note When the callback executes, thread cancellation is blocked,
516 * and any exceptions are consumed with a g_critical message issued.
517 * The callback will always execute in the main GUI thread when
518 * executed in response to the run() method. Because a SafeEmitterArg
519 * object is used, the emitter object itself is thread safe.
520 *
521 * Since 2.0.0-rc2
522 */
523 Cgu::SafeEmitterArg<Cgu::Application*, std::pair<GFile**, gint>, gchar*> open;
524
525 /**
526 * Add a Cgu::WinBase object to the Cgu::Application object, and so
527 * also add its managed GtkWindow object to the GtkApplication object.
528 * Any Cgu::WinBase object passed to this method should not normally
529 * be modal and must have been constructed on free store with the new
530 * expression. It is passed by pointer because it will be self-owning
531 * (its lifetime would normally be determined by user action, not by
532 * the program), although if it is removed from this Cgu::Application
533 * object with remove(), the delete expression can (and normally
534 * should) be called on it. If a delete event occurs on the WinBase
535 * object so that the WinBase object destroys itself (say, by the user
536 * clicking on the window's close/delete button), or it destroys
537 * itself in some other way (say, by calling the WinBase::close()
538 * method), it will automatically be removed from this Application
539 * object without further action being necessary. The WinBase::exec()
540 * method should never be called on a WinBase object which has been
541 * added to an Application object. The Cgu::Application class, and
542 * thus this method, does not employ mutexes to make it thread safe,
543 * as there should never be a reason to call Cgu::Application methods
544 * in other than the main GUI thread.
545 * @param win The Cgu::WinBase object to be added.
546 * @exception std::bad_alloc This method might throw std::bad_alloc if
547 * memory is exhausted and the system throws in that case, in which
548 * case the WinBase object passed in will not be added. If such an
549 * exception is thrown and program recovery is to be attempted (which
550 * is usually a waste of time as glib/gtk will terminate the program
551 * if unable to obtain memory from the operating system), it would be
552 * best to delete the Cgu::WinBase object passed in and start again.
553 * An alternative is to show the window to the user for the user to
554 * dispose of (windows passed to this method are self-owning); but if
555 * that is done note that if the contained GtkWindow object is a
556 * GtkApplicationWindow object, then it will already be associated
557 * with a GtkApplication object when constructed, so it would usually
558 * be best also to call gtk_application_remove_window() on it via
559 * Cgu::Application::get_g_app() and Cgu::WinBase::get_win() before or
560 * after it is shown so the Cgu::Application and GtkApplication
561 * objects remain in sync.
562 * @note As well as this method only being called in the main GUI
563 * thread, if the program by which it is called calls GTK directly in
564 * more than one thread and thus employs
565 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
566 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
567 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
568 * a GTK signal handler. (The best approach however is for a program
569 * only to address GTK/GDK in the main program thread, for which
570 * purpose this library provides various functions and classes for
571 * inter-thread communication, such as Cgu::Notifier and
572 * Cgu::Callback::post(): see @ref Threading for particulars about
573 * GTK thread safety.)
574 *
575 * Since 2.0.0-rc2
576 */
577 void add(Cgu::WinBase* win);
578
579 /**
580 * Remove a Cgu::WinBase object from the Cgu::Application object, and
581 * so also remove its managed GtkWindow object from the GtkApplication
582 * object. This method will not throw assuming that merely iterating
583 * through a list does not throw (as it would not on any sane
584 * implementation). The Cgu::Application class, and thus this method,
585 * does not employ mutexes to make it thread safe, as there should
586 * never be a reason to call Cgu::Application methods in other than
587 * the main GUI thread. Calling this method does not destroy the
588 * WinBase object.
589 * @param win The Cgu::WinBase object to be removed.
590 * @return true if the Cgu::WinBase object was found in the
591 * Cgu::Application object and so removed, otherwise false.
592 * @note As well as this method only being called in the main GUI
593 * thread, if the program by which it is called calls GTK directly in
594 * more than one thread and thus employs
595 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
596 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
597 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
598 * a GTK signal handler. (The best approach however is for a program
599 * only to address GTK/GDK in the main program thread, for which
600 * purpose this library provides various functions and classes for
601 * inter-thread communication, such as Cgu::Notifier and
602 * Cgu::Callback::post(): see @ref Threading for particulars about
603 * GTK thread safety.)
604 *
605 * Since 2.0.0-rc2
606 */
607 bool remove(Cgu::WinBase* win);
608
609 /**
610 * Calls g_application_run() in respect of the underlying
611 * GtkApplication object, so invoking some of the Cgu::Application
612 * class's emitters (normally in the first instance of the program to
613 * be started): the exact behaviour depends on the GApplication flags
614 * passed to the constructor and is explained in the introductory
615 * remarks above. This method is thread safe (although that is
616 * irrelevant to its purpose) and will not throw. In addition, if a
617 * callback connected to an emitter throws, the exception is consumed
618 * and a g_critical warning issued. This function blocks until the
619 * last WinBase object associated with this Application object is
620 * destroyed or removed.
621 * @param argc The argc from main() or 0.
622 * @param argv The argv from main() or 0.
623 * @return The exit status from g_application_run().
624 *
625 * Since 2.0.0-rc2
626 */
627 int run(int argc, char** argv) {
628 return g_application_run((GApplication*)app.get(), argc, argv);
629 }
630
631 /**
632 * Get the underlying GApplication object (note, not the
633 * GtkApplication object, although the GApplication object can be cast
634 * to GtkApplication), so allowing any of gio's g_application_*()
635 * functions to be applied to it. In normal usage it will not be
636 * necessary to call this method. This method is thread safe and will
637 * not throw.
638 * @return The underlying GApplication object.
639 *
640 * Since 2.0.0-rc2
641 */
642 GApplication* get_g_app() const {return (GApplication*)app.get();}
643
644 /**
645 * Get the list of Cgu::WinBase objects associated with the
646 * application. The Cgu::Application class, and thus this method,
647 * does not employ mutexes to make it thread safe, as there should
648 * never be a reason to call Cgu::Application methods in other than
649 * the main GUI thread.
650 * @return A list of the top level Cgu::WinBase objects associated
651 * with the application, which will appear in the order in which they
652 * were added. If you need to access these, you will probably want to
653 * do a dynamic_cast or static_cast to the child type.
654 * @exception std::bad_alloc This method might throw std::bad_alloc if
655 * memory is exhausted and the system throws in that case.
656 *
657 * Since 2.0.0-rc2
658 */
659 std::list<Cgu::WinBase*> get_windows() const {return win_list;}
660
661 /**
662 * Gets the current count of Cgu::WinBase objects associated with this
663 * Cgu::Application object. When it reaches 0, the application will
664 * normally end (but this can be prevented by calling
665 * g_application_hold()/g_application_release() on the GApplication
666 * object returned by get_g_app()). This method can be used in the
667 * callback of one of this class's emitters to determine whether this
668 * is the first instance of a program to be started (assuming the
669 * first instance calls add() to bring up a window), because in that
670 * case it will return 0 until add() is called. Calling
671 * get_windows().size() will give the same result, but using this
672 * method is more efficient as it will avoid a copy of the list of
673 * windows. This method will not throw assuming that calling
674 * std::list::size() does not throw (as it would not on any sane
675 * implementation). The Cgu::Application class, and thus this method,
676 * does not employ mutexes to make it thread safe, as there should
677 * never be a reason to call Cgu::Application methods in other than
678 * the main GUI thread.
679 * @return The number of Cgu::WinBase objects currently associated
680 * with this Cgu::Application object.
681 *
682 * Since 2.0.0-rc2
683 */
684 size_type get_win_count() const {return win_list.size();}
685
686 /**
687 * This constructor will, via gtk_application_new(), cause
688 * g_type_init() to be called. If any GTK functions are to be called
689 * before an Application object is constructed, g_type_init() (or
690 * gtk_init()) must be called explicitly.
691 * @param prog_name An identifier name. This can comprise any valid
692 * ASCII characters "[A-Z][a-z][0-9]_-", although it is usually best
693 * to pass the program name. Unlike with gtk_application_new(), it
694 * does not need to comprise a full dbus bus name: this method will
695 * construct its own valid dbus bus name from prog_name in the org.cgu
696 * domain.
697 * @param flags The GApplicationFlags to be passed to the
698 * Cgu::Application object. This class does not contain its own
699 * sub-class of GApplication to customize this, but adopts the
700 * behaviour of GtkApplication. That behaviour is explained in the
701 * introductory remarks.
702 * @exception Cgu::ApplicationNameError This exception will be thrown
703 * if the prog_name parameter does not meet the requirements referred
704 * to above.
705 * @exception std::bad_alloc This method might throw std::bad_alloc if
706 * memory is exhausted and the system throws in that case.
707 *
708 * Since 2.0.0-rc2
709 */
710 Application(const char* prog_name, GApplicationFlags flags);
711
712 /**
713 * From version 2.0.0-rc3, as a safety feature the destructor removes
714 * any remaining WinBase objects associated with this Application
715 * object (this would only be relevant if the user constructs the
716 * Application object on free store, and then deletes it while the
717 * run() method is still blocking for the purpose of constructing a
718 * different Application object, but does not call the remove() method
719 * on all associated WinBase objects before doing so: constructing an
720 * Application object on free store in this way would be highly
721 * unusual however).
722 *
723 * Since 2.0.0-rc3
724 */
725 ~Application() {while (!win_list.empty()) remove(win_list.front());}
726
727 /* Only has effect if --with-glib-memory-slices-compat or
728 * --with-glib-memory-slices-no-compat option picked */
729 CGU_GLIB_MEMORY_SLICES_FUNCS
730 };
731
732 #endif // GTK_CHECK_VERSION
733 #endif // CGU_USE_GTK
734
735 } // namespace Cgu
736
737 #endif // CGU_APPLICATION_H
Cgu::Application::command_line
Cgu::SafeEmitterArg< Cgu::Application *, GApplicationCommandLine *, gint & > command_line
Definition: application.h:496
Cgu::WinBase
This is a class for managing the lifetime of top level widgets.
Definition: window.h:227
Cgu
Definition: application.h:44
Cgu::Application::Application
Application(const Application &)=delete
Cgu::Application::remove
bool remove(Cgu::WinBase *win)
Cgu::ApplicationNameError
This class is thrown when the program id name passed to the constructor of Cgu::Application is invali...
Definition: application.h:54
Cgu::Application::~Application
~Application()
Definition: application.h:725
Cgu::GobjHandle< GtkApplication >
Cgu::Application::open
Cgu::SafeEmitterArg< Cgu::Application *, std::pair< GFile **, gint >, gchar * > open
Definition: application.h:523
Cgu::Application
This is a class for constructing and managing GtkApplication objects.
Definition: application.h:409
Cgu::ApplicationNameError::what
virtual const char * what() const
Definition: application.h:55
Cgu::Application::add
void add(Cgu::WinBase *win)
Cgu::Application::startup
Cgu::SafeEmitterArg< Cgu::Application * > startup
Definition: application.h:462
gobj_handle.h
Cgu::Application::get_windows
std::list< Cgu::WinBase * > get_windows() const
Definition: application.h:659
Cgu::SafeEmitterArg< Cgu::Application * >
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Cgu::Application::get_win_count
size_type get_win_count() const
Definition: application.h:684
Cgu::Application::size_type
std::list< WinBase * >::size_type size_type
Definition: application.h:417
Cgu::Application::get_g_app
GApplication * get_g_app() const
Definition: application.h:642
window.h
Cgu::Application::run
int run(int argc, char **argv)
Definition: application.h:627
emitter.h
This file provides a thread-safe signal/slot mechanism, with automatic disconnection.
cgu_config.h
Cgu::Application::operator=
Application & operator=(const Application &)=delete
Cgu::Application::activate
Cgu::SafeEmitterArg< Cgu::Application * > activate
Definition: application.h:442
Cgu::GobjHandle::get
T * get() const noexcept
Definition: gobj_handle.h:292