PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/termit-2.9.3/src/termit_preferences.c

#
C | 335 lines | 282 code | 33 blank | 20 comment | 24 complexity | 75231601be09ca27784e39cb3640efd9 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* Copyright (C) 2007-2010, Evgeny Ratnikov
  2. This file is part of termit.
  3. termit is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License version 2
  5. as published by the Free Software Foundation.
  6. termit is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with termit. If not, see <http://www.gnu.org/licenses/>.*/
  12. #include <string.h>
  13. #include <gtk/gtk.h>
  14. #include <gdk/gdkkeysyms.h>
  15. #include <config.h>
  16. #include "termit.h"
  17. #include "termit_style.h"
  18. #include "termit_core_api.h"
  19. static gboolean dlg_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
  20. {
  21. switch (event->keyval) {
  22. case GDK_KEY_Return:
  23. g_signal_emit_by_name(widget, "response", GTK_RESPONSE_OK, NULL);
  24. break;
  25. case GDK_KEY_Escape:
  26. g_signal_emit_by_name(widget, "response", GTK_RESPONSE_NONE, NULL);
  27. break;
  28. default:
  29. return FALSE;
  30. }
  31. return TRUE;
  32. }
  33. static void dlg_set_tab_color__(GtkColorButton *widget, gpointer user_data, void (*callback)(struct TermitTab*, const GdkColor*))
  34. {
  35. if (!user_data) {
  36. ERROR("user_data is NULL");
  37. return;
  38. }
  39. struct TermitTab* pTab = (struct TermitTab*)user_data;
  40. GdkColor color = {};
  41. gtk_color_button_get_color(widget, &color);
  42. callback(pTab, &color);
  43. }
  44. static void dlg_set_foreground(GtkColorButton *widget, gpointer user_data)
  45. {
  46. return dlg_set_tab_color__(widget, user_data, termit_tab_set_color_foreground);
  47. }
  48. static void dlg_set_background(GtkColorButton *widget, gpointer user_data)
  49. {
  50. return dlg_set_tab_color__(widget, user_data, termit_tab_set_color_background);
  51. }
  52. static void dlg_set_font(GtkFontButton *widget, gpointer user_data)
  53. {
  54. if (!user_data) {
  55. ERROR("user_data is NULL");
  56. return;
  57. }
  58. struct TermitTab* pTab = (struct TermitTab*)user_data;
  59. termit_tab_set_font(pTab, gtk_font_button_get_font_name(widget));
  60. }
  61. static gboolean dlg_set_transparency(GtkSpinButton *btn, gpointer user_data)
  62. {
  63. if (!user_data) {
  64. ERROR("user_data is NULL");
  65. return FALSE;
  66. }
  67. struct TermitTab* pTab = (struct TermitTab*)user_data;
  68. gdouble value = gtk_spin_button_get_value(btn);
  69. termit_tab_set_transparency(pTab, value);
  70. return FALSE;
  71. }
  72. static gboolean dlg_set_audible_bell(GtkToggleButton *btn, gpointer user_data)
  73. {
  74. if (!user_data) {
  75. ERROR("user_data is NULL");
  76. return FALSE;
  77. }
  78. struct TermitTab* pTab = (struct TermitTab*)user_data;
  79. gboolean value = gtk_toggle_button_get_active(btn);
  80. termit_tab_set_audible_bell(pTab, value);
  81. return FALSE;
  82. }
  83. static gboolean dlg_set_visible_bell(GtkToggleButton *btn, gpointer user_data)
  84. {
  85. if (!user_data) {
  86. ERROR("user_data is NULL");
  87. return FALSE;
  88. }
  89. struct TermitTab* pTab = (struct TermitTab*)user_data;
  90. gboolean value = gtk_toggle_button_get_active(btn);
  91. termit_tab_set_visible_bell(pTab, value);
  92. return FALSE;
  93. }
  94. struct TermitDlgHelper
  95. {
  96. struct TermitTab* pTab;
  97. gchar* tab_title;
  98. gboolean handmade_tab_title;
  99. struct TermitStyle style;
  100. gboolean au_bell;
  101. gboolean vi_bell;
  102. // widgets with values
  103. GtkWidget* dialog;
  104. GtkWidget* entry_title;
  105. GtkWidget* btn_font;
  106. GtkWidget* btn_foreground;
  107. GtkWidget* btn_background;
  108. GtkWidget* btn_image_file;
  109. GtkWidget* scale_transparency;
  110. GtkWidget* audible_bell;
  111. GtkWidget* visible_bell;
  112. };
  113. static struct TermitDlgHelper* termit_dlg_helper_new(struct TermitTab* pTab)
  114. {
  115. struct TermitDlgHelper* hlp = g_malloc0(sizeof(struct TermitDlgHelper));
  116. hlp->pTab = pTab;
  117. if (pTab->title) {
  118. hlp->handmade_tab_title = TRUE;
  119. hlp->tab_title = g_strdup(pTab->title);
  120. } else {
  121. hlp->tab_title = g_strdup(gtk_label_get_text(GTK_LABEL(pTab->tab_name)));
  122. }
  123. termit_style_copy(&hlp->style, &pTab->style);
  124. hlp->au_bell = pTab->audible_bell;
  125. hlp->vi_bell = pTab->visible_bell;
  126. return hlp;
  127. }
  128. static void termit_dlg_helper_free(struct TermitDlgHelper* hlp)
  129. {
  130. g_free(hlp->tab_title);
  131. termit_style_free(&hlp->style);
  132. g_free(hlp);
  133. }
  134. static void dlg_set_tab_default_values(struct TermitTab* pTab, struct TermitDlgHelper* hlp)
  135. {
  136. if (hlp->tab_title)
  137. termit_tab_set_title(pTab, hlp->tab_title);
  138. vte_terminal_set_default_colors(VTE_TERMINAL(pTab->vte));
  139. termit_tab_set_font(pTab, hlp->style.font_name);
  140. termit_tab_set_background_image(pTab, hlp->style.image_file);
  141. termit_tab_set_color_foreground(pTab, hlp->style.foreground_color);
  142. termit_tab_set_color_background(pTab, hlp->style.background_color);
  143. termit_tab_set_transparency(pTab, hlp->style.transparency);
  144. termit_tab_set_audible_bell(pTab, hlp->au_bell);
  145. termit_tab_set_visible_bell(pTab, hlp->vi_bell);
  146. if (hlp->style.image_file) {
  147. gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(hlp->btn_image_file), hlp->style.image_file);
  148. }
  149. }
  150. static void dlg_set_default_values(struct TermitDlgHelper* hlp)
  151. {
  152. gtk_entry_set_text(GTK_ENTRY(hlp->entry_title), hlp->tab_title);
  153. gtk_font_button_set_font_name(GTK_FONT_BUTTON(hlp->btn_font), hlp->style.font_name);
  154. if (hlp->style.foreground_color) {
  155. gtk_color_button_set_color(GTK_COLOR_BUTTON(hlp->btn_foreground), hlp->style.foreground_color);
  156. }
  157. if (hlp->style.background_color) {
  158. gtk_color_button_set_color(GTK_COLOR_BUTTON(hlp->btn_background), hlp->style.background_color);
  159. }
  160. gtk_spin_button_set_value(GTK_SPIN_BUTTON(hlp->scale_transparency), hlp->style.transparency);
  161. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hlp->audible_bell), hlp->au_bell);
  162. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hlp->visible_bell), hlp->vi_bell);
  163. if (hlp->style.image_file) {
  164. gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(hlp->btn_image_file), hlp->style.image_file);
  165. } else {
  166. gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(hlp->btn_image_file));
  167. }
  168. }
  169. static void dlg_restore_defaults(GtkButton *button, gpointer user_data)
  170. {
  171. struct TermitDlgHelper* hlp = (struct TermitDlgHelper*)user_data;
  172. dlg_set_default_values(hlp);
  173. dlg_set_tab_default_values(hlp->pTab, hlp);
  174. }
  175. static void dlg_set_image_file(GtkFileChooserButton *widget, gpointer user_data)
  176. {
  177. struct TermitTab* pTab = (struct TermitTab*)user_data;
  178. termit_tab_set_background_image(pTab, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)));
  179. }
  180. static gboolean dlg_clear_image_file(GtkWidget* widget, GdkEventKey* event, gpointer user_data)
  181. {
  182. struct TermitTab* pTab = (struct TermitTab*)user_data;
  183. if (event->keyval == GDK_KEY_Delete) {
  184. if (pTab->style.image_file) {
  185. gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(widget));
  186. termit_tab_set_background_image(pTab, NULL);
  187. }
  188. }
  189. return FALSE;
  190. }
  191. void termit_preferences_dialog(struct TermitTab *pTab)
  192. {
  193. // store font_name, foreground, background
  194. struct TermitDlgHelper* hlp = termit_dlg_helper_new(pTab);
  195. GtkStockItem item = {};
  196. gtk_stock_lookup(GTK_STOCK_PREFERENCES, &item); // may be memory leak inside
  197. GtkWidget* dialog = gtk_dialog_new_with_buttons(item.label,
  198. GTK_WINDOW_TOPLEVEL,
  199. GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
  200. GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
  201. GTK_STOCK_OK, GTK_RESPONSE_OK,
  202. NULL);
  203. g_signal_connect(G_OBJECT(dialog), "key-press-event", G_CALLBACK(dlg_key_press), dialog);
  204. GtkWidget* dlg_table = gtk_table_new(5, 2, FALSE);
  205. #define TERMIT_PREFERENCE_ROW(pref_name, widget) \
  206. gtk_table_attach(GTK_TABLE(dlg_table), gtk_label_new(pref_name), 0, 1, row, row + 1, 0, 0, 0, 0); \
  207. gtk_table_attach_defaults(GTK_TABLE(dlg_table), widget, 1, 2, row, row + 1); \
  208. hlp->widget = widget; \
  209. row++;
  210. #define TERMIT_PREFERENCE_ROW2(pref_widget, widget) \
  211. gtk_table_attach(GTK_TABLE(dlg_table), pref_widget, 0, 1, row, row + 1, 0, 0, 0, 0); \
  212. gtk_table_attach_defaults(GTK_TABLE(dlg_table), widget, 1, 2, row, row + 1); \
  213. hlp->widget = widget; \
  214. row++;
  215. GtkWidget* entry_title = gtk_entry_new();
  216. guint row = 0;
  217. { // tab title
  218. gtk_entry_set_text(GTK_ENTRY(entry_title), hlp->tab_title);
  219. TERMIT_PREFERENCE_ROW(_("Title"), entry_title);
  220. }
  221. { // font selection
  222. GtkWidget* btn_font = gtk_font_button_new_with_font(pTab->style.font_name);
  223. g_signal_connect(btn_font, "font-set", G_CALLBACK(dlg_set_font), pTab);
  224. TERMIT_PREFERENCE_ROW(_("Font"), btn_font);
  225. }
  226. { // foreground
  227. GtkWidget* btn_foreground = (pTab->style.foreground_color)
  228. ? gtk_color_button_new_with_color(pTab->style.foreground_color)
  229. : gtk_color_button_new();
  230. g_signal_connect(btn_foreground, "color-set", G_CALLBACK(dlg_set_foreground), pTab);
  231. TERMIT_PREFERENCE_ROW(_("Foreground"), btn_foreground);
  232. }
  233. { // background
  234. GtkWidget* btn_background = (pTab->style.background_color)
  235. ? gtk_color_button_new_with_color(pTab->style.background_color)
  236. : gtk_color_button_new();
  237. g_signal_connect(btn_background, "color-set", G_CALLBACK(dlg_set_background), pTab);
  238. TERMIT_PREFERENCE_ROW(_("Background"), btn_background);
  239. }
  240. { // background image
  241. GtkWidget* btn_image_file = gtk_file_chooser_button_new(pTab->style.image_file,
  242. GTK_FILE_CHOOSER_ACTION_OPEN);
  243. GtkFileFilter* filter = gtk_file_filter_new();
  244. gtk_file_filter_set_name(filter, _("images"));
  245. gtk_file_filter_add_mime_type(filter, "image/*");
  246. if (pTab->style.image_file) {
  247. gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(btn_image_file), pTab->style.image_file);
  248. }
  249. gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(btn_image_file), filter);
  250. g_signal_connect(btn_image_file, "file-set", G_CALLBACK(dlg_set_image_file), pTab);
  251. g_signal_connect(btn_image_file, "key-press-event", G_CALLBACK(dlg_clear_image_file), pTab);
  252. GtkWidget* btn_switch_image_file = gtk_check_button_new_with_label(_("Background image"));
  253. if (pTab->style.image_file) {
  254. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(btn_switch_image_file), TRUE);
  255. }
  256. /*g_signal_connect(btn_switch_image_file, "toggled", G_CALLBACK(dlg_switch_image_file), btn_image_file);*/
  257. /*TERMIT_PREFERENCE_ROW2(btn_switch_image_file, btn_image_file);*/
  258. TERMIT_PREFERENCE_ROW(_("Image"), btn_image_file);
  259. }
  260. { // transparency
  261. GtkWidget* scale_transparency = gtk_spin_button_new_with_range(0, 1, 0.05);
  262. gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_transparency), pTab->style.transparency);
  263. g_signal_connect(scale_transparency, "value-changed", G_CALLBACK(dlg_set_transparency), pTab);
  264. TERMIT_PREFERENCE_ROW(_("Transparency"), scale_transparency);
  265. }
  266. { // audible_bell
  267. GtkWidget* audible_bell = gtk_check_button_new();
  268. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(audible_bell), pTab->audible_bell);
  269. g_signal_connect(audible_bell, "toggled", G_CALLBACK(dlg_set_audible_bell), pTab);
  270. TERMIT_PREFERENCE_ROW(_("Audible bell"), audible_bell);
  271. }
  272. { // visible_bell
  273. GtkWidget* visible_bell = gtk_check_button_new();
  274. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(visible_bell), pTab->visible_bell);
  275. g_signal_connect(visible_bell, "toggled", G_CALLBACK(dlg_set_visible_bell), pTab);
  276. TERMIT_PREFERENCE_ROW(_("Visible bell"), visible_bell);
  277. }
  278. {
  279. GtkWidget* btn_restore = gtk_button_new_from_stock(GTK_STOCK_REVERT_TO_SAVED);
  280. g_signal_connect(G_OBJECT(btn_restore), "clicked", G_CALLBACK(dlg_restore_defaults), hlp);
  281. gtk_table_attach(GTK_TABLE(dlg_table), btn_restore, 1, 2, row, row + 1, 0, 0, 0, 0);
  282. }
  283. gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), dlg_table);
  284. // TODO: apply to all tabs
  285. // TODO: color palette
  286. // TODO: save style - choose from saved (murphy, delek, etc.)
  287. gtk_widget_show_all(dialog);
  288. if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
  289. dlg_set_tab_default_values(pTab, hlp);
  290. } else {
  291. // insane title flag
  292. if (pTab->title ||
  293. (!pTab->title &&
  294. strcmp(gtk_label_get_text(GTK_LABEL(pTab->tab_name)),
  295. gtk_entry_get_text(GTK_ENTRY(entry_title))) != 0)) {
  296. termit_tab_set_title(pTab, gtk_entry_get_text(GTK_ENTRY(entry_title)));
  297. }
  298. }
  299. termit_dlg_helper_free(hlp);
  300. gtk_widget_destroy(dialog);
  301. }