~ubuntu-branches/ubuntu/vivid/mate-applets/vivid-proposed

« back to all changes in this revision

Viewing changes to command/command.c

  • Committer: Package Import Robot
  • Author(s): Mike Gabriel
  • Date: 2014-04-21 13:57:07 UTC
  • Revision ID: package-import@ubuntu.com-20140421135707-hh4arlnzglq9xxfo
Tags: upstream-1.8.0+dfsg1
ImportĀ upstreamĀ versionĀ 1.8.0+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* command.c:
 
2
 *
 
3
 * Copyright (C) 2013-2014 Stefano Karapetsas
 
4
 *
 
5
 *  This file is part of MATE Applets.
 
6
 *
 
7
 *  MATE Applets is free software: you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation, either version 3 of the License, or
 
10
 *  (at your option) any later version.
 
11
 *
 
12
 *  MATE Applets is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with MATE Applets.  If not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 * Authors:
 
21
 *      Stefano Karapetsas <stefano@karapetsas.com>
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <glib.h>
 
27
#include <glib/gi18n.h>
 
28
#include <gio/gio.h>
 
29
#include <gtk/gtk.h>
 
30
 
 
31
#include <mate-panel-applet.h>
 
32
#include <mate-panel-applet-gsettings.h>
 
33
 
 
34
/* Applet constants */
 
35
#define APPLET_ICON    "terminal"
 
36
#define ERROR_OUTPUT   "#"
 
37
 
 
38
/* GSettings constants */
 
39
#define COMMAND_SCHEMA "org.mate.panel.applet.command"
 
40
#define COMMAND_KEY    "command"
 
41
#define INTERVAL_KEY   "interval"
 
42
#define SHOW_ICON_KEY  "show-icon"
 
43
 
 
44
/* GKeyFile constants */
 
45
#define GK_COMMAND_GROUP   "Command"
 
46
#define GK_COMMAND_OUTPUT  "Output"
 
47
#define GK_COMMAND_ICON    "Icon"
 
48
 
 
49
/* Max output lenght accepted from commands */
 
50
#define MAX_OUTPUT_LENGTH 30
 
51
 
 
52
typedef struct
 
53
{
 
54
    MatePanelApplet   *applet;
 
55
 
 
56
    GSettings         *settings;
 
57
 
 
58
    GtkLabel          *label;
 
59
    GtkImage          *image;
 
60
    GtkHBox           *hbox;
 
61
 
 
62
    gchar             *command;
 
63
    gint               interval;
 
64
 
 
65
    guint              timeout_id;
 
66
} CommandApplet;
 
67
 
 
68
static void command_about_callback (GtkAction *action, CommandApplet *command_applet);
 
69
static void command_settings_callback (GtkAction *action, CommandApplet *command_applet);
 
70
static gboolean command_execute (CommandApplet *command_applet);
 
71
 
 
72
static const GtkActionEntry applet_menu_actions [] = {
 
73
    { "Preferences", GTK_STOCK_PROPERTIES, N_("_Preferences"), NULL, NULL, G_CALLBACK (command_settings_callback) },
 
74
    { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, G_CALLBACK (command_about_callback) }
 
75
};
 
76
 
 
77
static char *ui = "<menuitem name='Item 1' action='Preferences' />"
 
78
                  "<menuitem name='Item 2' action='About' />";
 
79
 
 
80
static void
 
81
command_applet_destroy (MatePanelApplet *applet_widget, CommandApplet *command_applet)
 
82
{
 
83
    g_assert (command_applet);
 
84
 
 
85
    if (command_applet->timeout_id != 0)
 
86
    {
 
87
        g_source_remove(command_applet->timeout_id);
 
88
        command_applet->timeout_id = 0;
 
89
    }
 
90
 
 
91
    if (command_applet->command != NULL)
 
92
    {
 
93
        g_free (command_applet->command);
 
94
        command_applet->command = NULL;
 
95
    }
 
96
 
 
97
    g_object_unref (command_applet->settings);
 
98
}
 
99
 
 
100
/* Show the about dialog */
 
101
static void
 
102
command_about_callback (GtkAction *action, CommandApplet *command_applet)
 
