aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Tari <robert@tari.in>2024-08-27 14:43:59 +0200
committerRobert Tari <robert@tari.in>2024-08-27 14:43:59 +0200
commit269aa4c7df03e1e581c01866c91bcfa5524d6334 (patch)
tree2fcd022cbfcb82537b15ae334b563cfaf16e5dde /src
parent4bfbd579171d9194956376c7153f378ff6eb9d4e (diff)
downloadayatana-settings-269aa4c7df03e1e581c01866c91bcfa5524d6334.tar.gz
ayatana-settings-269aa4c7df03e1e581c01866c91bcfa5524d6334.tar.bz2
ayatana-settings-269aa4c7df03e1e581c01866c91bcfa5524d6334.zip
Rewrite using C/CMake/Gtk4 and add some features/tweaks
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/glib.h61
-rw-r--r--src/gtk.h210
-rwxr-xr-xsrc/main.c493
4 files changed, 773 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..cb68f96
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,9 @@
+# ayatana-settings
+
+set_source_files_properties ("${CMAKE_BINARY_DIR}/data/${CMAKE_PROJECT_NAME}-gresource.c" PROPERTIES GENERATED TRUE)
+add_executable ("ayatana-settings" "main.c" "${CMAKE_BINARY_DIR}/data/${CMAKE_PROJECT_NAME}-gresource.c")
+add_dependencies ("ayatana-settings" "data")
+target_compile_definitions ("ayatana-settings" PUBLIC G_LOG_DOMAIN="${CMAKE_PROJECT_NAME}" LOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" GETTEXT_PACKAGE="${CMAKE_PROJECT_NAME}")
+target_link_libraries ("ayatana-settings" ${DEPS_LIBRARIES})
+target_include_directories ("ayatana-settings" PUBLIC ${DEPS_INCLUDE_DIRS})
+install (TARGETS "ayatana-settings" RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
diff --git a/src/glib.h b/src/glib.h
new file mode 100644
index 0000000..be9cb06
--- /dev/null
+++ b/src/glib.h
@@ -0,0 +1,61 @@
+#ifndef __GLIB__
+#define __GLIB__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+static inline void file_Copy (gchar *sPathIn, gchar *sPathOut)
+{
+ GError *pError = NULL;
+ GFile *pFileIn = g_file_new_for_path (sPathIn);
+ GFile *pFileOut = g_file_new_for_path (sPathOut);
+ g_file_copy (pFileIn, pFileOut, G_FILE_COPY_NONE, NULL, NULL, NULL, &pError);
+ g_object_unref (pFileIn);
+ g_object_unref (pFileOut);
+
+ if (pError)
+ {
+ g_error ("Panic: Failed copying file from %s to %s: %s", sPathIn, sPathOut, pError->message);
+ g_clear_error (&pError);
+
+ return;
+ }
+}
+
+static inline gboolean string_Equal (gchar *sText, gchar *sText2)
+{
+ gint nEquality = g_strcmp0 (sText, sText2);
+
+ return (nEquality == 0);
+}
+
+static inline guint string_Length (gchar *sText)
+{
+ glong nLength = g_utf8_strlen (sText, -1);
+
+ return nLength;
+}
+
+static inline gchar* string_Replace (gchar *sText, gchar *sFind, gchar *sReplace)
+{
+ GString *sString = g_string_new (sText);
+ g_string_replace (sString, sFind, sReplace, 0);
+ gchar *sNewText = g_string_free_and_steal (sString);
+
+ return sNewText;
+}
+
+static inline gchar* string_Remove (gchar *sText, gchar *sRemove)
+{
+ gchar *sNewText = string_Replace (sText, sRemove, "");
+
+ return sNewText;
+}
+
+#define string_ToInt atoi
+
+G_END_DECLS
+
+#endif
diff --git a/src/gtk.h b/src/gtk.h
new file mode 100644
index 0000000..fc01b3c
--- /dev/null
+++ b/src/gtk.h
@@ -0,0 +1,210 @@
+#ifndef __GTK__
+#define __GTK__
+
+#include <glib/gi18n.h>
+#include <locale.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ gchar *sId;
+ GCallback pCallback;
+} ApplicationCallbackSymbol;
+
+typedef struct
+{
+ gchar *sUi;
+ GCallback pCallback;
+ ApplicationCallbackSymbol *lSymbols;
+} ApplicationStartup;
+
+static GtkBuilder *m_pBuilder = NULL;
+static GSettings *m_pDesktopSettings = NULL;
+static GSettings *m_pA11ySettings = NULL;
+
+static inline void application_OnShutdown (GApplication *pApplication, gpointer pData)
+{
+ if (pData)
+ {
+ GCallback pCallback = (GCallback) pData;
+ pCallback ();
+ }
+
+ g_object_unref (m_pBuilder);
+ g_clear_object (&m_pDesktopSettings);
+ g_clear_object (&m_pA11ySettings);
+}
+
+static inline GObject* application_GetObject (gchar *sId)
+{
+ GObject *pObject = gtk_builder_get_object (m_pBuilder, sId);
+
+ return pObject;
+}
+
+static inline void application_OnActivate (GApplication *pApplication, gpointer pData)
+{
+ GList *lWindows = gtk_application_get_windows (GTK_APPLICATION (pApplication));
+
+ if (lWindows)
+ {
+ return;
+ }
+
+ GObject *pWindow = gtk_builder_get_object (m_pBuilder, "window");
+ gtk_window_present (GTK_WINDOW (pWindow));
+ gtk_application_add_window (GTK_APPLICATION (pApplication), GTK_WINDOW (pWindow));
+ GCallback pCallback = (GCallback) pData;
+
+ if (pCallback)
+ {
+ pCallback ();
+ }
+}
+
+static inline void application_onThemeChanged (GSettings *pSettings, const gchar *sKey, gpointer pData)
+{
+ gchar *sColorScheme = g_settings_get_string (m_pDesktopSettings, "color-scheme");
+ gboolean bDark = string_Equal (sColorScheme, "prefer-dark");
+ g_free (sColorScheme);
+ gboolean bHighContrast = g_settings_get_boolean (m_pA11ySettings, "high-contrast");
+ GtkSettings *pGtkSettings = gtk_settings_get_default ();
+
+ if (bHighContrast && bDark)
+ {
+ g_object_set (pGtkSettings, "gtk-theme-name", "Default-hc-dark", NULL);
+ }
+ else if (bHighContrast)
+ {
+ g_object_set (pGtkSettings, "gtk-theme-name", "Default-hc", NULL);
+ }
+ else if (bDark)
+ {
+ gtk_settings_reset_property (pGtkSettings, "gtk-theme-name");
+ }
+ else
+ {
+ gtk_settings_reset_property (pGtkSettings, "gtk-theme-name");
+ }
+
+ g_object_set (pGtkSettings, "gtk-application-prefer-dark-theme", bDark, NULL);
+}
+
+static inline void application_OnStartup (GApplication *pApplication, gpointer pData)
+{
+ ApplicationStartup *pStartup = (ApplicationStartup*) pData;
+ m_pBuilder = gtk_builder_new ();
+ GtkBuilderScope *pScope = gtk_builder_get_scope (m_pBuilder);
+ guint nId = 0;
+
+ while (pStartup->lSymbols[nId].pCallback != NULL)
+ {
+ gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (pScope), pStartup->lSymbols[nId].sId, pStartup->lSymbols[nId].pCallback);
+ nId++;
+ }
+
+ gtk_builder_add_from_resource (m_pBuilder, pStartup->sUi, NULL);
+ g_free (pStartup->sUi);
+ gtk_builder_set_translation_domain (m_pBuilder, GETTEXT_PACKAGE);
+ GSettingsSchemaSource *pSource = g_settings_schema_source_get_default ();
+ GSettingsSchema *pSchema = g_settings_schema_source_lookup (pSource, "org.gnome.desktop.interface", FALSE);
+
+ if (pSchema)
+ {
+ gboolean bKey = g_settings_schema_has_key (pSchema, "color-scheme");
+ g_settings_schema_unref (pSchema);
+
+ if (bKey)
+ {
+ m_pDesktopSettings = g_settings_new ("org.gnome.desktop.interface");
+ g_signal_connect (m_pDesktopSettings, "changed::color-scheme", G_CALLBACK (application_onThemeChanged), NULL);
+ }
+ }
+
+ pSchema = g_settings_schema_source_lookup (pSource, "org.gnome.desktop.a11y.interface", FALSE);
+
+ if (pSchema)
+ {
+ gboolean bKey = g_settings_schema_has_key (pSchema, "high-contrast");
+ g_settings_schema_unref (pSchema);
+
+ if (bKey)
+ {
+ m_pA11ySettings = g_settings_new ("org.gnome.desktop.a11y.interface");
+ g_signal_connect (m_pA11ySettings, "changed::high-contrast", G_CALLBACK (application_onThemeChanged), NULL);
+ }
+ }
+
+ if (m_pDesktopSettings && m_pA11ySettings)
+ {
+ application_onThemeChanged (NULL, NULL, NULL);
+ }
+
+ if (pStartup->pCallback)
+ {
+ pStartup->pCallback ();
+ }
+}
+
+static inline gint application_Init (ApplicationCallbackSymbol *lSymbols, gchar *sId, GCallback pOnStartup, GCallback pOnActivate, GCallback pOnShutdown, gint argc, gchar *argv[])
+{
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ GtkApplication *pApplication = gtk_application_new (sId, G_APPLICATION_DEFAULT_FLAGS);
+ gchar *sReplaced = string_Replace (sId, ".", "/");
+ gchar *sConcatenated = g_strconcat ("/", sReplaced, "/", GETTEXT_PACKAGE, ".ui", NULL);
+ g_free (sReplaced);
+ ApplicationStartup cApplicationStartup = {sConcatenated, pOnStartup, lSymbols};
+ g_signal_connect (pApplication, "startup", G_CALLBACK (application_OnStartup), &cApplicationStartup);
+ g_signal_connect (pApplication, "activate", G_CALLBACK (application_OnActivate), pOnActivate);
+ g_signal_connect (pApplication, "shutdown", G_CALLBACK (application_OnShutdown), pOnShutdown);
+ gint nStatus = g_application_run (G_APPLICATION (pApplication), argc, argv);
+ g_object_unref (pApplication);
+
+ return nStatus;
+}
+
+static inline void listview_SetStringListFactory (gchar *sListView)
+{
+ const char *sFactory =
+ "<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<interface>\n"
+ " <template class='GtkListItem'>\n"
+ " <property name='child'>\n"
+ " <object class='GtkInscription'>\n"
+ " <property name='xalign'>0</property>\n"
+ " <binding name='text'>\n"
+ " <lookup name='string' type='GtkStringObject'>\n"
+ " <lookup name='item'>GtkListItem</lookup>\n"
+ " </lookup>\n"
+ " </binding>\n"
+ " </object>\n"
+ " </property>\n"
+ " </template>\n"
+ "</interface>\n";
+
+ gsize nSize = strlen (sFactory);
+ GBytes *pBytes = g_bytes_new_static (sFactory, nSize);
+ GtkListItemFactory *pFactory = gtk_builder_list_item_factory_new_from_bytes (NULL, pBytes);
+ GtkListView *pListView = GTK_LIST_VIEW (application_GetObject (sListView));
+ gtk_list_view_set_factory (pListView, pFactory);
+}
+
+static inline void notebook_DisablePage (gchar *sPage)
+{
+ GtkNotebookPage *pPage = GTK_NOTEBOOK_PAGE (application_GetObject (sPage));
+ GtkWidget *pChild = gtk_notebook_page_get_child (pPage);
+ gtk_widget_set_sensitive (pChild, FALSE);
+ GtkWidget *pTab = NULL;
+ g_object_get (pPage, "tab", &pTab, NULL);
+ gtk_widget_set_sensitive (pTab, FALSE);
+ g_object_unref (pTab);
+}
+
+G_END_DECLS
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100755
index 0000000..028c78a
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,493 @@
+/*
+ Copyright 2020-2024 Robert Tari <robert@tari.in>
+
+ This file is part of Ayatana Settings.
+
+ Ayatana Settings 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 3 of the License, or
+ (at your option) any later version.
+
+ Ayatana Settings 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 Ayatana Settings. If not, see <http://www.gnu.org/licenses/gpl-3.0.txt>.
+*/
+
+#include "glib.h"
+#include "gtk.h"
+
+static gboolean m_bInit = FALSE;
+static gboolean m_bMate = FALSE;
+static GSettings *m_pSettingsSession = NULL;
+static GSettings *m_pSettingsDateTime = NULL;
+static GSettings *m_pSettingsSound = NULL;
+static GSettings *m_pSettingsPower = NULL;
+static GSettings *m_pSettingsNotifications = NULL;
+
+static gboolean isEnabled (gchar *sIndicator)
+{
+ gboolean bEnabled = TRUE;
+ const gchar *sHome = g_get_home_dir ();
+ gchar *sDesktop = g_strdup_printf (".config/autostart/ayatana-indicator-%s.desktop", sIndicator);
+ gchar *sPath = g_build_filename (sHome, sDesktop, NULL);
+ g_free (sDesktop);
+ gboolean bExists = g_file_test (sPath, G_FILE_TEST_EXISTS);
+
+ if (bExists)
+ {
+ GKeyFile *pKeyFile = g_key_file_new ();
+ GError *pError = NULL;
+ g_key_file_load_from_file (pKeyFile, sPath, G_KEY_FILE_NONE, &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed loading key file: %s", pError->message);
+ g_clear_error (&pError);
+
+ return FALSE;
+ }
+
+ gboolean bKey = g_key_file_has_key (pKeyFile, "Desktop Entry", "X-MATE-Autostart-enabled", &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed parsing key file for X-MATE-Autostart-enabled: %s", pError->message);
+ g_clear_error (&pError);
+
+ return FALSE;
+ }
+
+ if (bKey)
+ {
+ bEnabled = g_key_file_get_boolean (pKeyFile, "Desktop Entry", "X-MATE-Autostart-enabled", &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed getting the value of X-MATE-Autostart-enabled from the key file: %s", pError->message);
+ g_clear_error (&pError);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ gboolean bKey = g_key_file_has_key (pKeyFile, "Desktop Entry", "X-GNOME-Autostart-enabled", &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed parsing key file for X-GNOME-Autostart-enabled: %s", pError->message);
+ g_clear_error (&pError);
+
+ return FALSE;
+ }
+
+ if (bKey)
+ {
+ bEnabled = g_key_file_get_boolean (pKeyFile, "Desktop Entry", "X-GNOME-Autostart-enabled", &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed getting the value of X-GNOME-Autostart-enabled from the key file: %s", pError->message);
+ g_clear_error (&pError);
+
+ return FALSE;
+ }
+ }
+ }
+
+ g_key_file_free (pKeyFile);
+ }
+
+ g_free (sPath);
+
+ return bEnabled;
+}
+
+static void onToggleButtonEnableToggled (GtkToggleButton *pButton, gpointer pData)
+{
+ if (!m_bInit)
+ {
+ return;
+ }
+
+ const gchar *sHome = g_get_home_dir ();
+ gchar *sAutostartFolder = g_build_filename (sHome, ".config/autostart", NULL);
+ gboolean bExists = g_file_test (sAutostartFolder, G_FILE_TEST_IS_DIR);
+
+ if (!bExists)
+ {
+ g_mkdir_with_parents (sAutostartFolder, 755);
+ }
+
+ g_free (sAutostartFolder);
+ const gchar *sIndicator = gtk_widget_get_name (GTK_WIDGET (pButton));
+ gchar *sDesktop = g_strdup_printf (".config/autostart/ayatana-indicator-%s.desktop", sIndicator);
+ gchar *sPath = g_build_filename (sHome, sDesktop, NULL);
+ g_free (sDesktop);
+ bExists = g_file_test (sPath, G_FILE_TEST_EXISTS);
+
+ if (!bExists)
+ {
+ gchar *sPathIn = g_strdup_printf ("/etc/xdg/autostart/ayatana-indicator-%s.desktop", sIndicator);
+ file_Copy (sPathIn, sPath);
+ g_free (sPathIn);
+ }
+
+ GKeyFile *pKeyFile = g_key_file_new ();
+ GError *pError = NULL;
+ g_key_file_load_from_file (pKeyFile, sPath, G_KEY_FILE_NONE, &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed loading key file: %s", pError->message);
+ g_clear_error (&pError);
+
+ return;
+ }
+
+ gboolean bEnabled = gtk_toggle_button_get_active (pButton);
+
+ if (m_bMate)
+ {
+ g_key_file_set_boolean (pKeyFile, "Desktop Entry", "X-MATE-Autostart-enabled", bEnabled);
+ }
+ else
+ {
+ g_key_file_set_boolean (pKeyFile, "Desktop Entry", "X-GNOME-Autostart-enabled", bEnabled);
+ }
+
+ g_key_file_save_to_file (pKeyFile, sPath, &pError);
+
+ if (pError)
+ {
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+ g_error ("Panic: Failed saving key file: %s", pError->message);
+ g_clear_error (&pError);
+
+ return;
+ }
+
+ g_key_file_free (pKeyFile);
+ g_free (sPath);
+}
+
+static void onSpinButtonNotificationsValueChanged (GtkSpinButton *pSpinButton, gpointer pData)
+{
+ gint nValue = gtk_spin_button_get_value_as_int (pSpinButton);
+ g_settings_set_int (m_pSettingsNotifications, "max-items", nValue);
+}
+
+static void saveFilterList ()
+{
+ GStrvBuilder *pBuilder = g_strv_builder_new ();
+ GtkStringList *pStringList = GTK_STRING_LIST (application_GetObject ("StringListNotificationsFilters"));
+ guint nItems = g_list_model_get_n_items (G_LIST_MODEL (pStringList));
+
+ for (guint nItem = 0; nItem < nItems; nItem++)
+ {
+ const gchar *sModelText = gtk_string_list_get_string (pStringList, nItem);
+ g_strv_builder_add (pBuilder, (gchar*) sModelText);
+ }
+
+ GStrv lItems = g_strv_builder_end (pBuilder);
+ g_strv_builder_unref (pBuilder);
+ g_settings_set_strv (m_pSettingsNotifications, "filter-list", (const char* const*) lItems);
+ g_strfreev (lItems);
+}
+
+static void onButtonNotificationsAddClicked (GtkButton *pButton, gpointer pData)
+{
+ GObject *pEntryNotifications = application_GetObject ("EntryNotifications");
+ const gchar *sText = gtk_editable_get_text (GTK_EDITABLE (pEntryNotifications));
+ gchar *sTextDup = g_strdup (sText);
+ g_strstrip (sTextDup);
+ guint nLength = string_Length (sTextDup);
+
+ if (nLength)
+ {
+ gboolean bDuplicate = FALSE;
+ GtkStringList *pStringList = GTK_STRING_LIST (application_GetObject ("StringListNotificationsFilters"));
+ guint nItems = g_list_model_get_n_items (G_LIST_MODEL (pStringList));
+
+ for (guint nItem = 0; nItem < nItems; nItem++)
+ {
+ const gchar *sModelText = gtk_string_list_get_string (pStringList, nItem);
+ gboolean bEqual = string_Equal ((gchar*) sModelText, (gchar*) sText);
+
+ if (bEqual)
+ {
+ bDuplicate = TRUE;
+
+ break;
+ }
+ }
+
+ if (!bDuplicate)
+ {
+ gtk_string_list_append (pStringList, sTextDup);
+ saveFilterList ();
+ }
+ }
+
+ g_free (sTextDup);
+ gtk_editable_set_text (GTK_EDITABLE (pEntryNotifications), "");
+}
+
+static void onButtonNotificationsRemoveClicked (GtkButton *pButton, gpointer pData)
+{
+ GtkSingleSelection *pSelection = GTK_SINGLE_SELECTION (application_GetObject ("SingleSelectionNotifications"));
+ guint nSelected = gtk_single_selection_get_selected (pSelection);
+ GtkStringList *pStringList = GTK_STRING_LIST (application_GetObject ("StringListNotificationsFilters"));
+
+ if (nSelected != GTK_INVALID_LIST_POSITION)
+ {
+ gtk_string_list_remove (pStringList, nSelected);
+ saveFilterList ();
+ }
+}
+
+static void onActivate ()
+{
+ GSettingsSchemaSource *pSource = g_settings_schema_source_get_default ();
+ GSettingsSchema *pSchema = NULL;
+ GObject *pSwitch = NULL;
+
+ // Session
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.session", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ m_pSettingsSession = g_settings_new ("org.ayatana.indicator.session");
+ pSwitch = application_GetObject ("SwitchSessionShowName");
+ g_settings_bind (m_pSettingsSession, "show-real-name-on-panel", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchSessionRemoveLogOut");
+ g_settings_bind (m_pSettingsSession, "suppress-logout-menuitem", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchSessionSuppressConfirmation");
+ g_settings_bind (m_pSettingsSession, "suppress-logout-restart-shutdown", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchSessionRemoveRestart");
+ g_settings_bind (m_pSettingsSession, "suppress-restart-menuitem", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchSessionRemoveShutDown");
+ g_settings_bind (m_pSettingsSession, "suppress-shutdown-menuitem", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchSessionShowUsers");
+ g_settings_bind (m_pSettingsSession, "user-show-menu", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ gboolean bEnabled = isEnabled ("session");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonSessionEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageSession");
+ }
+ //~Session
+
+ // Date/Time
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.datetime", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ m_pSettingsDateTime = g_settings_new ("org.ayatana.indicator.datetime");
+ pSwitch = application_GetObject ("SwitchDatetimeShowCalendar");
+ g_settings_bind (m_pSettingsDateTime, "show-calendar", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowDate");
+ g_settings_bind (m_pSettingsDateTime, "show-date", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowDay");
+ g_settings_bind (m_pSettingsDateTime, "show-day", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowEvents");
+ g_settings_bind (m_pSettingsDateTime, "show-events", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowSeconds");
+ g_settings_bind (m_pSettingsDateTime, "show-seconds", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowWeekNumbers");
+ g_settings_bind (m_pSettingsDateTime, "show-week-numbers", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchDatetimeShowYear");
+ g_settings_bind (m_pSettingsDateTime, "show-year", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ gboolean bEnabled = isEnabled ("datetime");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonDatetimeEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageDatetime");
+ }
+ //~Date/Time
+
+ // Sound
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.sound", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ m_pSettingsSound = g_settings_new ("org.ayatana.indicator.sound");
+ pSwitch = application_GetObject ("SwitchSoundAllowAmplified");
+ g_settings_bind (m_pSettingsSound, "allow-amplified-volume", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ gboolean bEnabled = isEnabled ("sound");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonSoundEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageSound");
+ }
+ //~Sound
+
+ // Power
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.power", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ m_pSettingsPower = g_settings_new ("org.ayatana.indicator.power");
+ pSwitch = application_GetObject ("SwitchPowerShowPercentage");
+ g_settings_bind (m_pSettingsPower, "show-percentage", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ pSwitch = application_GetObject ("SwitchPowerShowTime");
+ g_settings_bind (m_pSettingsPower, "show-time", pSwitch, "active", G_SETTINGS_BIND_DEFAULT);
+ gboolean bEnabled = isEnabled ("power");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonPowerEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPagePower");
+ }
+ //~Power
+
+ // Messages
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.messages", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ gboolean bEnabled = isEnabled ("messages");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonMessagesEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageMessages");
+ }
+ //~Messages
+
+ // Bluetooth
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.bluetooth", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ gboolean bEnabled = isEnabled ("bluetooth");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonBluetoothEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageBluetooth");
+ }
+ //~Bluetooth
+
+ // Notifications
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.notifications", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ m_pSettingsNotifications = g_settings_new ("org.ayatana.indicator.notifications");
+ gint nMaxItems = g_settings_get_int (m_pSettingsNotifications, "max-items");
+ GtkSpinButton *pSpinButton = GTK_SPIN_BUTTON (application_GetObject ("SpinButtonNotifications"));
+ gtk_spin_button_set_value (pSpinButton, nMaxItems);
+ GStrv lFilters = g_settings_get_strv (m_pSettingsNotifications, "filter-list");
+ guint nFilters = g_strv_length (lFilters);
+ listview_SetStringListFactory ("ListViewNotifications");
+ GtkStringList *pStringList = GTK_STRING_LIST (application_GetObject ("StringListNotificationsFilters"));
+
+ for (guint nFilter = 0; nFilter < nFilters; nFilter++)
+ {
+ gtk_string_list_append (pStringList, lFilters[nFilter]);
+ }
+
+ g_strfreev (lFilters);
+ GStrv lHints = g_settings_get_strv (m_pSettingsNotifications, "filter-list-hints");
+ guint nHints = g_strv_length (lHints);
+ pStringList = GTK_STRING_LIST (application_GetObject ("StringListNotificationsHints"));
+
+ for (guint nHint = 0; nHint < nHints; nHint++)
+ {
+ gtk_string_list_append (pStringList, lHints[nHint]);
+ }
+
+ g_strfreev (lHints);
+ // TODO: Entry completion replacement goes here, once available
+ gboolean bEnabled = isEnabled ("notifications");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonNotificationsEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageNotifications");
+ }
+ //~Notifications
+
+ // Keyboard
+ pSchema = g_settings_schema_source_lookup (pSource, "org.ayatana.indicator.keyboard", FALSE);
+
+ if (pSchema)
+ {
+ gboolean bEnabled = isEnabled ("keyboard");
+ GtkToggleButton *pToggleButton = GTK_TOGGLE_BUTTON (application_GetObject ("ToggleButtonKeyboardEnable"));
+ gtk_toggle_button_set_active (pToggleButton, bEnabled);
+ }
+ else
+ {
+ notebook_DisablePage ("NotebookPageKeyboard");
+ }
+ //~Keyboard
+
+ m_bInit = TRUE;
+}
+
+static void onShutdown ()
+{
+ g_clear_object (&m_pSettingsSession);
+ g_clear_object (&m_pSettingsDateTime);
+ g_clear_object (&m_pSettingsSound);
+ g_clear_object (&m_pSettingsPower);
+ g_clear_object (&m_pSettingsNotifications);
+}
+
+static void onStartup ()
+{
+ const gchar *sDesktop = g_getenv ("XDG_CURRENT_DESKTOP");
+ m_bMate = string_Equal ((gchar*) sDesktop, "MATE");
+}
+
+gint main (gint argc, gchar *argv[])
+{
+ ApplicationCallbackSymbol lSymbols[] =
+ {
+ {"onToggleButtonEnableToggled", G_CALLBACK (onToggleButtonEnableToggled)},
+ {"onButtonNotificationsRemoveClicked", G_CALLBACK (onButtonNotificationsRemoveClicked)},
+ {"onButtonNotificationsAddClicked", G_CALLBACK (onButtonNotificationsAddClicked)},
+ {"onSpinButtonNotificationsValueChanged", G_CALLBACK (onSpinButtonNotificationsValueChanged)},
+ {NULL, NULL}
+ };
+
+ gint nStatus = application_Init (lSymbols, "org.ayatana.ayatana-settings", onStartup, onActivate, onShutdown, argc, argv);
+
+ return nStatus;
+}