PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/xfce4-dict-0.6.0/panel-plugin/xfce4-dict-plugin.c

#
C | 474 lines | 309 code | 112 blank | 53 comment | 58 complexity | 890cb2b7cef8f13b3102e0218e54e0fa MD5 | raw file
Possible License(s): GPL-2.0
  1. /* $Id$
  2. *
  3. * Copyright 2006-2009 Enrico Tr??ger <enrico(dot)troeger(at)uvena(dot)de>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Library General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #include <stdlib.h>
  23. #include <gtk/gtk.h>
  24. #include <libxfcegui4/libxfcegui4.h>
  25. #include <libxfce4panel/xfce-panel-plugin.h>
  26. #include <libxfce4panel/xfce-panel-convenience.h>
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <sys/stat.h>
  30. #include <unistd.h>
  31. #include <netdb.h>
  32. #include <netinet/tcp.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35. #include <string.h>
  36. #include "libdict.h"
  37. #include "sexy-icon-entry.h"
  38. typedef struct
  39. {
  40. DictData *dd;
  41. XfcePanelPlugin *plugin;
  42. GtkTooltips *tooltips;
  43. GtkWidget *panel_button;
  44. GtkWidget *panel_button_image;
  45. } DictPanelData;
  46. static gboolean entry_is_dirty = FALSE;
  47. static GdkPixbuf *dict_plugin_load_and_scale(const guint8 *data, gint dstw, gint dsth)
  48. {
  49. GdkPixbuf *pb, *pb_scaled;
  50. gint pb_w, pb_h;
  51. pb = gdk_pixbuf_new_from_inline(-1, data, FALSE, NULL);
  52. pb_w = gdk_pixbuf_get_width(pb);
  53. pb_h = gdk_pixbuf_get_height(pb);
  54. if (dstw == pb_w && dsth == pb_h)
  55. return(pb);
  56. else if (dstw < 0)
  57. dstw = (dsth * pb_w) / pb_h;
  58. else if (dsth < 0)
  59. dsth = (dstw * pb_h) / pb_w;
  60. pb_scaled = gdk_pixbuf_scale_simple(pb, dstw, dsth, GDK_INTERP_HYPER);
  61. g_object_unref(G_OBJECT(pb));
  62. return pb_scaled;
  63. }
  64. static gboolean dict_plugin_panel_set_size(XfcePanelPlugin *plugin, gint wsize, DictPanelData *dpd)
  65. {
  66. gint width;
  67. gint height = wsize;
  68. gint size = wsize - 2 - (2 * MAX(dpd->panel_button->style->xthickness,
  69. dpd->panel_button->style->ythickness));
  70. dpd->dd->icon = dict_plugin_load_and_scale(dict_gui_get_icon_data(), size, -1);
  71. gtk_image_set_from_pixbuf(GTK_IMAGE(dpd->panel_button_image), dpd->dd->icon);
  72. if (dpd->dd->show_panel_entry &&
  73. xfce_panel_plugin_get_orientation(plugin) == GTK_ORIENTATION_HORIZONTAL)
  74. {
  75. width = size + dpd->dd->panel_entry_size;
  76. gtk_widget_set_size_request(dpd->dd->panel_entry, dpd->dd->panel_entry_size, -1);
  77. }
  78. else
  79. width = size;
  80. if (xfce_panel_plugin_get_orientation(plugin) == GTK_ORIENTATION_VERTICAL)
  81. height -= 4; /* reduce some of the height because it creates too much space otherwise */
  82. gtk_widget_set_size_request(dpd->panel_button, wsize, height);
  83. return TRUE;
  84. }
  85. /* TODO remove me, unused
  86. static void dict_toggle_main_window(GtkWidget *button, DictData *dd)
  87. {
  88. if (GTK_WIDGET_VISIBLE(dd->window))
  89. gtk_widget_hide(dd->window);
  90. else
  91. {
  92. const gchar *panel_text = "";
  93. if (dd->panel_entry != NULL)
  94. panel_text = gtk_entry_get_text(GTK_ENTRY(dd->panel_entry));
  95. dict_show_main_window(dd);
  96. if (NZV(panel_text))
  97. {
  98. dict_search_word(dd, panel_text);
  99. gtk_entry_set_text(GTK_ENTRY(dd->main_entry), panel_text);
  100. }
  101. gtk_widget_grab_focus(dd->main_entry);
  102. }
  103. }
  104. */
  105. static void dict_plugin_panel_button_clicked(GtkWidget *button, DictPanelData *dpd)
  106. {
  107. if (GTK_WIDGET_VISIBLE(dpd->dd->window))
  108. {
  109. /* we must query geometry settings here because position and maximized state
  110. * doesn't work when the window is hidden */
  111. dict_gui_query_geometry(dpd->dd);
  112. gtk_widget_hide(dpd->dd->window);
  113. }
  114. else
  115. {
  116. dict_gui_show_main_window(dpd->dd);
  117. /* Do not search the panel text if it is still the default text */
  118. if (dpd->dd->show_panel_entry &&
  119. xfce_panel_plugin_get_orientation(dpd->plugin) == GTK_ORIENTATION_HORIZONTAL &&
  120. entry_is_dirty)
  121. {
  122. const gchar *panel_text = gtk_entry_get_text(GTK_ENTRY(dpd->dd->panel_entry));
  123. if (NZV(panel_text))
  124. {
  125. dict_search_word(dpd->dd, panel_text);
  126. gtk_entry_set_text(GTK_ENTRY(dpd->dd->main_entry), panel_text);
  127. }
  128. }
  129. gtk_widget_grab_focus(dpd->dd->main_entry);
  130. }
  131. }
  132. /* Handle user messages (xfce4-dict) */
  133. static gboolean dict_plugin_message_received(GtkWidget *w, GdkEventClient *ev, DictPanelData *dpd)
  134. {
  135. if (ev->data_format == 8 && strncmp(ev->data.b, "xfdict", 6) == 0)
  136. {
  137. gchar flags = ev->data.b[6];
  138. gchar *tts = ev->data.b + 7;
  139. dpd->dd->mode_in_use = dict_set_search_mode_from_flags(dpd->dd->mode_in_use, flags);
  140. if (NZV(tts))
  141. {
  142. gtk_entry_set_text(GTK_ENTRY(dpd->dd->main_entry), tts);
  143. dict_search_word(dpd->dd, tts);
  144. }
  145. else if (flags & DICT_FLAGS_FOCUS_PANEL_ENTRY && dpd->dd->show_panel_entry)
  146. {
  147. xfce_panel_plugin_focus_widget(dpd->plugin, dpd->dd->panel_entry);
  148. }
  149. else
  150. {
  151. dict_plugin_panel_button_clicked(NULL, dpd);
  152. }
  153. return TRUE;
  154. }
  155. return FALSE;
  156. }
  157. static gboolean dict_plugin_set_selection(DictPanelData *dpd)
  158. {
  159. GdkScreen *gscreen;
  160. gchar selection_name[32];
  161. Atom selection_atom;
  162. GtkWidget *win;
  163. Window xwin;
  164. win = gtk_invisible_new();
  165. gtk_widget_realize(win);
  166. xwin = GDK_WINDOW_XID(GTK_WIDGET(win)->window);
  167. gscreen = gtk_widget_get_screen(win);
  168. g_snprintf(selection_name, sizeof (selection_name),
  169. XFCE_DICT_SELECTION"%d", gdk_screen_get_number(gscreen));
  170. selection_atom = XInternAtom(GDK_DISPLAY(), selection_name, False);
  171. if (XGetSelectionOwner(GDK_DISPLAY(), selection_atom))
  172. {
  173. gtk_widget_destroy(win);
  174. return FALSE;
  175. }
  176. XSelectInput(GDK_DISPLAY(), xwin, PropertyChangeMask);
  177. XSetSelectionOwner(GDK_DISPLAY(), selection_atom, xwin, GDK_CURRENT_TIME);
  178. g_signal_connect(G_OBJECT(win), "client-event", G_CALLBACK(dict_plugin_message_received), dpd);
  179. return TRUE;
  180. }
  181. void dict_plugin_close_button_clicked(GtkWidget *button, DictPanelData *dpd)
  182. {
  183. gtk_widget_hide(dpd->dd->window);
  184. }
  185. static void dict_plugin_free_data(XfcePanelPlugin *plugin, DictPanelData *dpd)
  186. {
  187. /* Destroy the setting dialog, if this open */
  188. GtkWidget *dialog = g_object_get_data(G_OBJECT(dpd->plugin), "dialog");
  189. /* if the main window is visible, query geometry as usual, if it is hidden the geometry
  190. * was queried when it was hidden */
  191. if (GTK_WIDGET_VISIBLE(dpd->dd->window))
  192. {
  193. dict_gui_query_geometry(dpd->dd);
  194. }
  195. if (dialog != NULL)
  196. gtk_widget_destroy(dialog);
  197. gtk_object_sink(GTK_OBJECT(dpd->tooltips));
  198. dict_free_data(dpd->dd);
  199. g_free(dpd);
  200. }
  201. static void dict_plugin_panel_change_orientation(XfcePanelPlugin *plugin,
  202. GtkOrientation orientation, DictPanelData *dpd)
  203. {
  204. if (! dpd->dd->show_panel_entry || orientation == GTK_ORIENTATION_VERTICAL)
  205. gtk_widget_hide(dpd->dd->panel_entry);
  206. else
  207. gtk_widget_show(dpd->dd->panel_entry);
  208. }
  209. static void dict_plugin_style_set(XfcePanelPlugin *plugin, gpointer unused, DictPanelData *dpd)
  210. {
  211. dict_plugin_panel_set_size(plugin, xfce_panel_plugin_get_size(plugin), dpd);
  212. }
  213. static void dict_plugin_write_rc_file(XfcePanelPlugin *plugin, DictPanelData *dpd)
  214. {
  215. dict_write_rc_file(dpd->dd);
  216. }
  217. static void dict_plugin_panel_save_settings(DictPanelData *dpd)
  218. {
  219. if (dpd->dd->show_panel_entry &&
  220. xfce_panel_plugin_get_orientation(dpd->plugin) == GTK_ORIENTATION_HORIZONTAL)
  221. {
  222. gtk_widget_show(dpd->dd->panel_entry);
  223. }
  224. else
  225. gtk_widget_hide(dpd->dd->panel_entry);
  226. dict_plugin_panel_set_size(dpd->plugin, xfce_panel_plugin_get_size(dpd->plugin), dpd);
  227. }
  228. static void dict_plugin_properties_dialog_response(GtkWidget *dlg, gint response, DictPanelData *dpd)
  229. {
  230. /* first run the real response handler which reads the settings from the dialog */
  231. dict_prefs_dialog_response(dlg, response, dpd->dd);
  232. dict_plugin_panel_save_settings(dpd);
  233. g_object_set_data(G_OBJECT(dpd->plugin), "dialog", NULL);
  234. xfce_panel_plugin_unblock_menu(dpd->plugin);
  235. }
  236. static void dict_plugin_properties_dialog(XfcePanelPlugin *plugin, DictPanelData *dpd)
  237. {
  238. GtkWidget *dlg;
  239. xfce_panel_plugin_block_menu(plugin);
  240. dlg = dict_prefs_dialog_show(gtk_widget_get_toplevel(GTK_WIDGET(plugin)), dpd->dd);
  241. g_object_set_data(G_OBJECT(dpd->plugin), "dialog", dlg);
  242. g_signal_connect(dlg, "response", G_CALLBACK(dict_plugin_properties_dialog_response), dpd);
  243. gtk_widget_show(dlg);
  244. }
  245. static void entry_activate_cb(GtkEntry *entry, DictPanelData *dpd)
  246. {
  247. const gchar *entered_text = gtk_entry_get_text(GTK_ENTRY(dpd->dd->panel_entry));
  248. gtk_entry_set_text(GTK_ENTRY(dpd->dd->main_entry), entered_text);
  249. dict_search_word(dpd->dd, entered_text);
  250. }
  251. static void entry_icon_pressed_cb(SexyIconEntry *entry, gint pos, gint button, DictPanelData *dpd)
  252. {
  253. if (button != 1)
  254. return;
  255. if (pos == SEXY_ICON_ENTRY_PRIMARY)
  256. {
  257. entry_activate_cb(NULL, dpd);
  258. gtk_widget_grab_focus(dpd->dd->main_entry);
  259. }
  260. else if (pos == SEXY_ICON_ENTRY_SECONDARY)
  261. {
  262. dict_gui_clear_text_buffer(dpd->dd);
  263. gtk_entry_set_text(GTK_ENTRY(dpd->dd->main_entry), "");
  264. dict_gui_set_panel_entry_text(dpd->dd, "");
  265. dict_gui_status_add(dpd->dd, _("Ready"));
  266. }
  267. }
  268. static gboolean entry_buttonpress_cb(GtkWidget *entry, GdkEventButton *event, DictPanelData *dpd)
  269. {
  270. GtkWidget *toplevel;
  271. if (! entry_is_dirty)
  272. {
  273. entry_is_dirty = TRUE;
  274. if (event->button == 1)
  275. gtk_entry_set_text(GTK_ENTRY(entry), "");
  276. }
  277. /* Determine toplevel parent widget */
  278. toplevel = gtk_widget_get_toplevel(entry);
  279. /* Grab entry focus if possible */
  280. if (event->button != 3 && toplevel && toplevel->window)
  281. xfce_panel_plugin_focus_widget(dpd->plugin, entry);
  282. return FALSE;
  283. }
  284. static void entry_changed_cb(GtkEditable *editable, DictData *dd)
  285. {
  286. entry_is_dirty = TRUE;
  287. }
  288. static void dict_plugin_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context,
  289. gint x, gint y, GtkSelectionData *data, guint info, guint ltime, DictPanelData *dpd)
  290. {
  291. if ((data != NULL) && (data->length >= 0) && (data->format == 8))
  292. {
  293. if (widget == dpd->panel_button || widget == dpd->dd->panel_entry)
  294. {
  295. gtk_entry_set_text(GTK_ENTRY(dpd->dd->main_entry), (const gchar*) data->data);
  296. }
  297. dict_drag_data_received(widget, drag_context, x, y, data, info, ltime, dpd->dd);
  298. }
  299. }
  300. static void dict_plugin_construct(XfcePanelPlugin *plugin)
  301. {
  302. DictPanelData *dpd = g_new0(DictPanelData, 1);
  303. GtkWidget *hbox;
  304. xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
  305. g_thread_init(NULL);
  306. dpd->dd = dict_create_dictdata();
  307. dpd->dd->is_plugin = TRUE;
  308. dpd->plugin = plugin;
  309. dict_read_rc_file(dpd->dd);
  310. dpd->panel_button = xfce_create_panel_button();
  311. dpd->tooltips = gtk_tooltips_new();
  312. gtk_tooltips_set_tip(dpd->tooltips, dpd->panel_button, _("Look up a word"), NULL);
  313. dpd->panel_button_image = gtk_image_new();
  314. gtk_container_add(GTK_CONTAINER(dpd->panel_button), GTK_WIDGET(dpd->panel_button_image));
  315. gtk_widget_show_all(dpd->panel_button);
  316. g_signal_connect(dpd->panel_button, "clicked", G_CALLBACK(dict_plugin_panel_button_clicked), dpd);
  317. dict_gui_create_main_window(dpd->dd);
  318. g_signal_connect(dpd->dd->window, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
  319. g_signal_connect(dpd->dd->close_button, "clicked", G_CALLBACK(dict_plugin_close_button_clicked), dpd);
  320. g_signal_connect(plugin, "free-data", G_CALLBACK(dict_plugin_free_data), dpd);
  321. g_signal_connect(plugin, "size-changed", G_CALLBACK(dict_plugin_panel_set_size), dpd);
  322. g_signal_connect(plugin, "orientation-changed", G_CALLBACK(dict_plugin_panel_change_orientation), dpd);
  323. g_signal_connect(plugin, "style-set", G_CALLBACK(dict_plugin_style_set), dpd);
  324. g_signal_connect(plugin, "save", G_CALLBACK(dict_plugin_write_rc_file), dpd);
  325. g_signal_connect(plugin, "configure-plugin", G_CALLBACK(dict_plugin_properties_dialog), dpd);
  326. g_signal_connect(plugin, "about", G_CALLBACK(dict_gui_about_dialog), dpd->dd);
  327. xfce_panel_plugin_menu_show_configure(plugin);
  328. xfce_panel_plugin_menu_show_about(plugin);
  329. /* file menu */
  330. g_signal_connect(dpd->dd->close_menu_item, "activate", G_CALLBACK(dict_plugin_close_button_clicked), dpd);
  331. g_signal_connect(dpd->dd->pref_menu_item, "activate", G_CALLBACK(dict_plugin_properties_dialog), dpd);
  332. /* panel entry */
  333. dpd->dd->panel_entry = sexy_icon_entry_new_full(NULL, "gtk-clear");
  334. gtk_entry_set_width_chars(GTK_ENTRY(dpd->dd->panel_entry), 25);
  335. gtk_entry_set_text(GTK_ENTRY(dpd->dd->panel_entry), _("Search term"));
  336. g_signal_connect(dpd->dd->panel_entry, "icon_released", G_CALLBACK(entry_icon_pressed_cb), dpd);
  337. g_signal_connect(dpd->dd->panel_entry, "activate", G_CALLBACK(entry_activate_cb), dpd);
  338. g_signal_connect(dpd->dd->panel_entry, "button-press-event", G_CALLBACK(entry_buttonpress_cb), dpd);
  339. g_signal_connect(dpd->dd->panel_entry, "changed", G_CALLBACK(entry_changed_cb), dpd);
  340. if (dpd->dd->show_panel_entry &&
  341. xfce_panel_plugin_get_orientation(dpd->plugin) == GTK_ORIENTATION_HORIZONTAL)
  342. {
  343. gtk_widget_show(dpd->dd->panel_entry);
  344. }
  345. hbox = gtk_hbox_new(FALSE, 3);
  346. gtk_widget_show(hbox);
  347. gtk_box_pack_start(GTK_BOX(hbox), dpd->panel_button, FALSE, FALSE, 0);
  348. gtk_box_pack_start(GTK_BOX(hbox), dpd->dd->panel_entry, FALSE, FALSE, 0);
  349. gtk_container_add(GTK_CONTAINER(plugin), hbox);
  350. xfce_panel_plugin_add_action_widget(plugin, dpd->panel_button);
  351. dict_plugin_set_selection(dpd);
  352. /* DnD stuff */
  353. gtk_drag_dest_set(GTK_WIDGET(dpd->panel_button), GTK_DEST_DEFAULT_ALL,
  354. NULL, 0, GDK_ACTION_COPY | GDK_ACTION_MOVE);
  355. gtk_drag_dest_add_text_targets(GTK_WIDGET(dpd->panel_button));
  356. g_signal_connect(dpd->panel_button, "drag-data-received", G_CALLBACK(dict_plugin_drag_data_received), dpd);
  357. g_signal_connect(dpd->dd->panel_entry, "drag-data-received", G_CALLBACK(dict_plugin_drag_data_received), dpd);
  358. dict_gui_status_add(dpd->dd, _("Ready"));
  359. }
  360. XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(dict_plugin_construct);