103
{
 
104
    const char* authors[] = { "Stefano Karapetsas <stefano@karapetsas.com>", NULL };
 
105
 
 
106
    gtk_show_about_dialog(NULL,
 
107
                          "version", VERSION,
 
108
                          "copyright", "Copyright Ā© 2013-2014 Stefano Karapetsas",
 
109
                          "authors", authors,
 
110
                          "comments", _("Shows the output of a command"),
 
111
                          "translator-credits", _("translator-credits"),
 
112
                          "logo-icon-name", APPLET_ICON,
 
113
    NULL );
 
114
}
 
115
 
 
116
/* Show the preferences dialog */
 
117
static void
 
118
command_settings_callback (GtkAction *action, CommandApplet *command_applet)
 
119
{
 
120
    GtkDialog *dialog;
 
121
    GtkTable *table;
 
122
    GtkWidget *widget;
 
123
    GtkWidget *command;
 
124
    GtkWidget *interval;
 
125
    GtkWidget *showicon;
 
126
 
 
127
    dialog = GTK_DIALOG (gtk_dialog_new_with_buttons(_("Command Applet Preferences"),
 
128
                                                     NULL,
 
129
                                                     GTK_DIALOG_MODAL,
 
130
                                                     GTK_STOCK_CLOSE,
 
131
                                                     GTK_RESPONSE_CLOSE,
 
132
                                                     NULL));
 
133
    table = gtk_table_new (3, 2, FALSE);
 
134
    gtk_table_set_row_spacings (table, 12);
 
135
    gtk_table_set_col_spacings (table, 12);
 
136
 
 
137
    gtk_window_set_default_size (GTK_WINDOW (dialog), 350, 150);
 
138
 
 
139
    widget = gtk_label_new (_("Command:"));
 
140
    gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
 
141
    gtk_table_attach (table, widget, 1, 2, 0, 1,
 
142
                      GTK_FILL, GTK_FILL,
 
143
                      0, 0);
 
144
 
 
145
    command = gtk_entry_new ();
 
146
    gtk_table_attach (table, command, 2, 3, 0, 1,
 
147
                      GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL,
 
148
                      0, 0);
 
149
 
 
150
    widget = gtk_label_new (_("Interval (seconds):"));
 
151
    gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
 
152
    gtk_table_attach (table, widget, 1, 2, 1, 2,
 
153
                      GTK_FILL, GTK_FILL,
 
154
                      0, 0);
 
155
 
 
156
    interval = gtk_spin_button_new_with_range (1.0, 600.0, 1.0);
 
157
    gtk_table_attach (table, interval, 2, 3, 1, 2,
 
158
                      GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL,
 
159
                      0, 0);
 
160
 
 
161
    showicon = gtk_check_button_new_with_label (_("Show icon"));
 
162
    gtk_table_attach (table, showicon, 2, 3, 3, 4,
 
163
                      GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL,
 
164
                      0, 0);
 
165
 
 
166
    gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (dialog)), table, TRUE, TRUE, 0);
 
167
 
 
168
    g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
 
169
 
 
170
    /* use g_settings_bind to manage settings */
 
171
    g_settings_bind (command_applet->settings, COMMAND_KEY, command, "text", G_SETTINGS_BIND_DEFAULT);
 
172
    g_settings_bind (command_applet->settings, INTERVAL_KEY, interval, "value", G_SETTINGS_BIND_DEFAULT);
 
173
    g_settings_bind (command_applet->settings, SHOW_ICON_KEY, showicon, "active", G_SETTINGS_BIND_DEFAULT);
 
174
 
 
175
    gtk_widget_show_all (GTK_WIDGET (dialog));
 
176
}
 
177
 
 
178
/* GSettings signal callbacks */
 
179
static void
 
180
settings_command_changed (GSettings *settings, gchar *key, CommandApplet *command_applet)
 
181
{
 
182
    gchar *command;
 
183
 
 
184
    command = g_settings_get_string (command_applet->settings, COMMAND_KEY);
 
185
 
 
186
    if (command_applet->command)
 
187
        g_free (command_applet->command);
 
188
 
 
189
    if (command != NULL && command[0] != 0)
 
190
        command_applet->command = command;
 
191
    else
 
192
        command_applet->command = g_strdup ("");
 
193
}
 
