wckbuttons-dialogs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /* $Id$
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * Copyright (C) 2013 Cedric Leporcq <cedl38@gmail.com>
  18. *
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23. #include <string.h>
  24. #include <gtk/gtk.h>
  25. #include <libxfce4ui/libxfce4ui.h>
  26. #include <libxfce4panel/xfce-panel-plugin.h>
  27. #include <common/theme.h>
  28. #include "wckbuttons.h"
  29. #include "wckbuttons-theme.h"
  30. #include "wckbuttons-dialogs.h"
  31. #include "wckbuttons-dialogs_ui.h"
  32. enum
  33. {
  34. COL_THEME_NAME,
  35. COL_THEME_RC,
  36. N_COLUMNS
  37. };
  38. static void on_only_maximized_toggled(GtkRadioButton *only_maximized, WBPlugin *wb)
  39. {
  40. wb->prefs->only_maximized = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(only_maximized));
  41. reload_wnck (wb->win, wb->prefs->only_maximized, wb);
  42. }
  43. static void on_show_on_desktop_toggled(GtkToggleButton *show_on_desktop, WBPlugin *wb)
  44. {
  45. wb->prefs->show_on_desktop = gtk_toggle_button_get_active(show_on_desktop);
  46. reload_wnck (wb->win, wb->prefs->only_maximized, wb);
  47. }
  48. static void on_button_layout_changed (GtkEditable *entry, WBPlugin *wb)
  49. {
  50. if (gtk_widget_get_sensitive (GTK_WIDGET(entry)))
  51. {
  52. const gchar *button_layout = gtk_entry_get_text (GTK_ENTRY(entry));
  53. wb->prefs->button_layout = button_layout_filter (button_layout, wb->prefs->button_layout);
  54. if (wb->prefs->sync_wm_theme)
  55. {
  56. gchar *part;
  57. const gchar *layout;
  58. const gchar *wm_button_layout = xfconf_channel_get_string(wb->wm_channel, "/general/button_layout", "O|HMC");
  59. /* get opposite part of the layout and concatenate it */
  60. part = opposite_layout_filter (wm_button_layout);
  61. if (wm_button_layout[0] == part[0])
  62. layout = g_strconcat (part, wb->prefs->button_layout, NULL);
  63. else
  64. layout = g_strconcat (wb->prefs->button_layout, part, NULL);
  65. xfconf_channel_set_string (wb->wm_channel, "/general/button_layout", layout);
  66. g_free (part);
  67. }
  68. else
  69. {
  70. replace_buttons (wb->prefs->button_layout, wb);
  71. on_wck_state_changed (wb->win->controlwindow, wb);
  72. }
  73. }
  74. }
  75. static void
  76. wckbuttons_theme_selection_changed (GtkTreeSelection *selection,
  77. WBPlugin *wb)
  78. {
  79. GtkTreeModel *model;
  80. GtkTreeIter iter;
  81. const gchar *theme;
  82. GtkWidget *entry;
  83. if (gtk_tree_selection_get_selected (selection, &model, &iter))
  84. {
  85. gtk_tree_model_get (model, &iter, COL_THEME_NAME, &theme, -1);
  86. /* set the theme name */
  87. wb->prefs->theme = g_strdup (theme);
  88. entry = GTK_WIDGET(gtk_builder_get_object(wb->prefs->builder, "button_layout"));
  89. if (wb->prefs->sync_wm_theme)
  90. {
  91. gchar *button_layout;
  92. xfconf_channel_set_string (wb->wm_channel, "/general/theme", wb->prefs->theme);
  93. button_layout = get_rc_button_layout (theme);
  94. if (button_layout)
  95. {
  96. gtk_widget_set_sensitive (entry, FALSE);
  97. gtk_entry_set_text (GTK_ENTRY(entry), button_layout);
  98. }
  99. else
  100. {
  101. gtk_entry_set_text (GTK_ENTRY(entry), wb->prefs->button_layout);
  102. gtk_widget_set_sensitive (entry, TRUE);
  103. }
  104. g_free (button_layout);
  105. }
  106. else
  107. {
  108. load_theme (wb->prefs->theme, wb);
  109. replace_buttons (wb->prefs->button_layout, wb);
  110. on_wck_state_changed (wb->win->controlwindow, wb);
  111. }
  112. }
  113. }
  114. static void
  115. wckbuttons_load_themes (GtkWidget *theme_name_treeview, WBPlugin *wb)
  116. {
  117. GtkTreeModel *model;
  118. GHashTable *themes;
  119. GDir *dir;
  120. const gchar *file;
  121. gchar **theme_dirs;
  122. gchar *themedir;
  123. gint i;
  124. themes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  125. model = gtk_tree_view_get_model (GTK_TREE_VIEW (theme_name_treeview));
  126. /* clear any previous row */
  127. gtk_list_store_clear (GTK_LIST_STORE (model));
  128. xfce_resource_push_path (XFCE_RESOURCE_THEMES, DATADIR G_DIR_SEPARATOR_S "themes");
  129. theme_dirs = xfce_resource_dirs (XFCE_RESOURCE_THEMES);
  130. xfce_resource_pop_path (XFCE_RESOURCE_THEMES);
  131. for (i = 0; theme_dirs[i] != NULL; ++i)
  132. {
  133. dir = g_dir_open (theme_dirs[i], 0, NULL);
  134. if (G_UNLIKELY (dir == NULL))
  135. continue;
  136. while ((file = g_dir_read_name (dir)) != NULL)
  137. {
  138. /* check if there is not already a theme with the
  139. * same name in the database */
  140. if (g_hash_table_lookup (themes, file) == NULL)
  141. {
  142. GtkTreeIter iter;
  143. if (wb->prefs->sync_wm_theme)
  144. {
  145. if (!test_theme_dir(file, "xfwm4", THEMERC))
  146. continue;
  147. }
  148. themedir = get_unity_theme_dir (file, NULL);
  149. if (!themedir)
  150. continue;
  151. g_hash_table_insert (themes, g_strdup (file), GINT_TO_POINTER (1));
  152. /* insert in the list store */
  153. gtk_list_store_append (GTK_LIST_STORE (model), &iter);
  154. gtk_list_store_set (GTK_LIST_STORE (model), &iter,
  155. COL_THEME_NAME, file,
  156. COL_THEME_RC, g_path_get_basename (themedir), -1);
  157. if (G_UNLIKELY (g_str_equal (wb->prefs->theme, file)))
  158. {
  159. GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
  160. gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_name_treeview)),
  161. &iter);
  162. gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (theme_name_treeview), path, NULL, TRUE, 0.5, 0.5);
  163. gtk_tree_path_free (path);
  164. }
  165. g_free (themedir);
  166. }
  167. }
  168. g_dir_close (dir);
  169. }
  170. g_strfreev (theme_dirs);
  171. g_hash_table_destroy (themes);
  172. }
  173. static gint
  174. wckbuttons_theme_sort_func (GtkTreeModel *model,
  175. GtkTreeIter *iter1,
  176. GtkTreeIter *iter2)
  177. {
  178. gchar *str1 = NULL;
  179. gchar *str2 = NULL;
  180. gtk_tree_model_get (model, iter1, 0, &str1, -1);
  181. gtk_tree_model_get (model, iter2, 0, &str2, -1);
  182. if (str1 == NULL) str1 = g_strdup ("");
  183. if (str2 == NULL) str2 = g_strdup ("");
  184. return g_utf8_collate (str1, str2);
  185. }
  186. static void on_sync_wm_theme_toggled(GtkToggleButton *sync_wm_theme, WBPlugin *wb)
  187. {
  188. GtkWidget *theme_name_treeview;
  189. theme_name_treeview = GTK_WIDGET(gtk_builder_get_object(wb->prefs->builder, "theme_name_treeview"));
  190. wb->prefs->sync_wm_theme = gtk_toggle_button_get_active(sync_wm_theme);
  191. init_theme (wb);
  192. wckbuttons_load_themes (theme_name_treeview, wb);
  193. if (!wb->prefs->sync_wm_theme)
  194. {
  195. GtkWidget *entry;
  196. entry = GTK_WIDGET(gtk_builder_get_object(wb->prefs->builder, "button_layout"));
  197. gtk_widget_set_sensitive (entry, TRUE);
  198. gtk_entry_set_text (GTK_ENTRY(entry), wb->prefs->button_layout);
  199. }
  200. }
  201. static GtkWidget * build_properties_area(WBPlugin *wb, const gchar *buffer, gsize length) {
  202. GError *error = NULL;
  203. GObject *area = NULL;
  204. GtkRadioButton *only_maximized, *active_window;
  205. GtkToggleButton *show_on_desktop, *sync_wm_theme;
  206. GtkTreeSelection *selection;
  207. GtkCellRenderer *renderer;
  208. GtkListStore *list_store;
  209. GtkWidget *theme_name_treeview;
  210. GtkEntry *button_layout;
  211. wb->prefs->builder = gtk_builder_new();
  212. if (gtk_builder_add_from_string(wb->prefs->builder, buffer, length, &error)) {
  213. area = gtk_builder_get_object(wb->prefs->builder, "alignment0");
  214. if (G_LIKELY (area != NULL))
  215. {
  216. only_maximized = GTK_RADIO_BUTTON(gtk_builder_get_object(wb->prefs->builder, "only_maximized"));
  217. active_window = GTK_RADIO_BUTTON(gtk_builder_get_object(wb->prefs->builder, "active_window"));
  218. if (G_LIKELY (only_maximized != NULL))
  219. {
  220. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(only_maximized), wb->prefs->only_maximized);
  221. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(active_window), !wb->prefs->only_maximized);
  222. g_signal_connect(only_maximized, "toggled", G_CALLBACK(on_only_maximized_toggled), wb);
  223. }
  224. else {
  225. DBG("No widget with the name \"only_maximized\" found");
  226. }
  227. show_on_desktop = GTK_TOGGLE_BUTTON(gtk_builder_get_object(wb->prefs->builder, "show_on_desktop"));
  228. if (G_LIKELY (show_on_desktop != NULL)) {
  229. gtk_toggle_button_set_active(show_on_desktop, wb->prefs->show_on_desktop);
  230. g_signal_connect(show_on_desktop, "toggled", G_CALLBACK(on_show_on_desktop_toggled), wb);
  231. }
  232. else {
  233. DBG("No widget with the name \"show_on_desktop\" found");
  234. }
  235. /* Style widgets */
  236. theme_name_treeview = GTK_WIDGET (gtk_builder_get_object (wb->prefs->builder, "theme_name_treeview"));
  237. /* theme name */
  238. {
  239. list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
  240. gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store), COL_THEME_NAME,
  241. (GtkTreeIterCompareFunc) wckbuttons_theme_sort_func,
  242. NULL, NULL);
  243. gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store), COL_THEME_NAME, GTK_SORT_ASCENDING);
  244. gtk_tree_view_set_model (GTK_TREE_VIEW (theme_name_treeview), GTK_TREE_MODEL (list_store));
  245. g_object_unref (G_OBJECT (list_store));
  246. renderer = gtk_cell_renderer_text_new ();
  247. gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (theme_name_treeview),
  248. 0, _("Directory"), renderer, "text", 1, NULL);
  249. gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (theme_name_treeview),
  250. 0, _("Themes usable"), renderer, "text", 0, NULL);
  251. selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_name_treeview));
  252. g_signal_connect (selection, "changed", G_CALLBACK (wckbuttons_theme_selection_changed),
  253. wb);
  254. gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
  255. wckbuttons_load_themes (theme_name_treeview, wb);
  256. }
  257. sync_wm_theme = GTK_TOGGLE_BUTTON(gtk_builder_get_object(wb->prefs->builder, "sync_wm_theme"));
  258. if (G_LIKELY (sync_wm_theme != NULL))
  259. {
  260. if (wb->wm_channel)
  261. {
  262. gtk_toggle_button_set_active(sync_wm_theme, wb->prefs->sync_wm_theme);
  263. g_signal_connect(sync_wm_theme, "toggled", G_CALLBACK(on_sync_wm_theme_toggled), wb);
  264. }
  265. else {
  266. gtk_widget_set_sensitive (GTK_WIDGET(sync_wm_theme), FALSE);
  267. }
  268. }
  269. else {
  270. DBG("No widget with the name \"sync_wm_theme\" found");
  271. }
  272. button_layout = GTK_ENTRY(gtk_builder_get_object(wb->prefs->builder, "button_layout"));
  273. if (G_LIKELY (button_layout != NULL))
  274. {
  275. gtk_entry_set_text(button_layout, wb->prefs->button_layout);
  276. g_signal_connect(GTK_EDITABLE(button_layout), "changed", G_CALLBACK(on_button_layout_changed), wb);
  277. }
  278. else {
  279. DBG("No widget with the name \"button_layout\" found");
  280. }
  281. return GTK_WIDGET(area) ;
  282. }
  283. else {
  284. g_set_error_literal(&error, 0, 0, "No widget with the name \"contentarea\" found");
  285. }
  286. }
  287. g_critical("Faild to construct the builder for plugin %s-%d: %s.", xfce_panel_plugin_get_name (wb->plugin), xfce_panel_plugin_get_unique_id (wb->plugin), error->message);
  288. g_error_free(error);
  289. g_object_unref(G_OBJECT (wb->prefs->builder) );
  290. return NULL ;
  291. }
  292. static void
  293. wckbuttons_configure_response (GtkWidget *dialog, gint response, WBPlugin *wb)
  294. {
  295. gboolean result;
  296. if (response == GTK_RESPONSE_HELP)
  297. {
  298. /* show help */
  299. result = g_spawn_command_line_async ("exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
  300. if (G_UNLIKELY (result == FALSE))
  301. g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
  302. }
  303. else
  304. {
  305. /* remove the dialog data from the plugin */
  306. g_object_set_data (G_OBJECT (wb->plugin), "dialog", NULL);
  307. /* unlock the panel menu */
  308. xfce_panel_plugin_unblock_menu (wb->plugin);
  309. /* save the plugin */
  310. wckbuttons_save (wb->plugin, wb);
  311. /* destroy the properties dialog */
  312. gtk_widget_destroy (dialog);
  313. }
  314. }
  315. void wckbuttons_configure (XfcePanelPlugin *plugin, WBPlugin *wb)
  316. {
  317. GtkWidget *dialog;
  318. GtkWidget *content_area;
  319. GtkWidget *ca;
  320. const gchar *name;
  321. /* block the plugin menu */
  322. xfce_panel_plugin_block_menu (plugin);
  323. /* create the dialog */
  324. name = xfce_panel_plugin_get_display_name (plugin);
  325. dialog = xfce_titled_dialog_new_with_buttons (_(name),
  326. GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (plugin))),
  327. GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
  328. GTK_STOCK_HELP, GTK_RESPONSE_HELP,
  329. GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
  330. NULL);
  331. /* center dialog on the screen */
  332. gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
  333. /* set dialog icon */
  334. gtk_window_set_icon_name (GTK_WINDOW (dialog), "xfce4-settings");
  335. /* link the dialog to the plugin, so we can destroy it when the plugin
  336. * is closed, but the dialog is still open */
  337. g_object_set_data (G_OBJECT (plugin), "dialog", dialog);
  338. /* connect the reponse signal to the dialog */
  339. g_signal_connect (G_OBJECT (dialog), "response",
  340. G_CALLBACK(wckbuttons_configure_response), wb);
  341. content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog) );
  342. ca = build_properties_area (wb, wckbuttons_dialogs_ui, wckbuttons_dialogs_ui_length);
  343. if (G_LIKELY (ca != NULL))
  344. gtk_container_add(GTK_CONTAINER (content_area), ca);
  345. else
  346. DBG("Failed to create content area");
  347. /* show the entire dialog */
  348. gtk_widget_show (dialog);
  349. }