diff options
-rw-r--r-- | finch/finchui.c (renamed from finch/gntui.c) | 92 | ||||
-rw-r--r-- | finch/finchui.h (renamed from finch/gntui.h) | 27 | ||||
-rw-r--r-- | finch/libfinch.c | 45 | ||||
-rw-r--r-- | finch/meson.build | 4 | ||||
-rw-r--r-- | libpurple/core.c | 57 | ||||
-rw-r--r-- | libpurple/core.h | 31 | ||||
-rw-r--r-- | libpurple/meson.build | 6 | ||||
-rw-r--r-- | libpurple/plugins/kwallet/purplekwallet.cpp | 8 | ||||
-rw-r--r-- | libpurple/protocols/jabber/bosh.c | 8 | ||||
-rw-r--r-- | libpurple/protocols/jabber/iq.c | 10 | ||||
-rw-r--r-- | libpurple/protocols/jabber/jabber.c | 8 | ||||
-rw-r--r-- | libpurple/purplecoreuiops.c | 48 | ||||
-rw-r--r-- | libpurple/purplecoreuiops.h | 75 | ||||
-rw-r--r-- | libpurple/purplepath.c | 6 | ||||
-rw-r--r-- | libpurple/purpleui.c | 425 | ||||
-rw-r--r-- | libpurple/purpleui.h | 201 | ||||
-rw-r--r-- | libpurple/purpleuiinfo.c | 326 | ||||
-rw-r--r-- | libpurple/purpleuiinfo.h | 143 | ||||
-rw-r--r-- | libpurple/tests/test_ui.c | 59 | ||||
-rw-r--r-- | pidgin/gtkconv.h | 2 | ||||
-rw-r--r-- | pidgin/libpidgin.c | 194 | ||||
-rw-r--r-- | pidgin/meson.build | 2 | ||||
-rw-r--r-- | pidgin/pidginapplication.c | 12 | ||||
-rw-r--r-- | pidgin/pidgincore.h | 12 | ||||
-rw-r--r-- | pidgin/pidginui.c | 263 | ||||
-rw-r--r-- | pidgin/pidginui.h | 60 | ||||
-rw-r--r-- | po/POTFILES.in | 3 |
27 files changed, 1145 insertions, 982 deletions
diff --git a/finch/gntui.c b/finch/finchui.c index f0f15a1563..f4af9330fd 100644 --- a/finch/gntui.c +++ b/finch/finchui.c @@ -1,5 +1,6 @@ /* - * finch + * Finch - Universal Text Chat Client + * Copyright (C) Pidgin Developers <devel@pidgin.im> * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -16,17 +17,16 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * along with this program; if not, see <https://www.gnu.org/licenses/>. */ -#include <config.h> +#include <glib.h> +#include <glib/gi18n.h> -#include <glib/gi18n-lib.h> +#define G_SETTINGS_ENABLE_BACKEND +#include <gio/gsettingsbackend.h> -#include <purple.h> - -#include "gntui.h" +#include "finchui.h" #include "finchnotifications.h" #include "gntaccount.h" @@ -34,15 +34,25 @@ #include "gntconn.h" #include "gntconv.h" #include "gntdebug.h" -#include "gntxfer.h" #include "gntmedia.h" #include "gntnotify.h" #include "gntplugin.h" #include "gntprefs.h" +#include "gntprefs.h" #include "gntrequest.h" #include "gntroomlist.h" #include "gntstatus.h" +#include "gntxfer.h" + +struct _FinchUi { + PurpleUi parent; +}; +G_DEFINE_TYPE(FinchUi, finch_ui, PURPLE_TYPE_UI) + +/****************************************************************************** + * Helpers + *****************************************************************************/ static gboolean finch_history_init(GError **error) { PurpleHistoryManager *manager = NULL; @@ -74,9 +84,16 @@ finch_history_init(GError **error) { return purple_history_manager_set_active(manager, id, error); } -void -finch_ui_init(void) -{ +/****************************************************************************** + * PurpleUi Implementation + *****************************************************************************/ +static void +finch_ui_prefs_init(G_GNUC_UNUSED PurpleUi *ui) { + finch_prefs_init(); +} + +static void +finch_ui_start(G_GNUC_UNUSED PurpleUi *ui) { GError *error = NULL; finch_debug_init(); @@ -144,9 +161,8 @@ finch_ui_init(void) #ifdef STANDALONE } -void -finch_ui_uninit(void) -{ +static void +finch_ui_stop(G_GNUC_UNUSED PurpleUi *ui) { purple_accounts_set_ui_ops(NULL); finch_accounts_uninit(); @@ -182,3 +198,49 @@ finch_ui_uninit(void) #endif /* _WIN32 */ #endif /* STANDALONE */ } + +static gpointer +finch_ui_get_settings_backend(G_GNUC_UNUSED PurpleUi *ui) { + GSettingsBackend *backend = NULL; + char *config = NULL; + + config = g_build_filename(purple_config_dir(), "finch3.ini", NULL); + backend = g_keyfile_settings_backend_new(config, "/", NULL); + + g_free(config); + + return backend; +} + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +finch_ui_init(G_GNUC_UNUSED FinchUi *ui) { +} + +static void +finch_ui_class_init(FinchUiClass *klass) { + PurpleUiClass *ui_class = PURPLE_UI_CLASS(klass); + + ui_class->prefs_init = finch_ui_prefs_init; + ui_class->start = finch_ui_start; + ui_class->stop = finch_ui_stop; + ui_class->get_settings_backend = finch_ui_get_settings_backend; +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +PurpleUi * +finch_ui_new(void) { + return g_object_new( + FINCH_TYPE_UI, + "id", "finch3", + "name", _("Finch"), + "version", VERSION, + "website", "https://pidgin.im", + "support-website", "https://pidgin.im/contact/", + "client-type", "console", + NULL); +} diff --git a/finch/gntui.h b/finch/finchui.h index 36597cae56..4913707067 100644 --- a/finch/gntui.h +++ b/finch/finchui.h @@ -1,5 +1,6 @@ /* - * finch + * Finch - Universal Text Chat Client + * Copyright (C) Pidgin Developers <devel@pidgin.im> * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -16,8 +17,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * along with this program; if not, see <https://www.gnu.org/licenses/>. */ #if !defined(FINCH_GLOBAL_HEADER_INSIDE) && !defined(FINCH_COMPILATION) @@ -27,10 +27,25 @@ #ifndef FINCH_UI_H #define FINCH_UI_H -#include "gnt.h" +#include <purple.h> -void finch_ui_init(void); -void finch_ui_uninit(void); +G_BEGIN_DECLS + +#define FINCH_TYPE_UI (finch_ui_get_type()) +G_DECLARE_FINAL_TYPE(FinchUi, finch_ui, FINCH, UI, PurpleUi) + +/** + * finch_ui_new: + * + * Creates the [class@Purple.Ui] for finch. + * + * Note: This isn't really useful outside of Finch itself. + * + * Since: 3.0.0 + */ +PurpleUi *finch_ui_new(void); + +G_END_DECLS #endif /* FINCH_UI_H */ diff --git a/finch/libfinch.c b/finch/libfinch.c index 191a9eb9e4..d978d34289 100644 --- a/finch/libfinch.c +++ b/finch/libfinch.c @@ -26,54 +26,19 @@ #include <glib/gi18n-lib.h> #include <glib/gstdio.h> -#define G_SETTINGS_ENABLE_BACKEND -#include <gio/gsettingsbackend.h> - #include <locale.h> #include <purple.h> +#include "finchui.h" #include "gntdebug.h" #include "gntidle.h" #include "gntprefs.h" -#include "gntui.h" #include "libfinch.h" #include "config.h" #include "package_revision.h" -static void -finch_quit(void) -{ - finch_ui_uninit(); -} - -static gpointer -finch_get_settings_backend(void) { - GSettingsBackend *backend = NULL; - char *config = NULL; - - config = g_build_filename(purple_config_dir(), "finch3.ini", NULL); - backend = g_keyfile_settings_backend_new(config, "/", NULL); - - g_free(config); - - return backend; -} - -static PurpleCoreUiOps core_ops = { - .ui_prefs_init = finch_prefs_init, - .ui_init = finch_ui_init, - .quit = finch_quit, - .get_settings_backend = finch_get_settings_backend, -}; - -static PurpleCoreUiOps * -gnt_core_get_ui_ops(void) -{ - return &core_ops; -} - static gboolean start_with_debugwin(gpointer null) { @@ -106,7 +71,6 @@ finch_plugins_init(void) { static int init_libpurple(int argc, char **argv) { - PurpleUiInfo *ui_info = NULL; gboolean opt_nologin = FALSE; gboolean opt_version = FALSE; gboolean opt_debug = FALSE; @@ -196,14 +160,9 @@ init_libpurple(int argc, char **argv) g_timeout_add(0, start_with_debugwin, NULL); } - purple_core_set_ui_ops(gnt_core_get_ui_ops()); purple_idle_set_ui(finch_idle_new()); - ui_info = purple_ui_info_new("finch3", _("Finch"), VERSION, - "https://pidgin.im", - "https://developer.pidgin.im", "console"); - - if (!purple_core_init(ui_info)) + if (!purple_core_init(finch_ui_new())) { fprintf(stderr, "Initialization of the Purple core failed. Dumping core.\n" diff --git a/finch/meson.build b/finch/meson.build index e6b7bcca12..56d5af6ab6 100644 --- a/finch/meson.build +++ b/finch/meson.build @@ -79,6 +79,7 @@ enable_consoleui = true libfinch_SOURCES = [ 'finchnotifications.c', + 'finchui.c', 'gntaccount.c', 'gntblist.c', 'gntconn.c', @@ -93,7 +94,6 @@ libfinch_SOURCES = [ 'gntrequest.c', 'gntroomlist.c', 'gntstatus.c', - 'gntui.c', 'gntxfer.c', package_revision, 'libfinch.c' @@ -101,6 +101,7 @@ libfinch_SOURCES = [ libfinch_headers = [ 'finchnotifications.h', + 'finchui.h', 'gntaccount.h', 'gntblist.h', 'gntconn.h', @@ -115,7 +116,6 @@ libfinch_headers = [ 'gntrequest.h', 'gntroomlist.h', 'gntstatus.h', - 'gntui.h', 'gntxfer.h', 'libfinch.h' ] diff --git a/libpurple/core.c b/libpurple/core.c index b13e719730..f665a0b989 100644 --- a/libpurple/core.c +++ b/libpurple/core.c @@ -54,26 +54,25 @@ struct PurpleCore { - PurpleUiInfo *ui_info; + PurpleUi *ui; void *reserved; }; -static PurpleCoreUiOps *_ops = NULL; static PurpleCore *_core = NULL; static GSettingsBackend *settings_backend = NULL; static void purple_core_print_version(void) { - PurpleUiInfo *ui_info = purple_core_get_ui_info(); + PurpleUi *ui = purple_core_get_ui(); const gchar *ui_name = NULL; const gchar *ui_version = NULL; gchar *ui_full_name = NULL; - if(PURPLE_IS_UI_INFO(ui_info)) { - ui_name = purple_ui_info_get_name(ui_info); - ui_version = purple_ui_info_get_version(ui_info); + if(PURPLE_IS_UI(ui)) { + ui_name = purple_ui_get_name(ui); + ui_version = purple_ui_get_version(ui); } if (ui_name) { @@ -93,11 +92,10 @@ purple_core_print_version(void) } gboolean -purple_core_init(PurpleUiInfo *ui_info) { - PurpleCoreUiOps *ops; +purple_core_init(PurpleUi *ui) { PurpleCore *core; - g_return_val_if_fail(PURPLE_IS_UI_INFO(ui_info), FALSE); + g_return_val_if_fail(PURPLE_IS_UI(ui), FALSE); g_return_val_if_fail(purple_get_core() == NULL, FALSE); bindtextdomain(PACKAGE, PURPLE_LOCALEDIR); @@ -107,11 +105,9 @@ purple_core_init(PurpleUiInfo *ui_info) { #endif _core = core = g_new0(PurpleCore, 1); - core->ui_info = ui_info; + core->ui = ui; core->reserved = NULL; - ops = purple_core_get_ui_ops(); - /* This monster is to work around a bug that was fixed in glib 2.73.3. Once * we require glib 2.74.0 this should be removed. */ @@ -143,15 +139,12 @@ purple_core_init(PurpleUiInfo *ui_info) { /* The prefs subsystem needs to be initialized before static protocols * for protocol prefs to work. */ purple_prefs_init(); - settings_backend = ops->get_settings_backend(); + + settings_backend = purple_ui_get_settings_backend(core->ui); purple_debug_init(); - if (ops != NULL) { - if (ops->ui_prefs_init != NULL) { - ops->ui_prefs_init(); - } - } + purple_ui_prefs_init(core->ui); purple_notification_manager_startup(); @@ -197,8 +190,7 @@ purple_core_init(PurpleUiInfo *ui_info) { */ purple_network_discover_my_ip(); - if (ops != NULL && ops->ui_init != NULL) - ops->ui_init(); + purple_ui_start(core->ui); /* Load the buddy list after UI init */ purple_blist_boot(); @@ -211,7 +203,6 @@ purple_core_init(PurpleUiInfo *ui_info) { void purple_core_quit(void) { - PurpleCoreUiOps *ops; PurpleCore *core = purple_get_core(); PurpleCredentialManager *credential_manager = NULL; PurpleHistoryManager *history_manager = NULL; @@ -249,9 +240,7 @@ purple_core_quit(void) _purple_image_store_uninit(); purple_network_uninit(); - ops = purple_core_get_ui_ops(); - if (ops != NULL && ops->quit != NULL) - ops->quit(); + purple_ui_stop(core->ui); /* Everything after prefs_uninit must not try to read any prefs */ g_clear_object(&settings_backend); @@ -275,7 +264,7 @@ purple_core_quit(void) purple_signals_uninit(); - g_clear_object(&core->ui_info); + g_clear_object(&core->ui); g_free(core); #ifdef _WIN32 @@ -310,19 +299,7 @@ purple_core_get_settings_backend(void) { return settings_backend; } -void -purple_core_set_ui_ops(PurpleCoreUiOps *ops) -{ - _ops = ops; -} - -PurpleCoreUiOps * -purple_core_get_ui_ops(void) -{ - return _ops; -} - -PurpleUiInfo * -purple_core_get_ui_info(void) { - return _core->ui_info; +PurpleUi * +purple_core_get_ui(void) { + return _core->ui; } diff --git a/libpurple/core.h b/libpurple/core.h index 5f1ca11f65..514c5219ea 100644 --- a/libpurple/core.h +++ b/libpurple/core.h @@ -29,7 +29,7 @@ #include <glib.h> #include <glib-object.h> -#include <libpurple/purplecoreuiops.h> +#include <libpurple/purpleui.h> typedef struct PurpleCore PurpleCore; @@ -37,7 +37,7 @@ G_BEGIN_DECLS /** * purple_core_init: - * @ui_info: (transfer full): The [class@UiInfo] of the UI using the core. + * @ui: (transfer full): The [class@Purple.Ui] of the UI using the core. * * Initializes the core of purple. * @@ -45,7 +45,7 @@ G_BEGIN_DECLS * * Returns: %TRUE if successful, or %FALSE otherwise. */ -gboolean purple_core_init(PurpleUiInfo *ui_info); +gboolean purple_core_init(PurpleUi *ui); /** * purple_core_quit: @@ -112,30 +112,13 @@ PurpleCore *purple_get_core(void); gpointer purple_core_get_settings_backend(void); /** - * purple_core_set_ui_ops: - * @ops: A UI ops structure for the core. + * purple_core_get_ui: * - * Sets the UI ops for the core. - */ -void purple_core_set_ui_ops(PurpleCoreUiOps *ops); - -/** - * purple_core_get_ui_ops: - * - * Returns the UI ops for the core. - * - * Returns: The core's UI ops structure. - */ -PurpleCoreUiOps *purple_core_get_ui_ops(void); - -/** - * purple_core_get_ui_info: - * - * Returns a #PurpleUiInfo that contains information about the user interface. + * Gets the [class@Purple.Ui] that is running. * - * Returns: (transfer none): A #PurpleUiInfo instance. + * Returns: (transfer none): The ui. */ -PurpleUiInfo *purple_core_get_ui_info(void); +PurpleUi *purple_core_get_ui(void); G_END_DECLS diff --git a/libpurple/meson.build b/libpurple/meson.build index 592b09cb41..9c2df2169b 100644 --- a/libpurple/meson.build +++ b/libpurple/meson.build @@ -50,7 +50,6 @@ purple_coresources = [ 'purpleconversation.c', 'purpleconversationmanager.c', 'purpleconversationuiops.c', - 'purplecoreuiops.c', 'purplecredentialmanager.c', 'purplecredentialprovider.c', 'purpledebugui.c', @@ -88,7 +87,7 @@ purple_coresources = [ 'purplesqlite3.c', 'purplesqlitehistoryadapter.c', 'purpletags.c', - 'purpleuiinfo.c', + 'purpleui.c', 'purplewhiteboard.c', 'purplewhiteboardmanager.c', 'purplewhiteboarduiops.c', @@ -155,7 +154,6 @@ purple_coreheaders = [ 'purpleconversation.h', 'purpleconversationmanager.h', 'purpleconversationuiops.h', - 'purplecoreuiops.h', 'purplecredentialmanager.h', 'purplecredentialprovider.h', 'purpledebugui.h', @@ -194,7 +192,7 @@ purple_coreheaders = [ 'purplesqlite3.h', 'purplesqlitehistoryadapter.h', 'purpletags.h', - 'purpleuiinfo.h', + 'purpleui.h', 'purplewhiteboard.h', 'purplewhiteboardmanager.h', 'purplewhiteboardops.h', diff --git a/libpurple/plugins/kwallet/purplekwallet.cpp b/libpurple/plugins/kwallet/purplekwallet.cpp index e00fb00a8f..7ae63230c6 100644 --- a/libpurple/plugins/kwallet/purplekwallet.cpp +++ b/libpurple/plugins/kwallet/purplekwallet.cpp @@ -53,12 +53,12 @@ G_DEFINE_DYNAMIC_TYPE(PurpleKWalletProvider, purple_kwallet_provider, *****************************************************************************/ static QString purple_kwallet_get_ui_name(void) { - PurpleUiInfo *ui_info = NULL; + PurpleUi *ui = NULL; QString ui_name = NULL; - ui_info = purple_core_get_ui_info(); - if(PURPLE_IS_UI_INFO(ui_info)) { - ui_name = purple_ui_info_get_name(ui_info); + ui = purple_core_get_ui(); + if(PURPLE_IS_UI(ui)) { + ui_name = purple_ui_get_name(ui); } if(ui_name.isEmpty()) { diff --git a/libpurple/protocols/jabber/bosh.c b/libpurple/protocols/jabber/bosh.c index 83e04df988..15f4c5cb6e 100644 --- a/libpurple/protocols/jabber/bosh.c +++ b/libpurple/protocols/jabber/bosh.c @@ -65,13 +65,13 @@ jabber_bosh_connection_send_now(PurpleJabberBOSHConnection *conn); void jabber_bosh_init(void) { - PurpleUiInfo *ui_info = purple_core_get_ui_info(); + PurpleUi *ui = purple_core_get_ui(); const gchar *ui_name = NULL; const gchar *ui_version = NULL; - if(PURPLE_IS_UI_INFO(ui_info)) { - ui_name = purple_ui_info_get_name(ui_info); - ui_version = purple_ui_info_get_version(ui_info); + if(PURPLE_IS_UI(ui)) { + ui_name = purple_ui_get_name(ui); + ui_version = purple_ui_get_version(ui); } if(ui_name) { diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c index 184819016d..a87105b3e8 100644 --- a/libpurple/protocols/jabber/iq.c +++ b/libpurple/protocols/jabber/iq.c @@ -224,7 +224,7 @@ static void jabber_iq_version_parse(JabberStream *js, const char *from, PurpleXmlNode *query; if(type == JABBER_IQ_GET) { - PurpleUiInfo *ui_info; + PurpleUi *ui; const char *ui_name = NULL, *ui_version = NULL; iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); @@ -234,11 +234,11 @@ static void jabber_iq_version_parse(JabberStream *js, const char *from, query = purple_xmlnode_get_child(iq->node, "query"); - ui_info = purple_core_get_ui_info(); + ui = purple_core_get_ui(); - if(PURPLE_IS_UI_INFO(ui_info)) { - ui_name = purple_ui_info_get_name(ui_info); - ui_version = purple_ui_info_get_version(ui_info); + if(PURPLE_IS_UI(ui)) { + ui_name = purple_ui_get_name(ui); + ui_version = purple_ui_get_version(ui); } if(NULL != ui_name && NULL != ui_version) { diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c index dc04dd43c5..e807faa7d4 100644 --- a/libpurple/protocols/jabber/jabber.c +++ b/libpurple/protocols/jabber/jabber.c @@ -3679,7 +3679,7 @@ xmpp_uri_handler(const char *proto, const char *user, GHashTable *params, static void jabber_do_init(void) { - PurpleUiInfo *ui_info = purple_core_get_ui_info(); + PurpleUi *ui = purple_core_get_ui(); const gchar *ui_type; const gchar *type = "pc"; /* default client type, if unknown or unspecified */ @@ -3713,7 +3713,7 @@ jabber_do_init(void) jabber_cmds = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, cmds_free_func); - ui_type = ui_info ? purple_ui_info_get_client_type(ui_info) : NULL; + ui_type = ui ? purple_ui_get_client_type(ui) : NULL; if (ui_type) { if (purple_strequal(ui_type, "pc") || purple_strequal(ui_type, "console") || @@ -3725,8 +3725,8 @@ jabber_do_init(void) } } - if (ui_info) - ui_name = purple_ui_info_get_name(ui_info); + if (ui) + ui_name = purple_ui_get_name(ui); if (ui_name == NULL) ui_name = PACKAGE; diff --git a/libpurple/purplecoreuiops.c b/libpurple/purplecoreuiops.c deleted file mode 100644 index 0fe8819eed..0000000000 --- a/libpurple/purplecoreuiops.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#include "purplecoreuiops.h" - -static PurpleCoreUiOps * -purple_core_ui_ops_copy(PurpleCoreUiOps *ops) -{ - PurpleCoreUiOps *ops_new; - - g_return_val_if_fail(ops != NULL, NULL); - - ops_new = g_new(PurpleCoreUiOps, 1); - *ops_new = *ops; - - return ops_new; -} - -GType -purple_core_ui_ops_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - type = g_boxed_type_register_static("PurpleCoreUiOps", - (GBoxedCopyFunc)purple_core_ui_ops_copy, - (GBoxedFreeFunc)g_free); - } - - return type; -} - - diff --git a/libpurple/purplecoreuiops.h b/libpurple/purplecoreuiops.h deleted file mode 100644 index 576918da8b..0000000000 --- a/libpurple/purplecoreuiops.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) -# error "only <purple.h> may be included directly" -#endif - -#ifndef PURPLE_CORE_UIOPS_H -#define PURPLE_CORE_UIOPS_H - -#include <glib.h> -#include <glib-object.h> - -#include <libpurple/purpleuiinfo.h> - -#define PURPLE_TYPE_CORE_UI_OPS (purple_core_ui_ops_get_type()) -typedef struct _PurpleCoreUiOps PurpleCoreUiOps; - -G_BEGIN_DECLS - -/** - * PurpleCoreUiOps: - * @ui_prefs_init: Called just after the preferences subsystem is initialized; - * the UI could use this callback to add some preferences it - * needs to be in place when other subsystems are initialized. - * @ui_init: Called after all of libpurple has been initialized. The UI - * should use this hook to set all other necessary - * <link linkend="chapter-ui-ops"><literal>UiOps structures</literal></link>. - * @quit: Called after most of libpurple has been uninitialized. - * @get_settings_backend: Called to get the [class@Gio.SettingsBackend] that - * the UI is using. - * - * Callbacks that fire at different points of the initialization and teardown - * of libpurple, along with a hook to return descriptive information about the - * UI. - */ -struct _PurpleCoreUiOps { - /*< public >*/ - void (*ui_prefs_init)(void); - void (*ui_init)(void); - - void (*quit)(void); - - gpointer (*get_settings_backend)(void); - - /*< private >*/ - gpointer reserved[4]; -}; - -/** - * purple_core_ui_ops_get_type: - * - * Returns: The #GType for the #PurpleCoreUiOps boxed structure. - */ -GType purple_core_ui_ops_get_type(void); - - -G_END_DECLS - -#endif /* PURPLE_CORE_UIOPS_H */ diff --git a/libpurple/purplepath.c b/libpurple/purplepath.c index 54f736fd59..473d2e898a 100644 --- a/libpurple/purplepath.c +++ b/libpurple/purplepath.c @@ -19,7 +19,7 @@ #include <libpurple/purplepath.h> #include <libpurple/core.h> -#include <libpurple/purpleuiinfo.h> +#include <libpurple/purpleui.h> #ifdef _WIN32 # include "win32/win32dep.h" @@ -43,10 +43,10 @@ purple_xdg_dir(gchar **xdg_dir, const gchar *xdg_base_dir, { if (!*xdg_dir) { if (!custom_user_dir) { - PurpleUiInfo *info = purple_core_get_ui_info(); + PurpleUi *ui = purple_core_get_ui(); const gchar *id = NULL; - id = purple_ui_info_get_id(info); + id = purple_ui_get_id(ui); if(id == NULL) { id = "purple"; } diff --git a/libpurple/purpleui.c b/libpurple/purpleui.c new file mode 100644 index 0000000000..b6545a704c --- /dev/null +++ b/libpurple/purpleui.c @@ -0,0 +1,425 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include "purpleui.h" + +typedef struct { + char *id; + char *name; + char *version; + char *website; + char *support_website; + char *client_type; +} PurpleUiPrivate; + +enum { + PROP_0, + PROP_ID, + PROP_NAME, + PROP_VERSION, + PROP_WEBSITE, + PROP_SUPPORT_WEBSITE, + PROP_CLIENT_TYPE, + N_PROPERTIES, +}; +static GParamSpec *properties[N_PROPERTIES] = {NULL,}; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(PurpleUi, purple_ui, G_TYPE_OBJECT) + +/****************************************************************************** + * Helpers + *****************************************************************************/ +static void +purple_ui_set_id(PurpleUi *ui, const char *id) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->id); + priv->id = g_strdup(id); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_ID]); +} + +static void +purple_ui_set_name(PurpleUi *ui, const char *name) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->name); + priv->name = g_strdup(name); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_NAME]); +} + +static void +purple_ui_set_version(PurpleUi *ui, const char *version) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->version); + priv->version = g_strdup(version); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_VERSION]); +} + +static void +purple_ui_set_website(PurpleUi *ui, const char *website) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->website); + priv->website = g_strdup(website); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_WEBSITE]); +} + +static void +purple_ui_set_support_website(PurpleUi *ui, const char *support_website) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->support_website); + priv->support_website = g_strdup(support_website); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_SUPPORT_WEBSITE]); +} + +static void +purple_ui_set_client_type(PurpleUi *ui, const char *client_type) { + PurpleUiPrivate *priv = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + priv = purple_ui_get_instance_private(ui); + + g_free(priv->client_type); + priv->client_type = g_strdup(client_type); + + g_object_notify_by_pspec(G_OBJECT(ui), properties[PROP_CLIENT_TYPE]); +} + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +purple_ui_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleUi *ui = PURPLE_UI(obj); + + switch(param_id) { + case PROP_ID: + g_value_set_string(value, purple_ui_get_id(ui)); + break; + case PROP_NAME: + g_value_set_string(value, purple_ui_get_name(ui)); + break; + case PROP_VERSION: + g_value_set_string(value, purple_ui_get_version(ui)); + break; + case PROP_WEBSITE: + g_value_set_string(value, purple_ui_get_website(ui)); + break; + case PROP_SUPPORT_WEBSITE: + g_value_set_string(value, purple_ui_get_support_website(ui)); + break; + case PROP_CLIENT_TYPE: + g_value_set_string(value, purple_ui_get_client_type(ui)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_ui_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleUi *ui = PURPLE_UI(obj); + + switch(param_id) { + case PROP_ID: + purple_ui_set_id(ui, g_value_get_string(value)); + break; + case PROP_NAME: + purple_ui_set_name(ui, g_value_get_string(value)); + break; + case PROP_VERSION: + purple_ui_set_version(ui, g_value_get_string(value)); + break; + case PROP_WEBSITE: + purple_ui_set_website(ui, g_value_get_string(value)); + break; + case PROP_SUPPORT_WEBSITE: + purple_ui_set_support_website(ui, g_value_get_string(value)); + break; + case PROP_CLIENT_TYPE: + purple_ui_set_client_type(ui, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_ui_finalize(GObject *obj) { + PurpleUiPrivate *priv = purple_ui_get_instance_private(PURPLE_UI(obj)); + + g_clear_pointer(&priv->id, g_free); + g_clear_pointer(&priv->name, g_free); + g_clear_pointer(&priv->version, g_free); + g_clear_pointer(&priv->website, g_free); + g_clear_pointer(&priv->support_website, g_free); + g_clear_pointer(&priv->client_type, g_free); + + G_OBJECT_CLASS(purple_ui_parent_class)->finalize(obj); +} + +static void +purple_ui_init(G_GNUC_UNUSED PurpleUi *ui) { +} + +static void +purple_ui_class_init(PurpleUiClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + obj_class->get_property = purple_ui_get_property; + obj_class->set_property = purple_ui_set_property; + obj_class->finalize = purple_ui_finalize; + + /** + * PurpleUi:id: + * + * The identifier of the user interface. This is used in places where a + * constant string is need to represent the user interface. + * + * Since: 3.0.0 + */ + properties[PROP_ID] = g_param_spec_string( + "id", "id", + "The identifier of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + /** + * PurpleUi:name: + * + * The name of the user interface. This is used in places where it will be + * displayed to users, so it should be translated. + * + * Since: 3.0.0 + */ + properties[PROP_NAME] = g_param_spec_string( + "name", "name", + "The name of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + /** + * PurpleUi:version: + * + * The version number of the user interface. + * + * Since: 3.0.0 + */ + properties[PROP_VERSION] = g_param_spec_string( + "version", "version", + "The version of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + /** + * PurpleUi:website: + * + * The website of the user interface. This should be the main website. + * + * Since: 3.0.0 + */ + properties[PROP_WEBSITE] = g_param_spec_string( + "website", "website", + "The website of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + /** + * PurpleUi:support-website: + * + * The support website of the user interface. This should link to a page + * that specifically directs users how to get support for your user + * interface. + * + * Since: 3.0.0 + */ + properties[PROP_SUPPORT_WEBSITE] = g_param_spec_string( + "support-website", "support-website", + "The support website of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + /** + * PurpleUi:client-type: + * + * The client type of the user interface. Common values include `bot`, + * `console`, `mobile`, `pc`, `web`, etc. + * + * Since: 3.0.0 + */ + properties[PROP_CLIENT_TYPE] = g_param_spec_string( + "client-type", "client-type", + "The client type of the user interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +const char * +purple_ui_get_id(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->id; +} + +const char * +purple_ui_get_name(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->name; +} + +const char * +purple_ui_get_version(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->version; +} + +const char * +purple_ui_get_website(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->website; +} + +const char * +purple_ui_get_support_website(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->support_website; +} + +const char * +purple_ui_get_client_type(PurpleUi *ui) { + PurpleUiPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + priv = purple_ui_get_instance_private(ui); + + return priv->client_type; +} + +void +purple_ui_prefs_init(PurpleUi *ui) { + PurpleUiClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + klass = PURPLE_UI_GET_CLASS(ui); + if(klass != NULL && klass->prefs_init != NULL) { + klass->prefs_init(ui); + } +} + +void +purple_ui_start(PurpleUi *ui) { + PurpleUiClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + klass = PURPLE_UI_GET_CLASS(ui); + if(klass != NULL && klass->start != NULL) { + klass->start(ui); + } +} + +void +purple_ui_stop(PurpleUi *ui) { + PurpleUiClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_UI(ui)); + + klass = PURPLE_UI_GET_CLASS(ui); + if(klass != NULL && klass->stop != NULL) { + klass->stop(ui); + } +} + +gpointer +purple_ui_get_settings_backend(PurpleUi *ui) { + PurpleUiClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_UI(ui), NULL); + + klass = PURPLE_UI_GET_CLASS(ui); + if(klass != NULL && klass->get_settings_backend != NULL) { + return klass->get_settings_backend(ui); + } + + return NULL; +} diff --git a/libpurple/purpleui.h b/libpurple/purpleui.h new file mode 100644 index 0000000000..2bd92210fc --- /dev/null +++ b/libpurple/purpleui.h @@ -0,0 +1,201 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <pidgin.h> may be included directly" +#endif + +#ifndef PURPLE_UI_H +#define PURPLE_UI_H + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define PURPLE_TYPE_UI (purple_ui_get_type()) +G_DECLARE_DERIVABLE_TYPE(PurpleUi, purple_ui, PURPLE, UI, GObject) + +/** + * PurpleUi: + * + * An abstract class representing a user interface. All user interfaces must + * create a subclass of this and pass it to [func@Purple.Core.init]. + * + * Since: 3.0.0 + */ + +/** + * PurpleUiClass: + * @prefs_init: This function is called to initialize the ui's preferences. + * This is slowly being phased out for @get_settings_backend, but + * is still required. + * @start: Called when libpurple is done with its initialization when the user + * interface should start telling libpurple about the rest of the user + * interface's interfaces. + * @stop: Called after most of libpurple has been uninitialized. + * @get_settings_backend: Called to get the [class@Gio.SettingsBackend] that + * the UI is using. + * + * The base class for all user interfaces which is used to identify themselves + * to libpurple when calling [func@Purple.core_init]. + * + * Since: 3.0.0 + */ +struct _PurpleUiClass { + /*< private >*/ + GObjectClass parent; + + /*< public >*/ + void (*prefs_init)(PurpleUi *ui); + void (*start)(PurpleUi *ui); + void (*stop)(PurpleUi *ui); + + gpointer (*get_settings_backend)(PurpleUi *ui); + + /*< private >*/ + gpointer reserved[4]; +}; + +/** + * purple_ui_get_id: + * @ui: The instance. + * + * Gets the id for the user interface. + * + * Returns: id of the user interface. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_id(PurpleUi *ui); + +/** + * purple_ui_get_name: + * @ui: The instance. + * + * Gets the name of @ui. This should be translated. + * + * Returns: The name of the user interface. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_name(PurpleUi *ui); + +/** + * purple_ui_get_version: + * @ui: The instance. + * + * Gets the version of @ui. + * + * Returns: The version of the user interface. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_version(PurpleUi *ui); + +/** + * purple_ui_get_website: + * @ui: The instance. + * + * Gets the website from @ui. + * + * Returns: (nullable): The website URI of the user interface or %NULL. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_website(PurpleUi *ui); + +/** + * purple_ui_get_support_website: + * @ui: The instance. + * + * Gets the support website from @ui. + * + * Returns: (nullable): The support website URI of the user interface or %NULL. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_support_website(PurpleUi *ui); + +/** + * purple_ui_get_client_type: + * @ui: The instance. + * + * Gets the client type from @ui. + * + * Returns: (transfer none): The client type of the user interface. + * + * Since: 3.0.0 + */ +const char *purple_ui_get_client_type(PurpleUi *ui); + +/** + * purple_ui_prefs_init: + * @ui: The instance. + * + * Tells @ui that it should be initializing its preferences. + * + * Note: This should only be called by libpurple. + * + * Since: 3.0.0 + */ +void purple_ui_prefs_init(PurpleUi *ui); + +/** + * purple_ui_start: + * @ui: The instance. + * + * Tells @ui that libpurple is done initializing and that @ui should continue + * its initialization. + * + * Note: This should only be called by libpurple. + * + * Since: 3.0.0 + */ +void purple_ui_start(PurpleUi *ui); + +/** + * purple_ui_stop: + * @ui: The instance. + * + * Tells @ui that libpurple is done shutting down. + * + * Note: This should only be called by libpurple. + * + * Since: 3.0.0 + */ +void purple_ui_stop(PurpleUi *ui); + +/** + * purple_ui_get_settings_backend: + * @ui: The instance: + * + * Get the [class@Gio.SettingsBackend] that @ui is using for its settings. + * + * Note: This should only be called by libpurple. + * + * Returns: (transfer full): The settings that @ui is using. + * + * Since: 3.0.0 + */ +gpointer purple_ui_get_settings_backend(PurpleUi *ui); + + +G_END_DECLS + +#endif /* PURPLE_UI_H */ diff --git a/libpurple/purpleuiinfo.c b/libpurple/purpleuiinfo.c deleted file mode 100644 index 403b0860aa..0000000000 --- a/libpurple/purpleuiinfo.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "purpleuiinfo.h" - -struct _PurpleUiInfo { - GObject parent; - - gchar *id; - gchar *name; - gchar *version; - gchar *website; - gchar *support_website; - gchar *client_type; -}; - -enum { - PROP_0, - PROP_ID, - PROP_NAME, - PROP_VERSION, - PROP_WEBSITE, - PROP_SUPPORT_WEBSITE, - PROP_CLIENT_TYPE, - N_PROPERTIES -}; -static GParamSpec *properties[N_PROPERTIES] = { NULL, }; - -/****************************************************************************** - * Helpers - *****************************************************************************/ -static void -purple_ui_info_set_id(PurpleUiInfo *info, const gchar *id) { - g_free(info->id); - info->id = g_strdup(id); -} - -static void -purple_ui_info_set_name(PurpleUiInfo *info, const gchar *name) { - g_free(info->name); - info->name = g_strdup(name); -} - -static void -purple_ui_info_set_version(PurpleUiInfo *info, const gchar *version) { - g_free(info->version); - info->version = g_strdup(version); -} - -static void -purple_ui_info_set_website(PurpleUiInfo *info, const gchar *website) { - g_free(info->website); - info->website = g_strdup(website); -} - -static void -purple_ui_info_set_support_website(PurpleUiInfo *info, - const gchar *support_website) -{ - g_free(info->support_website); - info->support_website = g_strdup(support_website); -} - -static void -purple_ui_info_set_client_type(PurpleUiInfo *info, const gchar *client_type) { - g_free(info->client_type); - info->client_type = g_strdup(client_type); -} - -/****************************************************************************** - * GObject Implementation - *****************************************************************************/ -G_DEFINE_TYPE(PurpleUiInfo, purple_ui_info, G_TYPE_OBJECT); - -static void -purple_ui_info_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleUiInfo *info = PURPLE_UI_INFO(obj); - - switch(param_id) { - case PROP_ID: - g_value_set_string(value, purple_ui_info_get_id(info)); - break; - case PROP_NAME: - g_value_set_string(value, purple_ui_info_get_name(info)); - break; - case PROP_VERSION: - g_value_set_string(value, purple_ui_info_get_version(info)); - break; - case PROP_WEBSITE: - g_value_set_string(value, purple_ui_info_get_website(info)); - break; - case PROP_SUPPORT_WEBSITE: - g_value_set_string(value, purple_ui_info_get_support_website(info)); - break; - case PROP_CLIENT_TYPE: - g_value_set_string(value, purple_ui_info_get_client_type(info)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_ui_info_set_property(GObject *obj, guint param_id, const GValue *value, - GParamSpec *pspec) -{ - PurpleUiInfo *info = PURPLE_UI_INFO(obj); - - switch(param_id) { - case PROP_ID: - purple_ui_info_set_id(info, g_value_get_string(value)); - break; - case PROP_NAME: - purple_ui_info_set_name(info, g_value_get_string(value)); - break; - case PROP_VERSION: - purple_ui_info_set_version(info, g_value_get_string(value)); - break; - case PROP_WEBSITE: - purple_ui_info_set_website(info, g_value_get_string(value)); - break; - case PROP_SUPPORT_WEBSITE: - purple_ui_info_set_support_website(info, - g_value_get_string(value)); - break; - case PROP_CLIENT_TYPE: - purple_ui_info_set_client_type(info, g_value_get_string(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_ui_info_init(PurpleUiInfo *info) { -} - -static void -purple_ui_info_finalize(GObject *obj) { - PurpleUiInfo *info = PURPLE_UI_INFO(obj); - - g_clear_pointer(&info->id, g_free); - g_clear_pointer(&info->name, g_free); - g_clear_pointer(&info->version, g_free); - g_clear_pointer(&info->website, g_free); - g_clear_pointer(&info->support_website, g_free); - g_clear_pointer(&info->client_type, g_free); - - G_OBJECT_CLASS(purple_ui_info_parent_class)->finalize(obj); -} - -static void -purple_ui_info_class_init(PurpleUiInfoClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - - obj_class->get_property = purple_ui_info_get_property; - obj_class->set_property = purple_ui_info_set_property; - obj_class->finalize = purple_ui_info_finalize; - - /** - * PurpleUiInfo:id: - * - * The identifier of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_ID] = - g_param_spec_string("id", "id", "The identifier of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * PurpleUiInfo:name: - * - * The name of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_NAME] = - g_param_spec_string("name", "name", "The name of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * PurpleUiInfo:version: - * - * The version of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_VERSION] = - g_param_spec_string("version", "version", - "The version of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * PurpleUiInfo:website: - * - * The website of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_WEBSITE] = - g_param_spec_string("website", "website", - "The website of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * PurpleUiInfo:support-website: - * - * The support website of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_SUPPORT_WEBSITE] = - g_param_spec_string("support-website", "support-website", - "The support website of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * PurpleUiInfo:client-type: - * - * The client type of the user interface. - * - * Since: 3.0.0 - */ - properties[PROP_CLIENT_TYPE] = - g_param_spec_string("client-type", "client-type", - "The client type of the user interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, N_PROPERTIES, properties); -} - -/****************************************************************************** - * Public API - *****************************************************************************/ -PurpleUiInfo * -purple_ui_info_new(const gchar *id, const gchar *name, - const gchar *version, const gchar *website, - const gchar *support_website, const gchar *client_type) -{ - return g_object_new(PURPLE_TYPE_UI_INFO, - "id", id, - "name", name, - "version", version, - "website", website, - "support-website", support_website, - "client-type", client_type, - NULL); -} - -const gchar * -purple_ui_info_get_id(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->id; -} - -const gchar * -purple_ui_info_get_name(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->name; -} - -const gchar * -purple_ui_info_get_version(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->version; -} - -const gchar * -purple_ui_info_get_website(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->website; -} - -const gchar * -purple_ui_info_get_support_website(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->support_website; -} - -const gchar * -purple_ui_info_get_client_type(PurpleUiInfo *info) { - g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL); - - return info->client_type; -} diff --git a/libpurple/purpleuiinfo.h b/libpurple/purpleuiinfo.h deleted file mode 100644 index 8a72ab9a8a..0000000000 --- a/libpurple/purpleuiinfo.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) -# error "only <purple.h> may be included directly" -#endif - -#ifndef PURPLE_UI_INFO_H -#define PURPLE_UI_INFO_H - -#include <glib.h> -#include <glib-object.h> - -G_BEGIN_DECLS - -#define PURPLE_TYPE_UI_INFO (purple_ui_info_get_type()) - -/** - * PurpleUiInfo: - * - * #PurpleUiInfo keeps track of basic information about the user interface. - */ -G_DECLARE_FINAL_TYPE(PurpleUiInfo, purple_ui_info, PURPLE, UI_INFO, GObject) - -/** - * purple_ui_info_new: - * @id: The identifier. - * @name: The name, which will be displayed. - * @version: The version. - * @website: The website. - * @support_website: The support website. - * @client_type: The client type. - * - * Creates a new #PurpleUiInfo with the given values. If you only want to set - * a few of these, you should use g_object_new() directly. - * - * Returns: (transfer full): The newly created #PurpleUiInfo instance. - * - * Since: 3.0.0 - */ -PurpleUiInfo *purple_ui_info_new(const gchar *id, - const gchar *name, - const gchar *version, - const gchar *website, - const gchar *support_website, - const gchar *client_type); - -/** - * purple_ui_info_get_id: - * @info: The instance. - * - * Gets the identifier from @info. - * - * Returns: The identifier from @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_id(PurpleUiInfo *info); - -/** - * purple_ui_info_get_name: - * @info: The #PurpleUiInfo instance. - * - * Gets the name from @info. - * - * Returns: The name from @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_name(PurpleUiInfo *info); - -/** - * purple_ui_info_get_version: - * @info: The #PurpleUiInfo instance. - * - * Gets the version from @info. - * - * Returns: The version from @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_version(PurpleUiInfo *info); - -/** - * purple_ui_info_get_website: - * @info: The #PurpleUiInfo instance. - * - * Gets the website from @info. - * - * Returns: The website for @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_website(PurpleUiInfo *info); - -/** - * purple_ui_info_get_support_website: - * @info: The #PurpleUiInfo instance. - * - * Gets the support website from @info. - * - * Returns: The support website from @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_support_website(PurpleUiInfo *info); - -/** - * purple_ui_info_get_client_type: - * @info: The #PurpleUiInfo instance. - * - * Gets the client type from @info. For example: 'bot', 'console', 'mobile', - * 'pc', 'web', etc. - * - * Returns: The client type of @info. - * - * Since: 3.0.0 - */ -const gchar *purple_ui_info_get_client_type(PurpleUiInfo *info); - -G_END_DECLS - -#endif /* PURPLE_UI_INFO_H */ - diff --git a/libpurple/tests/test_ui.c b/libpurple/tests/test_ui.c index f172462678..30f30daf73 100644 --- a/libpurple/tests/test_ui.c +++ b/libpurple/tests/test_ui.c @@ -58,21 +58,51 @@ static PurpleConversationUiOps test_conv_uiops = { .write_conv = test_write_conv }; +/****************************************************************************** + * PurpleUi Implementation + *****************************************************************************/ +struct _TestPurpleUi { + PurpleUi parent; +}; + +G_DECLARE_FINAL_TYPE(TestPurpleUi, test_purple_ui, TEST_PURPLE, UI, PurpleUi) + +G_DEFINE_TYPE(TestPurpleUi, test_purple_ui, PURPLE_TYPE_UI) + static void -test_ui_init(void) -{ +test_purple_ui_start(G_GNUC_UNUSED PurpleUi *ui) { purple_conversations_set_ui_ops(&test_conv_uiops); } static gpointer -test_ui_get_settings_backend(void) { +test_purple_ui_get_settings_backend(G_GNUC_UNUSED PurpleUi *ui) { return g_memory_settings_backend_new(); } -static PurpleCoreUiOps test_core_uiops = { - .ui_init = test_ui_init, - .get_settings_backend = test_ui_get_settings_backend, -}; +static void +test_purple_ui_init(G_GNUC_UNUSED TestPurpleUi *ui) { +} + +static void +test_purple_ui_class_init(TestPurpleUiClass *klass) { + PurpleUiClass *ui_class = PURPLE_UI_CLASS(klass); + + ui_class->start = test_purple_ui_start; + ui_class->get_settings_backend = test_purple_ui_get_settings_backend; +} + +static PurpleUi * +test_purple_ui_new(void) { + return g_object_new( + test_purple_ui_get_type(), + "id", "test", + "name", "Test-UI", + "version", VERSION, + "website", PURPLE_WEBSITE, + "support-website", PURPLE_WEBSITE, + "client-type", "test", + NULL); +} static gboolean test_ui_init_history(GError **error) { @@ -101,7 +131,7 @@ test_ui_init_history(GError **error) { void test_ui_purple_init(void) { - PurpleUiInfo *ui_info = NULL; + PurpleUi *ui = NULL; GError *error = NULL; #ifndef _WIN32 @@ -116,21 +146,12 @@ test_ui_purple_init(void) { /* set the magic PURPLE_PLUGINS_SKIP environment variable */ g_setenv("PURPLE_PLUGINS_SKIP", "1", TRUE); - /* Set the core-uiops, which is used to - * - initialize the ui specific preferences. - * - initialize the debug ui. - * - initialize the ui components for all the modules. - * - uninitialize the ui components for all the modules when the core terminates. - */ - purple_core_set_ui_ops(&test_core_uiops); - - ui_info = purple_ui_info_new("test", "Test-UI", VERSION, PURPLE_WEBSITE, - PURPLE_WEBSITE, "test"); + ui = test_purple_ui_new(); /* Now that all the essential stuff has been set, let's try to init the core. It's * necessary to provide a non-NULL name for the current ui to the core. This name * is used by stuff that depends on this ui, for example the ui-specific plugins. */ - if (!purple_core_init(ui_info)) { + if (!purple_core_init(ui)) { /* Initializing the core failed. Terminate. */ fprintf(stderr, "libpurple initialization failed. Dumping core.\n" diff --git a/pidgin/gtkconv.h b/pidgin/gtkconv.h index f76d207271..cc075264c7 100644 --- a/pidgin/gtkconv.h +++ b/pidgin/gtkconv.h @@ -26,6 +26,8 @@ #ifndef _PIDGIN_CONVERSATION_H_ #define _PIDGIN_CONVERSATION_H_ +#include <gtk/gtk.h> + typedef struct _PidginConversation PidginConversation; enum { diff --git a/pidgin/libpidgin.c b/pidgin/libpidgin.c index 81a8d35237..24d089e2d2 100644 --- a/pidgin/libpidgin.c +++ b/pidgin/libpidgin.c @@ -30,31 +30,12 @@ #include <glib/gi18n-lib.h> #include <glib/gstdio.h> -#define G_SETTINGS_ENABLE_BACKEND -#include <gio/gsettingsbackend.h> - #include <locale.h> #include <purple.h> -#include "gtkaccount.h" -#include "gtkblist.h" -#include "gtkconn.h" -#include "gtkxfer.h" -#include "gtkidle.h" -#include "gtkmedia.h" -#include "gtknotify.h" -#include "gtkprivacy.h" -#include "gtkrequest.h" -#include "gtkroomlist.h" -#include "gtkutils.h" -#include "gtkwhiteboard.h" #include "pidginapplication.h" #include "pidgincore.h" -#include "pidgindebug.h" -#include "pidginplugininfo.h" -#include "pidginprefs.h" -#include "pidginprivate.h" #ifndef _WIN32 #include <signal.h> @@ -154,181 +135,6 @@ mainloop_sighandler(GIOChannel *source, GIOCondition cond, gpointer data) } #endif /* !_WIN32 */ -static void -purple_ui_add_protocol_theme_paths(PurpleProtocol *protocol) { - GdkDisplay *display = NULL; - GtkIconTheme *theme = NULL; - const gchar *path = NULL; - - display = gdk_display_get_default(); - - theme = gtk_icon_theme_get_for_display(display); - - path = purple_protocol_get_icon_search_path(protocol); - if(path != NULL) { - gtk_icon_theme_add_search_path(theme, path); - } - - path = purple_protocol_get_icon_resource_path(protocol); - if(path != NULL) { - gtk_icon_theme_add_resource_path(theme, path); - } -} - -static void -purple_ui_protocol_foreach_theme_cb(PurpleProtocol *protocol, gpointer data) { - purple_ui_add_protocol_theme_paths(protocol); -} - -static void -purple_ui_protocol_registered_cb(PurpleProtocolManager *manager, - PurpleProtocol *protocol) -{ - purple_ui_add_protocol_theme_paths(protocol); -} - -static gboolean -pidgin_history_init(GError **error) { - PurpleHistoryManager *manager = NULL; - PurpleHistoryAdapter *adapter = NULL; - gchar *filename = NULL; - const gchar *id = NULL; - - manager = purple_history_manager_get_default(); - - /* Attempt to create the config_dir. We don't care about the result as the - * logging adapter will fail with a better error than us failing to create - * the directory. - */ - g_mkdir_with_parents(purple_config_dir(), 0700); - - filename = g_build_filename(purple_config_dir(), "history.db", NULL); - adapter = purple_sqlite_history_adapter_new(filename); - g_free(filename); - - id = purple_history_adapter_get_id(adapter); - if(!purple_history_manager_register(manager, adapter, error)) { - g_clear_object(&adapter); - - return FALSE; - } - - /* The manager adds a ref to the adapter on registration, so we can remove - * our reference. - */ - g_clear_object(&adapter); - - return purple_history_manager_set_active(manager, id, error); -} - -static void -pidgin_ui_init(void) -{ - PurpleProtocolManager *protocol_manager = NULL; - GdkDisplay *display = NULL; - GtkIconTheme *theme = NULL; - GError *error = NULL; - gchar *path; - - pidgin_debug_init(); - - display = gdk_display_get_default(); - theme = gtk_icon_theme_get_for_display(display); - - path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons", NULL); - gtk_icon_theme_add_search_path(theme, path); - g_free(path); - - /* Add a callback for when a protocol is registered to add its icon paths - * if it was found after initial startup. - */ - protocol_manager = purple_protocol_manager_get_default(); - g_signal_connect(protocol_manager, "registered", - G_CALLBACK(purple_ui_protocol_registered_cb), NULL); - - /* Add the icon paths for all the protocols that libpurple found at start - * up. - */ - purple_protocol_manager_foreach(protocol_manager, - purple_ui_protocol_foreach_theme_cb, NULL); - - if(!pidgin_history_init(&error)) { - g_critical("failed to initialize the history api: %s", - error != NULL ? error->message : "unknown"); - g_clear_error(&error); - } - - /* Set the UI operation structures. */ - purple_xfers_set_ui_ops(pidgin_xfers_get_ui_ops()); - purple_blist_set_ui(PIDGIN_TYPE_BUDDY_LIST); - purple_notify_set_ui_ops(pidgin_notify_get_ui_ops()); - purple_request_set_ui_ops(pidgin_request_get_ui_ops()); - purple_connections_set_ui_ops(pidgin_connections_get_ui_ops()); - purple_whiteboard_set_ui_ops(pidgin_whiteboard_get_ui_ops()); - purple_idle_set_ui(pidgin_idle_new()); - - pidgin_accounts_init(); - pidgin_connection_init(); - pidgin_request_init(); - pidgin_blist_init(); - pidgin_conversations_init(); - pidgin_commands_init(); - pidgin_privacy_init(); - pidgin_xfers_init(); - pidgin_roomlist_init(); - pidgin_medias_init(); - pidgin_notify_init(); -} - -static void -pidgin_quit(void) -{ - /* Uninit */ - - /* Be sure to close all windows that are not attached to anything - * (e.g., the debug window), or they may access things after they are - * shut down. */ - pidgin_notify_uninit(); - pidgin_commands_uninit(); - pidgin_conversations_uninit(); - pidgin_blist_uninit(); - pidgin_request_uninit(); - pidgin_connection_uninit(); - pidgin_accounts_uninit(); - pidgin_xfers_uninit(); - pidgin_debug_window_hide(); - pidgin_debug_uninit(); - - /* and end it all... */ - g_application_quit(g_application_get_default()); -} - -static gpointer -pidgin_get_settings_backend(void) { - GSettingsBackend *backend = NULL; - char *config = NULL; - - config = g_build_filename(purple_config_dir(), "pidgin3.ini", NULL); - backend = g_keyfile_settings_backend_new(config, "/", NULL); - - g_free(config); - - return backend; -} - -static PurpleCoreUiOps core_ops = { - .ui_prefs_init = pidgin_prefs_init, - .ui_init = pidgin_ui_init, - .quit = pidgin_quit, - .get_settings_backend = pidgin_get_settings_backend, -}; - -PurpleCoreUiOps * -pidgin_core_get_ui_ops(void) -{ - return &core_ops; -} - #ifndef _WIN32 static void pidgin_setup_error_handler(void) diff --git a/pidgin/meson.build b/pidgin/meson.build index 67550c9e45..5b6560c53f 100644 --- a/pidgin/meson.build +++ b/pidgin/meson.build @@ -61,6 +61,7 @@ libpidgin_SOURCES = [ 'pidginstatusprimitivechooser.c', 'pidginstatusprimitivestore.c', 'pidgintalkatu.c', + 'pidginui.c', 'prefs/pidginprefs.c', 'prefs/pidginawayprefs.c', 'prefs/pidginconversationprefs.c', @@ -129,6 +130,7 @@ libpidgin_headers = [ 'pidginstatusprimitivechooser.h', 'pidginstatusprimitivestore.h', 'pidgintalkatu.h', + 'pidginui.h', ] libpidgin_prefs_headers = [ diff --git a/pidgin/pidginapplication.c b/pidgin/pidginapplication.c index 3e534a0281..5180d81255 100644 --- a/pidgin/pidginapplication.c +++ b/pidgin/pidginapplication.c @@ -52,9 +52,10 @@ #include "pidginmooddialog.h" #include "pidginpluginsdialog.h" #include "pidginpluginsmenu.h" +#include "pidginprefs.h" #include "pidginstatuseditor.h" #include "pidginstatusmanager.h" -#include "pidginprefs.h" +#include "pidginui.h" struct _PidginApplication { GtkApplication parent; @@ -745,7 +746,6 @@ pidgin_application_window_added(GtkApplication *application, static void pidgin_application_startup(GApplication *application) { PurpleAccountManager *manager = NULL; - PurpleUiInfo *ui_info = NULL; GList *active_accounts = NULL; gpointer handle = NULL; @@ -780,13 +780,7 @@ pidgin_application_startup(GApplication *application) { winpidgin_init(); #endif - purple_core_set_ui_ops(pidgin_core_get_ui_ops()); - - ui_info = purple_ui_info_new("pidgin3", PIDGIN_NAME, VERSION, - "https://pidgin.im", - "https://developer.pidgin.im", "pc"); - - if(!purple_core_init(ui_info)) { + if(!purple_core_init(pidgin_ui_new())) { fprintf(stderr, _("Initialization of the libpurple core failed. Aborting!\n" "Please report this!\n")); diff --git a/pidgin/pidgincore.h b/pidgin/pidgincore.h index ea73ae5d24..46d8b85a0d 100644 --- a/pidgin/pidgincore.h +++ b/pidgin/pidgincore.h @@ -61,17 +61,5 @@ */ int pidgin_start(int argc, char *argv[]); -/** - * pidgin_core_get_ui_ops: - * - * Gets the #PurpleCoreUiOps that Pidgin sets up. You probably don't want to - * call this. - * - * Returns: The #PurpleCoreUiOps for Pidgin. - * - * Since: 3.0.0 - */ -PurpleCoreUiOps *pidgin_core_get_ui_ops(void); - #endif /* PIDGIN_CORE_H */ diff --git a/pidgin/pidginui.c b/pidgin/pidginui.c new file mode 100644 index 0000000000..88e514e751 --- /dev/null +++ b/pidgin/pidginui.c @@ -0,0 +1,263 @@ +/* + * Pidgin - Internet Messenger + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <glib.h> +#include <glib/gi18n.h> + +#define G_SETTINGS_ENABLE_BACKEND +#include <gio/gsettingsbackend.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pidginui.h" + +#include "gtkaccount.h" +#include "gtkblist.h" +#include "gtkconn.h" +#include "gtkconv.h" +#include "gtkidle.h" +#include "gtkmedia.h" +#include "gtknotify.h" +#include "gtkprivacy.h" +#include "gtkroomlist.h" +#include "gtkrequest.h" +#include "gtkwhiteboard.h" +#include "gtkxfer.h" +#include "pidgincore.h" +#include "pidgindebug.h" +#include "pidginprefs.h" +#include "pidginprivate.h" + +struct _PidginUi { + PurpleUi parent; +}; + +G_DEFINE_TYPE(PidginUi, pidgin_ui, PURPLE_TYPE_UI) + +/****************************************************************************** + * Helpers + *****************************************************************************/ +static gboolean +pidgin_history_init(GError **error) { + PurpleHistoryManager *manager = NULL; + PurpleHistoryAdapter *adapter = NULL; + gchar *filename = NULL; + const gchar *id = NULL; + + manager = purple_history_manager_get_default(); + + /* Attempt to create the config_dir. We don't care about the result as the + * logging adapter will fail with a better error than us failing to create + * the directory. + */ + g_mkdir_with_parents(purple_config_dir(), 0700); + + filename = g_build_filename(purple_config_dir(), "history.db", NULL); + adapter = purple_sqlite_history_adapter_new(filename); + g_free(filename); + + id = purple_history_adapter_get_id(adapter); + if(!purple_history_manager_register(manager, adapter, error)) { + g_clear_object(&adapter); + + return FALSE; + } + + /* The manager adds a ref to the adapter on registration, so we can remove + * our reference. + */ + g_clear_object(&adapter); + + return purple_history_manager_set_active(manager, id, error); +} + +static void +pidgin_ui_add_protocol_theme_paths(PurpleProtocol *protocol) { + GdkDisplay *display = NULL; + GtkIconTheme *theme = NULL; + const gchar *path = NULL; + + display = gdk_display_get_default(); + + theme = gtk_icon_theme_get_for_display(display); + + path = purple_protocol_get_icon_search_path(protocol); + if(path != NULL) { + gtk_icon_theme_add_search_path(theme, path); + } + + path = purple_protocol_get_icon_resource_path(protocol); + if(path != NULL) { + gtk_icon_theme_add_resource_path(theme, path); + } +} + +/****************************************************************************** + * Callbacks + *****************************************************************************/ +static void +pidgin_ui_protocol_foreach_theme_cb(PurpleProtocol *protocol, + G_GNUC_UNUSED gpointer data) +{ + pidgin_ui_add_protocol_theme_paths(protocol); +} + +static void +pidgin_ui_protocol_registered_cb(G_GNUC_UNUSED PurpleProtocolManager *manager, + PurpleProtocol *protocol) +{ + pidgin_ui_add_protocol_theme_paths(protocol); +} + +/****************************************************************************** + * PurpleUi Implementation + *****************************************************************************/ +static void +pidgin_ui_prefs_init(G_GNUC_UNUSED PurpleUi *ui) { + pidgin_prefs_init(); +} + +static void +pidgin_ui_start(G_GNUC_UNUSED PurpleUi *ui) { + PurpleProtocolManager *protocol_manager = NULL; + GdkDisplay *display = NULL; + GtkIconTheme *theme = NULL; + GError *error = NULL; + gchar *path; + + pidgin_debug_init(); + + display = gdk_display_get_default(); + theme = gtk_icon_theme_get_for_display(display); + + path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons", NULL); + gtk_icon_theme_add_search_path(theme, path); + g_free(path); + + /* Add a callback for when a protocol is registered to add its icon paths + * if it was found after initial startup. + */ + protocol_manager = purple_protocol_manager_get_default(); + g_signal_connect(protocol_manager, "registered", + G_CALLBACK(pidgin_ui_protocol_registered_cb), NULL); + + /* Add the icon paths for all the protocols that libpurple found at start + * up. + */ + purple_protocol_manager_foreach(protocol_manager, + pidgin_ui_protocol_foreach_theme_cb, NULL); + + if(!pidgin_history_init(&error)) { + g_critical("failed to initialize the history api: %s", + error != NULL ? error->message : "unknown"); + g_clear_error(&error); + } + + /* Set the UI operation structures. */ + purple_xfers_set_ui_ops(pidgin_xfers_get_ui_ops()); + purple_blist_set_ui(PIDGIN_TYPE_BUDDY_LIST); + purple_notify_set_ui_ops(pidgin_notify_get_ui_ops()); + purple_request_set_ui_ops(pidgin_request_get_ui_ops()); + purple_connections_set_ui_ops(pidgin_connections_get_ui_ops()); + purple_whiteboard_set_ui_ops(pidgin_whiteboard_get_ui_ops()); + purple_idle_set_ui(pidgin_idle_new()); + + pidgin_accounts_init(); + pidgin_connection_init(); + pidgin_request_init(); + pidgin_blist_init(); + pidgin_conversations_init(); + pidgin_commands_init(); + pidgin_privacy_init(); + pidgin_xfers_init(); + pidgin_roomlist_init(); + pidgin_medias_init(); + pidgin_notify_init(); +} + +static void +pidgin_ui_stop(G_GNUC_UNUSED PurpleUi *ui) { + /* Be sure to close all windows that are not attached to anything + * (e.g., the debug window), or they may access things after they are + * shut down. */ + pidgin_notify_uninit(); + pidgin_commands_uninit(); + pidgin_conversations_uninit(); + pidgin_blist_uninit(); + pidgin_request_uninit(); + pidgin_connection_uninit(); + pidgin_accounts_uninit(); + pidgin_xfers_uninit(); + pidgin_debug_window_hide(); + pidgin_debug_uninit(); + + /* and end it all... */ + g_application_quit(g_application_get_default()); +} + +static gpointer +pidgin_ui_get_settings_backend(G_GNUC_UNUSED PurpleUi *ui) { + GSettingsBackend *backend = NULL; + char *config = NULL; + + config = g_build_filename(purple_config_dir(), "pidgin3.ini", NULL); + backend = g_keyfile_settings_backend_new(config, "/", NULL); + + g_free(config); + + return backend; +} + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +pidgin_ui_init(G_GNUC_UNUSED PidginUi *ui) { +} + +static void +pidgin_ui_class_init(PidginUiClass *klass) { + PurpleUiClass *ui_class = PURPLE_UI_CLASS(klass); + + ui_class->prefs_init = pidgin_ui_prefs_init; + ui_class->start = pidgin_ui_start; + ui_class->stop = pidgin_ui_stop; + ui_class->get_settings_backend = pidgin_ui_get_settings_backend; +} + +/****************************************************************************** + * Public UI + *****************************************************************************/ +PurpleUi * +pidgin_ui_new(void) { + return g_object_new( + PIDGIN_TYPE_UI, + "id", "pidgin3", + "name", PIDGIN_NAME, + "version", VERSION, + "website", "https://pidgin.im", + "support-website", "https://pidgin.im/contact/", + "client-type", "pc", + NULL); +} diff --git a/pidgin/pidginui.h b/pidgin/pidginui.h new file mode 100644 index 0000000000..915b165610 --- /dev/null +++ b/pidgin/pidginui.h @@ -0,0 +1,60 @@ +/* + * Pidgin - Internet Messenger + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION) +# error "only <pidgin.h> may be included directly" +#endif + +#ifndef PIDGIN_UI_H +#define PIDGIN_UI_H + +#include <glib.h> + +#include <purple.h> + +G_BEGIN_DECLS + +/** + * PidginUi: + * + * Is a subclass of [class@Purple.Ui] that identifies Pidgin to libpurple. + * + * Since: 3.0.0 + */ + +#define PIDGIN_TYPE_UI (pidgin_ui_get_type()) +G_DECLARE_FINAL_TYPE(PidginUi, pidgin_ui, PIDGIN, UI, PurpleUi) + +/** + * pidgin_ui_new: + * + * Creates the new [class@Pidgin.Ui] instance. + * + * Note: there's not much use for this outside of Pidgin's internal code. + * + * Returns: (transfer full): The new instance. + */ +PurpleUi *pidgin_ui_new(void); + +G_END_DECLS + +#endif /* PIDGIN_UI_H */ diff --git a/po/POTFILES.in b/po/POTFILES.in index e7ae75de87..b7b6681a4b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -188,7 +188,6 @@ libpurple/purplecontact.c libpurple/purpleconversation.c libpurple/purpleconversationmanager.c libpurple/purpleconversationuiops.c -libpurple/purplecoreuiops.c libpurple/purplecredentialmanager.c libpurple/purplecredentialprovider.c libpurple/purpledebugui.c @@ -219,7 +218,7 @@ libpurple/purpleprotocolroomlist.c libpurple/purpleprotocolserver.c libpurple/purpleprotocolwhiteboard.c libpurple/purplesqlitehistoryadapter.c -libpurple/purpleuiinfo.c +libpurple/purpleui.c libpurple/purplewhiteboard.c libpurple/purplewhiteboardmanager.c libpurple/purplewhiteboarduiops.c |