194
 
 
195
static void
 
196
settings_interval_changed (GSettings *settings, gchar *key, CommandApplet *command_applet)
 
197
{
 
198
    gint interval;
 
199
 
 
200
    interval = g_settings_get_int (command_applet->settings, INTERVAL_KEY);
 
201
 
 
202
    /* minimum interval */
 
203
    if (interval < 1)
 
204
        interval = 1;
 
205
 
 
206
    command_applet->interval = interval;
 
207
 
 
208
    /* stop current timer */
 
209
    if (command_applet->timeout_id != 0)
 
210
    {
 
211
        g_source_remove(command_applet->timeout_id);
 
212
        command_applet->timeout_id = 0;
 
213
    }
 
214
 
 
215
    /* execute command to start new timer */
 
216
    command_execute (command_applet);
 
217
}
 
218
 
 
219
static gboolean
 
220
command_execute (CommandApplet *command_applet)
 
221
{
 
222
    GError *error = NULL;
 
223
    gchar *output = NULL;
 
224
    gint ret = 0;
 
225
 
 
226
    if (g_spawn_command_line_sync (command_applet->command, &output, NULL, &ret, &error))
 
227
    {
 
228
        gtk_widget_set_tooltip_text (GTK_WIDGET (command_applet->label), command_applet->command);
 
229
 
 
230
        if ((output != NULL) && (output[0] != 0))
 
231
        {
 
232
            /* check if output is a custom GKeyFile */
 
233
            if (g_str_has_prefix (output, "[Command]"))
 
234
            {
 
235
                GKeyFile *file = g_key_file_new ();
 
236
                if (g_key_file_load_from_data (file, output, -1, G_KEY_FILE_NONE, NULL))
 
237
                {
 
238
                    gchar *goutput = g_key_file_get_string (file, GK_COMMAND_GROUP, GK_COMMAND_OUTPUT, NULL);
 
239
                    gchar *icon = g_key_file_get_string (file, GK_COMMAND_GROUP, GK_COMMAND_ICON, NULL);
 
240
 
 
241
                    if (goutput)
 
242
                    {
 
243
                        gtk_label_set_use_markup (command_applet->label, TRUE);
 
244
                        gtk_label_set_markup (command_applet->label, goutput);
 
245
                    }
 
246
                    if (icon)
 
247
                        gtk_image_set_from_icon_name (command_applet->image, icon, 24);
 
248
 
 
249
                    g_free (goutput);
 
250
                    g_free (icon);
 
251
                }
 
252
                else
 
253
                    gtk_label_set_text (command_applet->label, ERROR_OUTPUT);
 
254
                g_key_file_free (file);
 
255
            }
 
256
            else
 
257
            {
 
258
                /* check output length */
 
259
                if (strlen(output) > MAX_OUTPUT_LENGTH)
 
260
                {
 
261
                    GString *strip_output;
 
262
                    strip_output = g_string_new_len (output, MAX_OUTPUT_LENGTH);
 
263
                    g_free (output);
 
264
                    output = strip_output->str;
 
265
                    g_string_free (strip_output, FALSE);
 
266
                }
 
267
                /* remove last char if it is '\n' to avoid aligment problems */
 
268
                if (g_str_has_suffix (output, "\n"))
 
269
                {
 
270
                    output[strlen(output) - 1] = 0;
 
271
                }
 
272
 
 
273
                gtk_label_set_text (command_applet->label, output);
 
274
            }
 
275
        }
 
276
        else
 
277
            gtk_label_set_text (command_applet->label, ERROR_OUTPUT);
 
278
    }
 
279
    else
 
280
        gtk_label_set_text (command_applet->label, ERROR_OUTPUT);
 
281
 
 
282
    g_free (output);
 
283
 
 
284
    /* start timer for next execution */
 
285
    command_applet->timeout_id = g_timeout_add_seconds (command_applet->interval,
 
286
                                                        (GSourceFunc) command_execute,
 
287
                                                        command_applet);
 
288
 
 
289
    return FALSE;
 
290
}
 
291
 
 
292
static gboolean
 
293
command_applet_fill (MatePanelApplet* applet)
 
