/* Copyright (C) 2007 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
_CONFIGINCLUDE(giommconfig.h)
#include <giomm/actiongroup.h>
#include <giomm/actionmap.h>
#include <giomm/applicationcommandline.h>
#include <giomm/file.h>
#include <glibmm/object.h>
#include <glibmm/optionentry.h>
#include <glibmm/optiongroup.h>
#include <glibmm/variant.h>
#include <glibmm/variantdict.h>
#include <giomm/dbusconnection.h>
#include <giomm/notification.h>
_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)
namespace Gio
{
_WRAP_ENUM(ApplicationFlags, GApplicationFlags, NO_GTYPE)
/** Application - Core application class.
* An Application is the foundation of an application, unique for a given
* application identifier. The Application class wraps some low-level
* platform-specific services and is intended to act as the foundation for
* higher-level application classes such as Gtk::Application or MxApplication.
* In general, you should not use this class outside of a higher level
* framework.
*
* One of the core features that Application provides is process uniqueness,
* in the context of a "session". The session concept is platform-dependent,
* but corresponds roughly to a graphical desktop login. When your application
* is launched again, its arguments are passed through platform communication
* to the already running program. The already running instance of the program
* is called the <i>primary instance</i>.
*
* Before using Application, you must choose an "application identifier". The
* expected form of an application identifier is very close to that of of a
* <a href="
* http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface">DBus
* bus name</a>. Examples include: "com.example.MyApp",
* "org.example.internal-apps.Calculator". For details on valid application
* identifiers, see id_is_valid().
*
* Application provides convenient life cycle management by maintaining a
* <i>use count</i> for the primary application instance. The use count can be
* changed using hold() and release(). If it drops to zero, the application
* exits.
*
* Application also implements the ActionGroup and ActionMap
* interfaces and lets you easily export actions by adding them with
* Gio::ActionMap::add_action(). When invoking an action by calling
* Gio::ActionGroup::activate_action() on the application, it is always
* invoked in the primary instance.
*
* There is a number of different entry points into an Application:
*
* - via 'Activate' (i.e. just starting the application)
* - via 'Open' (i.e. opening some files)
* - via activating an action
*
* The signal_startup() signal lets you handle the application initialization
* for all of these in a single place.
*
* See the C API docs for an example.
*
* @newin{2,32}
*/
class Application : public Glib::Object, public ActionGroup, public ActionMap
{
_CLASS_GOBJECT(Application, GApplication, G_APPLICATION, Glib::Object, GObject)
_IMPLEMENTS_INTERFACE(ActionGroup)
_IMPLEMENTS_INTERFACE(ActionMap)
protected:
/** Constructs an application instance.
* If no application ID is given then some features (most notably application uniqueness) will be disabled.
*
* @param application_id The application ID.
* @param flags The application flags.
*/
explicit Application(const Glib::ustring& application_id = Glib::ustring(), ApplicationFlags flags = APPLICATION_FLAGS_NONE);
_IGNORE(g_application_new)
public:
_CUSTOM_DTOR()
/** The OptionType enum values determine the expected type of a command line option.
* If an option expects an extra argument, it can be specified in several ways;
* with a short option: "-x arg", with a long option: "--name arg" or combined
* in a single argument: "--name=arg". All option types except OPTION_TYPE_BOOL
* expect an extra argument. OPTION_TYPE_STRING_VECTOR and
* OPTION_TYPE_FILENAME_VECTOR accept more than one extra argument.
*
* The descriptions of the enum values show what type of Glib::Variant<>
* is stored in a Glib::VariantDict.
*
* @newin{2,42}
*
* @ingroup glibmmEnums
*/
enum OptionType
{
OPTION_TYPE_BOOL, ///< bool
OPTION_TYPE_STRING, ///< Glib::ustring
OPTION_TYPE_INT, ///< gint32
//OPTION_TYPE_CALLBACK,
OPTION_TYPE_FILENAME = OPTION_TYPE_INT+2, ///< std::string
OPTION_TYPE_STRING_VECTOR, ///< std::vector<Glib::ustring>
OPTION_TYPE_FILENAME_VECTOR, ///< std::vector<std::string>
OPTION_TYPE_DOUBLE, ///< double
OPTION_TYPE_INT64 ///< gint64
};
/** Creates an application instance.
* If no application ID is given then some features (most notably application uniqueness) will be disabled.
*
* @param application_id The application ID.
* @param flags The application flags.
*/
_WRAP_CREATE(const Glib::ustring& application_id = Glib::ustring(), ApplicationFlags flags = APPLICATION_FLAGS_NONE)
_WRAP_METHOD(static bool id_is_valid(const Glib::ustring& application_id), g_application_id_is_valid)
_WRAP_METHOD(Glib::ustring get_id() const, g_application_get_application_id)
_WRAP_METHOD(void set_id(const Glib::ustring& application_id), g_application_set_application_id)
_WRAP_METHOD(Glib::RefPtr<DBus::Connection> get_dbus_connection(), g_application_get_dbus_connection, refreturn)
_WRAP_METHOD(Glib::RefPtr<const DBus::Connection> get_dbus_connection() const, g_application_get_dbus_connection, refreturn, constversion)
_WRAP_METHOD(Glib::ustring get_dbus_object_path() const, g_application_get_dbus_object_path)
_WRAP_METHOD(guint get_inactivity_timeout() const, g_application_get_inactivity_timeout)
_WRAP_METHOD(void set_inactivity_timeout(guint inactivity_timeout), g_application_set_inactivity_timeout)
_WRAP_METHOD(ApplicationFlags get_flags() const, g_application_get_flags)
_WRAP_METHOD(void set_flags(ApplicationFlags flags), g_application_set_flags)
_WRAP_METHOD(std::string get_resource_base_path() const, g_application_get_resource_base_path, newin "2,44")
_WRAP_METHOD(void set_resource_base_path(const std::string& resource_path), g_application_set_resource_base_path, newin "2,44")
/** Disable automatic resource loading functionality.
* See set_resource_base_path().
* @newin{2,44}
*/
void unset_resource_base_path();
_WRAP_METHOD(void set_action_group(const Glib::RefPtr<ActionGroup>& action_group), g_application_set_action_group,
deprecated "Use the Gio::ActionMap interface instead.")
//Note: We would like to add a group, not just some entries,
//so we can do pre and post parsing. See https://bugzilla.gnome.org/show_bug.cgi?id=727602
//but instead we need to use the VariantDict passed to the handle_local_options signal
//and provided by ApplicationCommandLine::get_options_dict() in on_command_line().
/** Adds a main option entry to be handled by the Application.
*
* This function is comparable to Glib::OptionGroup::add_entry() +
* Glib::OptionContext::set_main_group().
*
* After the commandline arguments are parsed, the
* signal_handle_local_options() signal will be emitted. At this
* point, the application can inspect the parsed values.
*
* Unlike OptionGroup + OptionContext, Application packs the arguments
* into a Glib::VariantDict which is passed to the
* signal_handle_local_options() handler, where it can be
* inspected and modified. If Gio::APPLICATION_HANDLES_COMMAND_LINE is
* set, then the resulting dictionary is sent to the primary instance,
* where Gio::ApplicationCommandLine::get_options_dict() will return it.
* This "packing" is done according to the type of the argument --
* booleans for normal flags, Glib::ustring's for strings, std::string's for
* filenames, etc. The packing only occurs if the flag is given (ie: we
* do not pack a "false" Variant in the case that a flag is missing).
*
* In general, it is recommended that all commandline arguments are
* parsed locally. The options dictionary should then be used to
* transmit the result of the parsing to the primary instance, where
* Glib::VariantDict::lookup_value() can be used. For local options, it is
* possible to consult (and potentially remove) the option from the options dictionary.
*
* This function is new in GLib 2.40. Before then, the only real choice
* was to send all of the commandline arguments (options and all) to the
* primary instance for handling. Application ignored them completely
* on the local side. Calling this function "opts in" to the new
* behaviour, and in particular, means that unrecognised options will be
* treated as errors. Unrecognised options have never been ignored when
* Gio::APPLICATION_HANDLES_COMMAND_LINE is unset.
*
* If signal_handle_local_options() needs to see the list of
* filenames, then the use of G_OPTION_REMAINING as @a long_name is recommended.
* G_OPTION_REMAINING can be used as a key into
* the options dictionary. If you do use G_OPTION_REMAINING then you
* need to handle these arguments for yourself because once they are
* consumed, they will no longer be visible to the default handling
* (which treats them as filenames to be opened).
*
* @newin{2,42}
*
* @param arg_type A Gio::Application::OptionType.
* @param long_name The long name of an option can be used to specify it
* in a commandline as `--long_name`. Every option must have a
* long name.
* @param short_name If an option has a short name, it can be specified
* `-short_name` in a commandline. @a short_name must be a printable
* ASCII character different from '-', or '\0' if the option has no
* short name.
* @param description The description for the option in `--help` output.
* @param arg_description The placeholder to use for the extra argument parsed
* by the option in `--help` output.
* @param flags Flags from Glib::OptionEntry::Flags. Do not set FLAG_FILENAME.
* Character encoding is chosen with @a arg_type.
*/
void add_main_option_entry(OptionType arg_type, const Glib::ustring& long_name,
gchar short_name = '\0', const Glib::ustring& description = Glib::ustring(),
const Glib::ustring& arg_description = Glib::ustring(), int flags = 0);
_IGNORE(g_application_add_main_option_entries)
//g_application_add_main_option() seems to be just a new convenience function,
//TODO: Use it for some of our add_main_option_entry(without slot) implementation.
_IGNORE(g_application_add_main_option)
/** Adds a main option entry to be handled by the Application.
*
* Adds a string option entry, but lets the callback @a slot parse the extra
* argument instead of having it packed in a Glib::VariantDict.
*
* If you create more than one Application instance (unusual),
* one Application instance can't add an option with the same name as
* another instance adds. This restriction does not apply to the
* add_main_option_entry() that takes an OptionType parameter.
*
* @newin{2,42}
*
* @see add_main_option_entry(OptionType, const Glib::ustring&,
* gchar, const Glib::ustring&, const Glib::ustring&, int)
*/
void add_main_option_entry(const Glib::OptionGroup::SlotOptionArgString& slot,
const Glib::ustring& long_name,
gchar short_name = '\0', const Glib::ustring& description = Glib::ustring(),
const Glib::ustring& arg_description = Glib::ustring(), int flags = 0);
/** Adds a main option entry to be handled by the Application.
*
* Adds a filename option entry, but lets the callback @a slot parse the extra
* argument instead of having it packed in a Glib::VariantDict.
*
* If you create more than one Application instance (unusual),
* one Application instance can't add an option with the same name as
* another instance adds. This restriction does not apply to the
* add_main_option_entry() that takes an OptionType parameter.
*
* @newin{2,42}
*
* @see add_main_option_entry(OptionType, const Glib::ustring&,
* gchar, const Glib::ustring&, const Glib::ustring&, int)
*/
void add_main_option_entry_filename(const Glib::OptionGroup::SlotOptionArgFilename& slot,
const Glib::ustring& long_name,
gchar short_name = '\0', const Glib::ustring& description = Glib::ustring(),
const Glib::ustring& arg_description = Glib::ustring(), int flags = 0);
// _WRAP_METHOD(void add_option_group(Glib::OptionGroup& group), g_application_add_option_group)
// add_option_group() is probably not very useful. If implemented, it must probably
// be custom-implemented. See https://bugzilla.gnome.org/show_bug.cgi?id=727822#c10
_IGNORE(g_application_add_option_group)
_WRAP_METHOD(void set_option_context_parameter_string(const Glib::ustring& parameter_string{NULL}), g_application_set_option_context_parameter_string)
_WRAP_METHOD(void set_option_context_summary(const Glib::ustring& summary{NULL}), g_application_set_option_context_summary)
_WRAP_METHOD(void set_option_context_description(const Glib::ustring& description{NULL}), g_application_set_option_context_description)
_WRAP_METHOD(bool is_registered() const, g_application_get_is_registered)
_WRAP_METHOD(bool is_remote() const, g_application_get_is_remote)
//Renamed from register() because that is a C++ keyword.
_WRAP_METHOD(bool register_application(const Glib::RefPtr<Gio::Cancellable>& cancellable{?}), g_application_register, errthrow)
_IGNORE(g_application_impl_register)
_WRAP_METHOD(void hold(), g_application_hold)
_WRAP_METHOD(void release(), g_application_release)
_WRAP_METHOD(void activate(), g_application_activate)
using type_vec_files = std::vector< Glib::RefPtr<File> >;
/* Opens the given files.
*
* In essence, this results in the open signal being emitted
* in the primary instance.
*
* @a hint is simply passed through to the open signal. It is
* intended to be used by applications that have multiple modes for
* opening files (eg: "view" vs "edit", etc).
*
* The application must be registered before calling this method
* and it must have the APPLICATION_HANDLES_OPEN flag set.
*
* @param files The files to open. This must be non-empty.
* @param hint A hint.
*
* @newin{2,32}
*/
void open(const type_vec_files& files, const Glib::ustring& hint = Glib::ustring());
_IGNORE(g_application_open)
/* Opens the given file.
*
* In essence, this results in the open signal being emitted
* in the primary instance.
*
* @a hint is simply passed through to the open signal. It is
* intended to be used by applications that have multiple modes for
* opening files (eg: "view" vs "edit", etc).
*
* The application must be registered before calling this method
* and it must have the APPLICATION_HANDLES_OPEN flag set.
*
* @param file The file to open. This must be non-empty.
* @param hint A hint.
*
* @newin{2,32}
*/
void open(const Glib::RefPtr<Gio::File>& file, const Glib::ustring& hint = Glib::ustring());
_WRAP_METHOD(int run(int argc, char** argv), g_application_run)
_WRAP_METHOD(void quit(), g_application_quit)
_WRAP_METHOD(static void set_default(const Glib::RefPtr<Application>& application), g_application_set_default)
/// Unsets any existing default application.
static void unset_default();
_WRAP_METHOD(static Glib::RefPtr<Application> get_default(), g_application_get_default, refreturn)
_WRAP_METHOD(void mark_busy(), g_application_mark_busy)
_WRAP_METHOD(void unmark_busy(), g_application_unmark_busy)
_WRAP_METHOD(bool get_is_busy() const, g_application_get_is_busy)
_WRAP_METHOD(void send_notification(const Glib::ustring& id{?}, const Glib::RefPtr<Notification>& notification), g_application_send_notification)
_WRAP_METHOD(void withdraw_notification(const Glib::ustring& id), g_application_withdraw_notification)
//TODO: Glib::RefPtr<Glib::ObjectBase>, Glib::ObjectBase, or both?
//#m4 _CONVERSION(`const Glib::RefPtr<Glib::ObjectBase>&', `gpointer', `($3)->gobj()')
// _WRAP_METHOD(void bind_busy_property(const Glib::RefPtr<Glib::ObjectBase>& object, const Glib::ustring& property), g_application_bind_busy_property)
// _WRAP_METHOD(void unbind_busy_property(const Glib::RefPtr<Glib::ObjectBase>& object, const Glib::ustring& property), g_application_unbind_busy_property)
_WRAP_PROPERTY("action-group", Glib::RefPtr<ActionGroup>, deprecated "Use the Gio::ActionMap interface instead.")
_WRAP_PROPERTY("application-id", Glib::ustring)
_WRAP_PROPERTY("flags", ApplicationFlags)
_WRAP_PROPERTY("inactivity-timeout", guint)
_WRAP_PROPERTY("is-registered", bool)
_WRAP_PROPERTY("is-remote", bool)
//TODO: Change bool to std::string when we can break API/ABI.
_WRAP_PROPERTY("resource-base-path", bool, newin "2,44",
deprecated "This method has the wrong return type. Will be fixed at the next ABI break. Use property_resource_base_path_string() instead.")
/** The base resource path for the application.
*
* @newin{2,56}
*
* Default value: ""
*
* @return A PropertyProxy that allows you to get or set the value of the property,
* or receive notification when the value of the property changes.
*/
Glib::PropertyProxy< std::string > property_resource_base_path_string();
/** The base resource path for the application.
*
* @newin{2,56}
*
* Default value: ""
*
* @return A PropertyProxy_ReadOnly that allows you to get the value of the property,
* or receive notification when the value of the property changes.
*/
Glib::PropertyProxy_ReadOnly< std::string > property_resource_base_path_string() const;
_WRAP_PROPERTY("is-busy", bool)
//#m4 _CONVERSION(`const gchar*', `const Glib::ustring&', `Glib::ustring($3)')
//#m4 _CONVERSION(`GVariant*', `const Glib::VariantBase&', `Glib::wrap($3, true)')
_WRAP_SIGNAL(void startup(), "startup")
//TODO: Remove no_default_handler when we can break ABI
_WRAP_SIGNAL(void shutdown(), "shutdown", no_default_handler, newin "2,46")
_WRAP_SIGNAL(void activate(), "activate")
//We wrap the open signal without _WRAP_SIGNAL(), because we need to change its parameters.
//See bug https://bugzilla.gnome.org/show_bug.cgi?id=637457
Glib::SignalProxy< void, const type_vec_files&, const Glib::ustring& > signal_open();
_IGNORE_SIGNAL(open)
#m4 _CONVERSION(`GApplicationCommandLine*', `const Glib::RefPtr<ApplicationCommandLine>&',`Glib::wrap($3, true)')
_WRAP_SIGNAL(int command_line(const Glib::RefPtr<ApplicationCommandLine>& command_line), "command-line")
//TODO: Remove no_default_handler when we can break ABI
//TODO: Avoid the use of the Variants in the VariantDict?
//options must be non-const. The handler is meant to modify it. See the description
//of add_main_option_entry(OptionType, ...).
#m4 _CONVERSION(`GVariantDict*',`const Glib::RefPtr<Glib::VariantDict>&',`Glib::wrap($3, true)')
_WRAP_SIGNAL(int handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options), "handle-local-options", no_default_handler)
protected:
virtual void on_open(const type_vec_files& files, const Glib::ustring& hint);
#m4begin
_PUSH(SECTION_PCC_CLASS_INIT_DEFAULT_SIGNAL_HANDLERS)
klass->open = &open_callback;
_SECTION(SECTION_PH_DEFAULT_SIGNAL_HANDLERS)
static void open_callback(GApplication* self, GFile** files, gint n_files, const gchar* hint);
_POP()
#m4end
#m4 _CONVERSION(`char**&', `gchar***',`&($3)')
#m4 _CONVERSION(`gchar***', `char**&',`*($3)')
_WRAP_VFUNC(bool local_command_line(char**& arguments, int& exit_status), local_command_line)
#m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3,true)')
_WRAP_VFUNC(void before_emit(const Glib::VariantBase& platform_data), "before_emit")
_WRAP_VFUNC(void after_emit(const Glib::VariantBase& platform_data), "after_emit")
//TODO: File a bug about GVariantBuilder not being registered with the GType system first:
//_WRAP_VFUNC(void add_platform_data(Glib::VariantBuilder* builder), "add_platform_data")
_WRAP_VFUNC(void quit_mainloop(), "quit_mainloop")
_WRAP_VFUNC(void run_mainloop(), "run_mainloop")
private:
/** This is just a way to call Glib::init() (which calls g_type_init()) before
* calling application_class_.init(), so that
* g_application_get_type() will always succeed.
* See https://bugzilla.gnome.org/show_bug.cgi?id=639925
*/
const Glib::Class& custom_class_init();
// Code, common to the public add_main_option_entry*() methods.
void add_main_option_entry_private(GOptionArg arg, const Glib::ustring& long_name,
gchar short_name, const Glib::ustring& description,
const Glib::ustring& arg_description, int flags);
};
} // namespace Gio