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 installation, and if the library is not
65 * 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 * The gio/gtk+ documentation at the time of writing does not explain
78 * key concepts, and in particular how the GtkApplication sub-class
79 * interacts with GApplication's g_application_run(). Here is an
80 * explanation:
81 *
82 * @par
83 * (a) If a Cgu::Application object is constructed with the
84 * G_APPLICATION_FLAGS_NONE flag set, then calling the
85 * Cgu::Application::run() method (which hands off to
86 * g_application_run()) will cause the 'activate' emitter to emit. No
87 * command line parameter should be passed to the run method (argc
88 * should be 0 or 1), otherwise GtkApplication will cause the start-up
89 * to abort. Unlike with gtk_main(), g_application_run() (and so
90 * Cgu::Application::run()) does not consume any recognised glib/gtk+
91 * options, such as \--display, but regards these as application
92 * parameters. Such stripping out can be achieved by calling
93 * gtk_init() before constructing the Cgu::Application object (but
94 * gtk_init() does not need to be called for any other purpose), or by
95 * using the GOptionGroup/GOptionEntry interface.
96 * g_application_run(), and so Cgu::Application::run(), can be called
97 * with argc and argv set to 0, and that is generally the best
98 * approach if the G_APPLICATION_FLAGS_NONE flag is set.
99 * @par
100 * (b) If a Cgu::Application object is constructed with the
101 * G_APPLICATION_HANDLES_OPEN flag set, then calling the
102 * Cgu::Application::run() method will cause the 'activate' emitter to
103 * emit if no command line parameters were provided when the program
104 * was started (that is, if argc is 0 or 1), or cause the 'open'
105 * emitter to emit if parameters are passed (argc > 1). Such
106 * parameters will be construed as files/uris, and will be passed to
107 * the 'open' emitter by array of GFile*'s. Unlike with gtk_main(),
108 * g_application_run() (and so Cgu::Application::run()) does not
109 * consume any recognised glib/gtk+ options, such as \--display, but
110 * regards these as application parameters and so as file/uri names.
111 * Such stripping out can be achieved by calling gtk_init() before
112 * constructing the Cgu::Application object (but gtk_init() does not
113 * need to be called for any other purpose), or by using the
114 * GOptionGroup/GOptionEntry interface.
115 * @par
116 * (c) If a Cgu::Application object is constructed with the
117 * G_APPLICATION_HANDLES_COMMAND_LINE flag set, then calling the
118 * Cgu::Application::run() method will cause the 'command_line'
119 * emitter to emit. All the command line parameters will be passed
120 * on, and they can be obtained via the GApplicationCommandLine
121 * argument of the 'command_line' emitter. Unlike with gtk_main(),
122 * g_application_run() (and so Cgu::Application::run()) does not
123 * consume any recognised glib/gtk+ options, such as \--display, but
124 * regards these as command line parameters. Such stripping out can
125 * be achieved by calling gtk_init() before constructing the
126 * Cgu::Application object (but gtk_init() does not need to be called
127 * for any other purpose), or by using the GOptionGroup/GOptionEntry
128 * interface.
129 *
130 * There is little in this class that cannot also be done using the
131 * @ref prog_presenterAnchor "Cgu::prog_present" interface, which has
132 * the advantage of being more portable (@ref prog_presenterAnchor
133 * "Cgu::prog_present" does not depend on GTK+3), but this class is
134 * more convenient to use where a program requires multiple main
135 * application windows which can be independently opened and any of
136 * which are to keep the program alive until the last one is closed.
137 *
138 * Cgu::Application objects are not singletons. It is possible to
139 * drop an Application object out of scope or destroy it in some other
140 * way after closing or removing all its windows, then construct
141 * another with a different flag and then call run() on the second one
142 * (although it would be a curious application that wanted to do so).
143 * It is also possible, but even more off-the-wall, to have two
144 * Application objects in existence in the same process at the same
145 * time provided different dbus identifiers are supplied to the
146 * constructor for each, although run() may only be called on one of
147 * them at any one time. However, this is something of a curiosity:
148 * in nearly all cases an application will only have one
149 * Cgu::Application object, since the main purpose of Cgu::Application
150 * is to facilitate single instance programs.
151 *
152 * Cgu::WinBase objects, and so Cgu::Application, can be used with
153 * widget heirarchies or top level windows created using GtkBuilder.
154 * See @ref GtkBuilder for particulars about that.
155 *
156 * Here is a compilable example, demonstrating the use of the
157 * GApplicationFlags options. It uses a GtkApplicationWindow object,
158 * as provided by GTK+ >= 3.4, so that it can provide an application
159 * menu for, say, the gnome shell. For earlier versions of GTK+-3,
160 * the Message class can be constructed from a standard GtkWindow
161 * object, and the application menu code in the startup() callback can
162 * be omitted.
163 *
164 * @code
165 * #include <iostream>
166 * #include <ostream>
167 * #include <string>
168 * #include <list>
169 *
170 * #include <gtk/gtk.h>
171 *
172 * #include <c++-gtk-utils/callback.h>
173 * #include <c++-gtk-utils/application.h>
174 * #include <c++-gtk-utils/window.h>
175 * #include <c++-gtk-utils/shared_handle.h>
176 * #include <c++-gtk-utils/gobj_handle.h>
177 *
178 * // SETUP HERE: uncomment the flag to be tested:
179 *
180 * //const GApplicationFlags app_flag = G_APPLICATION_FLAGS_NONE;
181 * const GApplicationFlags app_flag = G_APPLICATION_HANDLES_OPEN;
182 * //const GApplicationFlags app_flag = G_APPLICATION_HANDLES_COMMAND_LINE;
183 *
184 * using namespace Cgu;
185 *
186 * // *** Demonstration message class ***
187 *
188 * extern "C" void message_button_clicked(GtkWidget*, void*);
189 *
190 * class Message: public Cgu::WinBase {
191 * public:
192 * friend void message_button_clicked(GtkWidget*, void*);
193 * Message(const char* text);
194 * };
195 *
196 * void message_button_clicked(GtkWidget* w, void*) {
197 * std::cout << "Clicked" << std::endl;
198 * }
199 *
200 * Message::Message(const char* text, GApplication* app):
201 * WinBase{"Message", 0, false, 0,
202 * GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(app)))} {
203 * GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
204 * gtk_box_set_homogeneous(GTK_BOX(box), false);
205 * gtk_container_add(GTK_CONTAINER(get_win()), box);
206 * GtkWidget* label = gtk_label_new(text);
207 * gtk_box_pack_start(GTK_BOX(box), label,
208 * true, false, 0);
209 * GtkWidget* button_box = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
210 * gtk_box_pack_start(GTK_BOX(box), button_box,
211 * false, false, 0);
212 * GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_OK);
213 * gtk_container_add(GTK_CONTAINER(button_box), button);
214 * g_signal_connect(G_OBJECT(button), "clicked",
215 * G_CALLBACK(message_button_clicked), 0);
216 * gtk_widget_set_can_default(button, true);
217 * }
218 *
219 * namespace {
220 *
221 * // *** for GtkApplicationWindow actions ***
222 *
223 * void beep_app(GSimpleAction*, GVariant*, void*) {
224 * gdk_beep();
225 * }
226 *
227 * void quit_app(GSimpleAction*, GVariant*, void* data) {
228 * Cgu::Application* app = static_cast<Cgu::Application*>(data);
229 * std::list<Cgu::WinBase*> wins = app->get_windows();
230 * for (auto iter = wins.begin(); iter != wins.end(); ++iter) {
231 * delete *iter; // this will also remove the Message object from
232 * // the Cgu::Application object
233 * }
234 * }
235 *
236 * GActionEntry app_entries[] = {
237 * { "beep", beep_app, NULL, NULL, NULL },
238 * { "quit", quit_app, NULL, NULL, NULL },
239 * };
240 *
241 * // *** callbacks ***
242 *
243 * void startup(Cgu::Application* app) {
244 * std::cout << "startup() called" << std::endl;
245 *
246 * g_action_map_add_action_entries(G_ACTION_MAP(app->get_g_app()),
247 * app_entries,
248 * G_N_ELEMENTS(app_entries),
249 * app);
250 *
251 * Cgu::GobjHandle<GMenu> menu{g_menu_new()};
252 * g_menu_append(menu, "Beep", "app.beep");
253 * g_menu_append(menu, "_Quit", "app.quit");
254 * gtk_application_set_app_menu(GTK_APPLICATION(app->get_g_app()),
255 * G_MENU_MODEL(menu.get()));
256 * }
257 *
258 * void activate(Cgu::Application* app) {
259 * std::cout << "activate() called" << std::endl;
260 *
261 * // probably if no arguments are passed, only one window is wanted,
262 * // which is now to present itself if it already exists: comment this
263 * // 'if' block out if a new window is to be added on each occasion
264 * // the program is started
265 * if (app->get_win_count() > 0) {
266 * gtk_window_present(app->get_windows().front()->get_win());
267 * return;
268 * }
269 * WinBase* dialog = new Message("This is a message", app->get_g_app());
270 * app->add(dialog);
271 * dialog->show_all();
272 * }
273 *
274 * void command_line(Cgu::Application* app, GApplicationCommandLine* cl, gint&) {
275 * std::cout << "command_line() called" << std::endl;
276 *
277 * // probably if the G_APPLICATION_HANDLES_COMMAND_LINE flag is set,
278 * // only one window is wanted, which is now to present itself if it
279 * // already exists: comment this 'if' block out if a new window is to
280 * // be added on each occasion the program is started
281 * if (app->get_win_count() > 0) {
282 * gtk_window_present(app->get_windows().front()->get_win());
283 * return;
284 * }
285 * std::string text("Command line options are:\n");
286 * int argc = 0;
287 * gchar** argv = g_application_command_line_get_arguments(cl, &argc);
288 * for (int count = 0; count < argc; ++count) {
289 * try {
290 * text += argv[count];
291 * text += '\n';
292 * }
293 * catch (...) {
294 * g_strfreev(argv);
295 * throw; // exceptions will be consumed by the callback handler and
296 * // a g_critical warning issued, but let's not leak memory
297 * }
298 * }
299 * g_strfreev(argv);
300 * WinBase* dialog = new Message(text.c_str(), app->get_g_app()));
301 * app->add(dialog);
302 * dialog->show_all();
303 * }
304 *
305 * void open(Cgu::Application* app, std::pair<GFile**, gint> files, gchar*) {
306 * std::cout << "open() called" << std::endl;
307 *
308 * // probably if the G_APPLICATION_HANDLES_OPEN flag is set and an
309 * // argument is passed, the adding of a new window is wanted on each
310 * // occasion the program is started
311 * std::string text("Files are:\n");
312 * for (int count = 0; count < files.second; ++count) {
313 * GcharScopedHandle uri(g_file_get_uri(files.first[count]));
314 * text += uri;
315 * text += '\n';
316 * }
317 * WinBase* dialog = new Message(text.c_str(), app->get_g_app()));
318 * app->add(dialog);
319 * dialog->show_all();
320 * }
321 *
322 * } // unnamed namespace
323 *
324 * // *** main() ***
325 *
326 * int main(int argc, char* argv[]) {
327 *
328 * // gtk_init() is only relevant for the purposes of stripping out
329 * // glib/gtk+ recognised options - gtk_application_new() (and so the
330 * // Cgu::Application constructor) will call g_type_init() if the type
331 * // system needs initialization
332 * gtk_init(&argc, &argv);
333 *
334 * Application app{"my_prog", app_flag};
335 * app.activate.connect(Callback::make(activate));
336 * app.startup.connect(Callback::make(startup));
337 * app.command_line.connect(Callback::make(command_line));
338 * app.open.connect(Callback::make(open));
339 * if (app_flag == G_APPLICATION_FLAGS_NONE)
340 * app.run(0, 0);
341 * else
342 * app.run(argc, argv);
343 *
344 * return 0;
345 * }
346 * @endcode
347 *
348 * One thing to note about this example is that the callbacks
349 * connected to the Cgu::Application object always execute in the
350 * first instance of the program to be started (the instance in which
351 * Cgu::Application::run() blocks). If the program is then restarted,
352 * Cgu::Application::run() returns in the new program instance as soon
353 * as it has invoked the existing instance via dbus, following which
354 * the new program instance exits, so immediately disposing of the
355 * Cgu::Application object and callbacks which were constructed on the
356 * restart. This is a feature of GApplication/GtkApplication: given
357 * the overhead of starting a new process, and that restarting a
358 * single-instance program is in any event an exceptional event, any
359 * additional overhead created by constructing and then destroying the
360 * Cgu::Application object and callbacks in the new instance is
361 * trivial.
362 */
363
364 class Application {
365
366 std::list<WinBase*> win_list;
367 GobjHandle<GtkApplication> app;
368
369 void* reserved; // for future use
370 public:
371
372 typedef std::list<WinBase*>::size_type size_type;
373
374 /**
375 * This class cannot be copied. The copy constructor is deleted.
376 */
377 Application(const Application&) = delete;
378
379 /**
380 * This class cannot be copied. The assignment operator is deleted.
381 */
382 Application& operator=(const Application&) = delete;
383
384 /**
385 * This SafeEmitterArg object emits (and so executes any connected
386 * callback) when the underlying GApplication object emits its
387 * @a activate signal. The argument passed to the emitter's
388 * callback(s) is a pointer to the Cgu::Application object.
389 * @note When the callback executes, thread cancellation is blocked,
390 * and any exceptions are consumed with a g_critical message issued.
391 * The callback will always execute in the main GUI thread when
392 * executed in response to the run() method. Because a SafeEmitterArg
393 * object is used, the emitter object itself is thread safe.
394 *
395 * Since 2.0.0-rc2
396 */
397 Cgu::SafeEmitterArg<Cgu::Application*> activate;
398
399 /**
400 * This SafeEmitterArg object emits (and so executes any connected
401 * callback) when the underlying GApplication object emits its @a
402 * startup signal (which it will do once, on the first occasion that
403 * run() is called). The argument passed to the emitter's callback(s)
404 * is a pointer to the Cgu::Application object. This signal can be
405 * used to set up a desktop application menu or menu bar with a
406 * WinBase object constructed from a GtkApplicationWindow object.
407 * @note When the callback executes, thread cancellation is blocked,
408 * and any exceptions are consumed with a g_critical message issued.
409 * The callback will always execute in the main GUI thread when
410 * executed in response to the run() method. Because a SafeEmitterArg
411 * object is used, the emitter object itself is thread safe.
412 *
413 * Since 2.0.0-rc2
414 */
415 Cgu::SafeEmitterArg<Cgu::Application*> startup;
416
417 /**
418 * This SafeEmitterArg object emits (and so executes any connected
419 * callback) when the underlying GApplication object emits its
420 * @a command-line signal. The second argument passed to the
421 * emitter's callback(s) is the one passed by that signal, that is to
422 * say the arguments are:
423 *
424 * first: a pointer to the Cgu::Application object.
425 *
426 * second: a pointer to a GApplicationCommandLine object representing
427 * the passed command line (this is owned by gio and should not be
428 * unref'ed).
429 *
430 * third: a gint& reference to which the value to be returned to the
431 * GApplication's command-line signal can be passed: if no value is
432 * assigned to it or no callback has been attached to the signal, 0
433 * will be returned, except that if an exception from a callback is
434 * consumed, -1 will be returned. If more than one callback is
435 * attached to the signal and no exception is consumed, the last one
436 * to assign a value will be have its value returned.
437 *
438 * @note When the callback executes, thread cancellation is blocked,
439 * and any exceptions are consumed with a g_critical message issued
440 * and a return value of -1 set. The callback will always execute in
441 * the main GUI thread when executed in response to the run() method.
442 * Because a SafeEmitterArg object is used, the emitter object itself
443 * is thread safe.
444 *
445 * Since 2.0.0-rc2
446 */
447 Cgu::SafeEmitterArg<Cgu::Application*, GApplicationCommandLine*, gint&> command_line;
448
449 /**
450 * This SafeEmitterArg object emits (and so executes any connected
451 * callback) when the underlying GApplication object emits its @a open
452 * signal. The second and third arguments passed to the emitter's
453 * callback(s) are those passed by that signal, that is to say the
454 * arguments are:
455 *
456 * first: a pointer to the Cgu::Application object.
457 *
458 * second: a std::pair object where the first member is an array of
459 * GFile*'s representing the files/uris passed as arguments, and the
460 * second member is the length of that array (the array is owned by
461 * gio and should not be freed).
462 *
463 * third: a gchar* argument comprising the text of the "hint" (this is
464 * owned by gio and should not be freed).
465 *
466 * @note When the callback executes, thread cancellation is blocked,
467 * and any exceptions are consumed with a g_critical message issued.
468 * The callback will always execute in the main GUI thread when
469 * executed in response to the run() method. Because a SafeEmitterArg
470 * object is used, the emitter object itself is thread safe.
471 *
472 * Since 2.0.0-rc2
473 */
474 Cgu::SafeEmitterArg<Cgu::Application*, std::pair<GFile**, gint>, gchar*> open;
475
476 /**
477 * Add a Cgu::WinBase object to the Cgu::Application object, and so
478 * also add its managed GtkWindow object to the GtkApplication object.
479 * Any Cgu::WinBase object passed to this method should not normally
480 * be modal and must have been constructed on free store with the new
481 * expression, and will be self owning, although if it is removed from
482 * this Cgu::Application object with remove(), the delete expression
483 * can (and normally should) be called on it. If a delete event
484 * occurs on the WinBase object so that the WinBase object destroys
485 * itself (say, by clicking on the window's close/delete button), or
486 * it destroys itself in some other way (say, by calling the
487 * WinBase::close() method), it will automatically be removed from
488 * this Application object without further action being necessary.
489 * The WinBase::exec() method should never be called on a WinBase
490 * object which has been added to an Application object. The
491 * Cgu::Application class, and thus this method, does not employ
492 * mutexes to make it thread safe, as there should never be a reason
493 * to call Cgu::Application methods in other than the main GUI thread.
494 * @param win The Cgu::WinBase object to be added.
495 * @exception std::bad_alloc This method might throw std::bad_alloc if
496 * memory is exhausted and the system throws in that case.
497 * @note As well as this method only being called in the main GUI
498 * thread, if the program by which it is called calls GTK+ directly in
499 * more than one thread and thus employs
500 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
501 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
502 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
503 * a GTK+ signal handler. (The best approach however is for a program
504 * only to address GTK+/GDK in the main program thread, for which
505 * purpose this library provides various functions and classes for
506 * inter-thread communication, such as Cgu::Notifier and
507 * Cgu::Callback::post(): see @ref Threading for particulars about
508 * GTK+ thread safety.)
509 *
510 * Since 2.0.0-rc2
511 */
512 void add(Cgu::WinBase* win);
513
514 /**
515 * Remove a Cgu::WinBase object from the Cgu::Application object, and
516 * so also remove its managed GtkWindow object from the GtkApplication
517 * object. This method will not throw assuming that merely iterating
518 * through a list does not throw (as it would not on any sane
519 * implementation). The Cgu::Application class, and thus this method,
520 * does not employ mutexes to make it thread safe, as there should
521 * never be a reason to call Cgu::Application methods in other than
522 * the main GUI thread. Calling this method does not destroy the
523 * WinBase object.
524 * @param win The Cgu::WinBase object to be removed.
525 * @return true if the Cgu::WinBase object was found in the
526 * Cgu::Application object and so removed, otherwise false.
527 * @note As well as this method only being called in the main GUI
528 * thread, if the program by which it is called calls GTK+ directly in
529 * more than one thread and thus employs
530 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
531 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
532 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
533 * a GTK+ signal handler. (The best approach however is for a program
534 * only to address GTK+/GDK in the main program thread, for which
535 * purpose this library provides various functions and classes for
536 * inter-thread communication, such as Cgu::Notifier and
537 * Cgu::Callback::post(): see @ref Threading for particulars about
538 * GTK+ thread safety.)
539 *
540 * Since 2.0.0-rc2
541 */
542 bool remove(Cgu::WinBase* win);
543
544 /**
545 * Calls g_application_run() in respect of the underlying
546 * GtkApplication object, so invoking one of this Cgu::Application
547 * class's emitters (the exact behaviour depends on the GApplication
548 * flags passed to the constructor and is explained in the
549 * introductory remarks above). This method is thread safe (although
550 * that is irrelevant to its purpose) and will not throw. In
551 * addition, if a callback connected to an emitter throws, the
552 * exception is consumed and a g_critical warning issued. This
553 * function blocks until the last WinBase object associated with this
554 * Application object is destroyed or removed.
555 * @param argc The argc from main() or 0.
556 * @param argv The argv from main() or 0.
557 * @return The exit status from g_application_run().
558 *
559 * Since 2.0.0-rc2
560 */
561 int run(int argc, char** argv) {
562 return g_application_run((GApplication*)app.get(), argc, argv);
563 }
564
565 /**
566 * Get the underlying GApplication object (note, not the
567 * GtkApplication object, although the GApplication object can be cast
568 * to GtkApplication), so allowing any of gio's g_application_*()
569 * functions to be applied to it. In normal usage it will not be
570 * necessary to call this method. This method is thread safe and will
571 * not throw.
572 * @return The underlying GApplication object.
573 *
574 * Since 2.0.0-rc2
575 */
576 GApplication* get_g_app() const {return (GApplication*)app.get();}
577
578 /**
579 * Get the list of Cgu::WinBase objects associated with the
580 * application. The Cgu::Application class, and thus this method,
581 * does not employ mutexes to make it thread safe, as there should
582 * never be a reason to call Cgu::Application methods in other than
583 * the main GUI thread.
584 * @return A list of the top level Cgu::WinBase objects associated
585 * with the application, which will appear in the order in which they
586 * were added. If you need to access these, you will probably want to
587 * do a dynamic_cast or static_cast to the child type.
588 * @exception std::bad_alloc This method might throw std::bad_alloc if
589 * memory is exhausted and the system throws in that case.
590 *
591 * Since 2.0.0-rc2
592 */
593 std::list<Cgu::WinBase*> get_windows() const {return win_list;}
594
595 /**
596 * Gets the current count of Cgu::WinBase objects associated with this
597 * Cgu::Application object. When it reaches 0, the application will
598 * normally end (but this can be prevented by calling
599 * g_application_hold()/g_application_release() on the GApplication
600 * object returned by get_g_app()). This method can be used in the
601 * callback of one of this class's emitters to determine whether this
602 * is the first instance of a program to be started (assuming the
603 * first instance calls add() to bring up a window), because in that
604 * case it will return 0 until add() is called. Calling
605 * get_windows().size() will give the same result, but using this
606 * method is more efficient as it will avoid a copy of the list of
607 * windows. This method will not throw assuming that calling
608 * std::list::size() does not throw (as it would not on any sane
609 * implementation). The Cgu::Application class, and thus this method,
610 * does not employ mutexes to make it thread safe, as there should
611 * never be a reason to call Cgu::Application methods in other than
612 * the main GUI thread.
613 * @return The number of Cgu::WinBase objects currently associated
614 * with this Cgu::Application object.
615 *
616 * Since 2.0.0-rc2
617 */
618 size_type get_win_count() const {return win_list.size();}
619
620 /**
621 * This constructor will, via gtk_application_new(), cause
622 * g_type_init() to be called. If any GTK+ functions are to be called
623 * before an Application object is constructed, g_type_init() (or
624 * gtk_init()) must be called explicitly.
625 * @param prog_name An identifier name. This can comprise any valid
626 * ASCII characters "[A-Z][a-z][0-9]_-", although it is usually best
627 * to pass the program name. Unlike with gtk_application_new(), it
628 * does not need to comprise a full dbus bus name: this method will
629 * construct its own valid dbus bus name from prog_name in the org.cgu
630 * domain.
631 * @param flags The GApplicationFlags to be passed to the
632 * Cgu::Application object. This class does not contain its own
633 * sub-class of GApplication to customize this, but adopts the
634 * behaviour of GtkApplication. That behaviour is explained in the
635 * introductory remarks.
636 * @exception Cgu::ApplicationNameError This exception will be thrown
637 * if the prog_name parameter does not meet the requirements referred
638 * to above.
639 * @exception std::bad_alloc This method might throw std::bad_alloc if
640 * memory is exhausted and the system throws in that case.
641 *
642 * Since 2.0.0-rc2
643 */
644 Application(const char* prog_name, GApplicationFlags flags);
645
646 /**
647 * From version 2.0.0-rc3, as a safety feature the destructor removes
648 * any remaining WinBase objects associated with this Application
649 * object (this would only be relevant if the user constructs the
650 * Application object on free store, and then deletes it while the
651 * run() method is still blocking for the purpose of constructing a
652 * different Application object, but does not call the remove() method
653 * on all associated WinBase objects before doing so: constructing an
654 * Application object on free store in this way would be highly
655 * unusual however).
656 *
657 * Since 2.0.0-rc3
658 */
659 ~Application() {while (!win_list.empty()) remove(win_list.front());}
660
661 /* Only has effect if --with-glib-memory-slices-compat or
662 * --with-glib-memory-slices-no-compat option picked */
663 CGU_GLIB_MEMORY_SLICES_FUNCS
664 };
665
666 #endif // GTK_CHECK_VERSION
667 #endif // CGU_USE_GTK
668
669 } // namespace Cgu
670
671 #endif // CGU_APPLICATION_H