aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
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/main.c
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/main.c')
-rwxr-xr-xsrc/main.c493
1 files changed, 493 insertions, 0 deletions
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;
+}