294
{
 
295
    CommandApplet *command_applet;
 
296
 
 
297
    g_set_application_name (_("Command Applet"));
 
298
    gtk_window_set_default_icon_name (APPLET_ICON);
 
299
 
 
300
    mate_panel_applet_set_flags (applet, MATE_PANEL_APPLET_EXPAND_MINOR);
 
301
    mate_panel_applet_set_background_widget (applet, GTK_WIDGET (applet));
 
302
 
 
303
    command_applet = g_malloc0(sizeof(CommandApplet));
 
304
    command_applet->applet = applet;
 
305
    command_applet->settings = mate_panel_applet_settings_new (applet, COMMAND_SCHEMA);
 
306
 
 
307
    command_applet->interval = g_settings_get_int (command_applet->settings, INTERVAL_KEY);
 
308
    command_applet->command = g_settings_get_string (command_applet->settings, COMMAND_KEY);
 
309
 
 
310
    command_applet->hbox = gtk_hbox_new (FALSE, 0);
 
311
    command_applet->image = gtk_image_new_from_icon_name (APPLET_ICON, 24);
 
312
    command_applet->label = gtk_label_new (ERROR_OUTPUT);
 
313
    command_applet->timeout_id = 0;
 
314
 
 
315
    /* we add the Gtk label into the applet */
 
316
    gtk_box_pack_start (GTK_BOX (command_applet->hbox),
 
317
                        GTK_WIDGET (command_applet->image),
 
318
                        TRUE, TRUE, 0);
 
319
    gtk_box_pack_start (GTK_BOX (command_applet->hbox),
 
320
                        GTK_WIDGET (command_applet->label),
 
321
                        TRUE, TRUE, 0);
 
322
 
 
323
    gtk_container_add (GTK_CONTAINER (applet),
 
324
                       GTK_WIDGET (command_applet->hbox));
 
325
 
 
326
    gtk_widget_show_all (GTK_WIDGET (command_applet->applet));
 
327
 
 
328
    g_signal_connect(G_OBJECT (command_applet->applet), "destroy",
 
329
                     G_CALLBACK (command_applet_destroy),
 
330
                     command_applet);
 
331
 
 
332
    /* GSettings signals */
 
333
    g_signal_connect(command_applet->settings,
 
334
                     "changed::" COMMAND_KEY,
 
335
                     G_CALLBACK (settings_command_changed),
 
336
                     command_applet);
 
337
    g_signal_connect(command_applet->settings,
 
338
                     "changed::" INTERVAL_KEY,
 
339
                     G_CALLBACK (settings_interval_changed),
 
340
                     command_applet);
 
341
    g_settings_bind (command_applet->settings,
 
342
                     SHOW_ICON_KEY,
 
343
                     command_applet->image,
 
344
                     "visible",
 
345
                     G_SETTINGS_BIND_DEFAULT);
 
346
 
 
347
    /* set up context menu */
 
348
    GtkActionGroup *action_group = gtk_action_group_new ("Command Applet Actions");
 
349
    gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
 
350
    gtk_action_group_add_actions (action_group, applet_menu_actions,
 
351
                                  G_N_ELEMENTS (applet_menu_actions), command_applet);
 
352
    mate_panel_applet_setup_menu (command_applet->applet, ui, action_group);
 
353
 
 
354
    /* first command execution */
 
355
    command_execute (command_applet);
 
356
 
 
357
    return TRUE;
 
358
}
 
359
 
 
360
/* this function, called by mate-panel, will create the applet */
 
361
static gboolean
 
362
command_factory (MatePanelApplet* applet, const char* iid, gpointer data)
 
363
{
 
364
    gboolean retval = FALSE;
 
365
 
 
366
    if (!g_strcmp0 (iid, "CommandApplet"))
 
367
        retval = command_applet_fill (applet);
 
368
 
 
369
    return retval;
 
370
}
 
371
 
 
372
/* needed by mate-panel applet library */
 
373
MATE_PANEL_APPLET_OUT_PROCESS_FACTORY("CommandAppletFactory",
 
374
                                      PANEL_TYPE_APPLET,
 
375
                                      "Command applet",
 
376
                                      command_factory,
 
377
                                      NULL)