Fixed HTTP-client query-string handling bug.
[doldaconnect.git] / clients / gnome-trans-applet / dolcon-trans-applet.c
CommitLineData
1a839140 1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
302a2600 3 * Copyright (C) 2005 Fredrik Tolf <fredrik@dolda2000.com>
1a839140 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
d3372da9 20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23#include <string.h>
24#include <doldaconnect/uilib.h>
25#include <doldaconnect/utils.h>
26#include <panel-applet.h>
27#include <gtk/gtk.h>
28#include <time.h>
29
30#include "conduit.h"
31
32struct appletdata
33{
34 PanelApplet *applet;
35 GtkLabel *label;
36 GtkProgressBar *pbar;
37 GtkTooltips *tips;
38 gint tiptimeout;
39 struct conduit *conduit;
40 struct transfer *curdisplay;
41};
42
43static char *ctxtmenu =
44"<popup name='button3'>"
6431aca0 45" <menuitem name='Preferences' verb='dca_pref' _label='Preferences' pixtype='stock' pixname='gtk-properties' />"
46" <menuitem name='Cancel transfer' verb='dca_cancel' _label='Cancel transfer' pixtype='stock' pixname='gtk-cancel' />"
d3372da9 47"</popup>";
48
49static void run_pref_dialog(BonoboUIComponent *uic, gpointer data, const char *cname)
50{
51}
52
6431aca0 53static void cancel_transfer(BonoboUIComponent *uic, struct appletdata *data, const char *cname)
54{
55 if(data->conduit->iface->cancel != NULL)
56 data->conduit->iface->cancel(data->conduit, data->curdisplay);
57}
58
d3372da9 59static BonoboUIVerb ctxtmenuverbs[] =
60{
61 BONOBO_UI_VERB("dca_pref", run_pref_dialog),
0a5f2058 62 BONOBO_UI_VERB("dca_cancel", (void (*)(BonoboUIComponent*, gpointer, const char *))cancel_transfer),
d3372da9 63 BONOBO_UI_VERB_END
64};
65
66static gint reconncb(struct appletdata *data)
67{
68 condtryconn(data->conduit);
69 return(FALSE);
70}
71
72static gboolean updatetip(struct appletdata *data)
73{
74 int diff, speed, left;
75 time_t now;
76 char buf[256];
77
0a5f2058
FT
78 if(data->curdisplay == NULL) {
79 gtk_tooltips_set_tip(data->tips, GTK_WIDGET(data->applet), _("No transfer selected"), NULL);
d3372da9 80 return(TRUE);
0a5f2058 81 }
d3372da9 82 now = time(NULL);
90db4549 83 if((data->curdisplay->cmptime == 0) || (now == data->curdisplay->cmptime))
d3372da9 84 {
85 strcpy(buf, _("Calculating remaining time..."));
86 } else {
87 diff = data->curdisplay->pos - data->curdisplay->cmpsize;
88 speed = diff / (now - data->curdisplay->cmptime);
89 if(speed == 0)
90 {
91 strcpy(buf, _("Time left: Infinite (Transfer is standing still)"));
92 } else {
93 left = (data->curdisplay->size - data->curdisplay->pos) / speed;
ac3c3676
FT
94 if(left >= 86400)
95 sprintf(buf, _("Time left: %id%02ih%02im"), left / 86400, (left / 3600) % 24, (left / 60) % 60);
96 else if(left >= 3600)
97 sprintf(buf, _("Time left: %ih%02im"), left / 3600, (left / 60) % 60);
98 else
99 sprintf(buf, _("Time left: %im"), left / 60);
d3372da9 100 }
101 }
102 gtk_tooltips_set_tip(data->tips, GTK_WIDGET(data->applet), buf, NULL);
103 return(TRUE);
104}
105
106static void update(struct appletdata *data)
107{
108 char buf[256];
daa53556 109 size_t l;
d3372da9 110
111 switch(data->conduit->state)
112 {
113 case CNDS_IDLE:
114 gtk_progress_bar_set_text(data->pbar, _("Not connected"));
115 gtk_label_set_text(data->label, "");
116 break;
117 case CNDS_SYN:
118 gtk_progress_bar_set_text(data->pbar, _("Connecting..."));
119 gtk_label_set_text(data->label, "");
120 break;
121 case CNDS_EST:
122 if(data->conduit->transfers == NULL)
123 {
124 gtk_progress_bar_set_fraction(data->pbar, 0);
125 gtk_progress_bar_set_text(data->pbar, "");
126 gtk_label_set_text(data->label, _("No transfers to display"));
127 } else if(data->curdisplay == NULL) {
128 gtk_progress_bar_set_fraction(data->pbar, 0);
129 gtk_progress_bar_set_text(data->pbar, "");
130 gtk_label_set_text(data->label, _("No transfer selected"));
131 } else {
132 if((data->curdisplay->pos > 0) && (data->curdisplay->size > 0))
133 {
e03797e4 134 sprintf(buf, "%'ji/%'ji", (intmax_t)data->curdisplay->pos, (intmax_t)data->curdisplay->size);
d3372da9 135 gtk_progress_bar_set_fraction(data->pbar, (double)data->curdisplay->pos / (double)data->curdisplay->size);
136 gtk_progress_bar_set_text(data->pbar, buf);
137 } else {
138 gtk_progress_bar_set_fraction(data->pbar, 0);
139 gtk_progress_bar_set_text(data->pbar, _("Initializing"));
140 }
daa53556 141 if((l = strlen(data->curdisplay->tag)) > 50) {
142 memcpy(buf, data->curdisplay->tag, 20);
143 memcpy(buf + 20, "...", 3);
144 memcpy(buf + 23 , data->curdisplay->tag + l - 20, 20);
145 buf[43] = 0;
146 gtk_label_set_text(data->label, buf);
147 } else {
148 gtk_label_set_text(data->label, data->curdisplay->tag);
149 }
d3372da9 150 }
151 break;
152 }
153}
154
155static void trsize(struct transfer *transfer, struct appletdata *data)
156{
157 update(data);
158}
159
160static void trpos(struct transfer *transfer, struct appletdata *data)
161{
162 update(data);
163}
164
165static void trnew(struct transfer *transfer, struct appletdata *data)
166{
167 if(data->curdisplay == NULL)
168 data->curdisplay = transfer;
169 update(data);
170}
171
172static void trfree(struct transfer *transfer, struct appletdata *data)
173{
174 if(data->curdisplay == transfer)
175 data->curdisplay = data->conduit->transfers;
176 update(data);
177}
178
179static void condstate(struct conduit *conduit, struct appletdata *data)
180{
181 if(conduit->state == CNDS_IDLE)
182 g_timeout_add(10000, (gboolean (*)(gpointer))reconncb, data);
183 update(data);
184}
185
186static void initcond(void)
187{
188 static int inited = 0;
189
190 if(!inited)
191 {
192 cb_trsize = (void (*)(struct transfer *, void *))trsize;
193 cb_trpos = (void (*)(struct transfer *, void *))trpos;
194 cb_trnew = (void (*)(struct transfer *, void *))trnew;
195 cb_trfree = (void (*)(struct transfer *, void *))trfree;
196 cb_condstate = (void (*)(struct conduit *, void *))condstate;
197 inited = 1;
198 }
199}
200
201static gboolean trview_applet_button_press(GtkWidget *widget, GdkEventButton *event, struct appletdata *data)
202{
203 if(event->button == 1)
204 {
205 if(data->curdisplay == NULL)
206 data->curdisplay = data->conduit->transfers;
207 else if(data->curdisplay->next == NULL)
208 data->curdisplay = data->conduit->transfers;
209 else
210 data->curdisplay = data->curdisplay->next;
211 update(data);
212 }
213 return(FALSE);
214}
215
d55bc1df 216static gboolean trview_applet_scroll(GtkWidget *widget, GdkEventScroll *event, struct appletdata *data)
217{
218 struct transfer *tr;
219
220 if(event->direction == GDK_SCROLL_DOWN)
221 {
222 if(data->curdisplay == NULL)
223 data->curdisplay = data->conduit->transfers;
224 else if(data->curdisplay->next == NULL)
225 data->curdisplay = data->conduit->transfers;
226 else
227 data->curdisplay = data->curdisplay->next;
228 update(data);
229 } else if(event->direction == GDK_SCROLL_UP) {
230 if(data->curdisplay == NULL)
231 {
232 data->curdisplay = data->conduit->transfers;
233 } else if(data->curdisplay->prev == NULL) {
234 for(tr = data->conduit->transfers; tr->next != NULL; tr = tr->next);
235 data->curdisplay = tr;
236 } else {
237 data->curdisplay = data->curdisplay->prev;
238 }
239 update(data);
240 }
241 return(TRUE);
242}
243
d3372da9 244static void trview_applet_destroy(GtkWidget *widget, struct appletdata *data)
245{
246 freeconduit(data->conduit);
247 g_source_remove(data->tiptimeout);
248 g_object_unref(data->applet);
249 g_object_unref(data->tips);
250 free(data);
251}
252
253static gboolean trview_applet_fill(PanelApplet *applet, const gchar *iid, gpointer uudata)
254{
255 GtkWidget *hbox, *pbar, *label;
256 struct appletdata *data;
257
258 initcond();
259 if(strcmp(iid, "OAFIID:Dolcon_Transferapplet"))
260 return(FALSE);
261
d3372da9 262 hbox = gtk_hbox_new(FALSE, 0);
263 label = gtk_label_new("");
264 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
265 pbar = gtk_progress_bar_new();
266 gtk_box_pack_start(GTK_BOX(hbox), pbar, TRUE, TRUE, 0);
267 gtk_container_add(GTK_CONTAINER(applet), hbox);
268 gtk_widget_show_all(GTK_WIDGET(applet));
269
270 data = smalloc(sizeof(*data));
271 memset(data, 0, sizeof(*data));
272 g_object_ref(data->applet = applet);
273 data->conduit = newconduit(conduit_dclib, data);
274 data->pbar = GTK_PROGRESS_BAR(pbar);
275 g_object_ref(data->tips = gtk_tooltips_new());
276 data->tiptimeout = g_timeout_add(500, (gboolean (*)(gpointer))updatetip, data);
277 data->label = GTK_LABEL(label);
278
6431aca0 279 panel_applet_setup_menu(applet, ctxtmenu, ctxtmenuverbs, data);
280
d3372da9 281 g_signal_connect(applet, "button-press-event", (GCallback)trview_applet_button_press, data);
d55bc1df 282 g_signal_connect(applet, "scroll-event", (GCallback)trview_applet_scroll, data);
d3372da9 283 g_signal_connect(applet, "destroy", (GCallback)trview_applet_destroy, data);
284
285 condtryconn(data->conduit);
286
287 update(data);
288
289 return(TRUE);
290}
291
292#define GETTEXT_PACKAGE PACKAGE
293#define GNOMELOCALEDIR LOCALEDIR
294
295PANEL_APPLET_BONOBO_FACTORY("OAFIID:Dolcon_Transferapplet_Factory",
296 PANEL_TYPE_APPLET,
297 "Doldaconnect Transfer Viewer",
298 "0",
299 trview_applet_fill,
300 NULL);