1 #include <stdio.h>
2 #include <gdk/gdkkeysyms.h>
3 #include "urlgfe.h"
4 #include "utility.h"
5 #include "main_app.h"
6 #include "download_dialog.h"
7 #include "category_dialog.h"
8 #include "batch_dialog.h"
9 #include "download_thread.h"
10 #include "global_dialog.h"
11 #include "category_selection_dialog.h"
12
13 #ifdef G_OS_WIN32
14 #include <windows.h>
15 #define main_app_thread_sleep() Sleep (500);
16 #else
17 #define main_app_thread_sleep() sleep (1);
18 #endif
19
20 // utility functions ------------------------------------------------
21
add_batch_download(Category * cate,Download * download_data,const gchar * pattern,guint n_min,guint n_max,guint n_width)22 static void add_batch_download (Category* cate,
23 Download* download_data,
24 const gchar* pattern,
25 guint n_min,
26 guint n_max,
27 guint n_width)
28 {
29 DownloadSetting* setting = DOWNLOAD_SETTING (download_data);
30 const gchar* p_star;
31 GString *str_url;
32 gssize truncate_len;
33 guint n_serial;
34 UrlPart up;
35
36 for (p_star=pattern; *p_star; ++p_star) {
37 if (*p_star=='*')
38 break;
39 }
40 if (*p_star == 0)
41 return;
42
43
44 str_url = g_string_new_len (pattern, p_star-pattern);
45 truncate_len = str_url->len;
46 g_free (setting->filename);
47 g_free (setting->url);
48
49 for (n_serial=n_min; n_serial<=n_max; ++n_serial) {
50 if (n_width) {
51 g_string_append_printf (str_url,
52 "%.*u%s",
53 n_width,
54 n_serial,
55 p_star+1);
56 }
57 else { // character mode
58 g_string_append_printf (str_url,
59 "%c%s",
60 (unsigned char)n_serial,
61 p_star+1);
62 }
63 setting->url = str_url->str;
64 // get filename
65 url_part (&up, setting->url);
66 setting->filename = up.name_beg;
67
68 download_store_add (&cate->waiting_store, download_data);
69 g_string_truncate (str_url, truncate_len);
70 }
71 g_string_free (str_url, TRUE);
72
73 setting->filename = NULL;
74 setting->url = NULL;
75 }
76
77 // utility function for GtkTreeSelection
78 // malloc and return Selected GtkTreeIter
79 // return value : number of Selected GtkTreeIter
tree_selection_get_selected_iters(GtkTreeSelection * selection,GtkTreeIter ** iter_array)80 guint tree_selection_get_selected_iters (GtkTreeSelection* selection,
81 GtkTreeIter** iter_array)
82 {
83 GtkTreeModel* model;
84 GtkTreeIter* p_iter;
85 GList* path_list;
86 GList* node_prev;
87 guint n_iter;
88
89 if (n_iter = gtk_tree_selection_count_selected_rows (selection)) {
90 // allocate array of iter
91 *iter_array = g_malloc (sizeof (GtkTreeIter) * n_iter);
92 // get GList contain GtkTreePath
93 path_list = gtk_tree_selection_get_selected_rows (selection, &model);
94 // convert GtkTreePath to GtkTreeIter
95 p_iter = *iter_array;
96 while (path_list) {
97 gtk_tree_model_get_iter (model, p_iter, path_list->data);
98 p_iter++;
99 node_prev = path_list;
100 path_list = path_list->next;
101 gtk_tree_path_free (node_prev->data);
102 g_list_free_1 (node_prev);
103 }
104 return n_iter;
105 }
106 return 0;
107 }
108
show_about_dialog(GtkWindow * parent)109 static void show_about_dialog (GtkWindow* parent)
110 {
111 GtkWidget* vbox;
112 // GtkWidget* image;
113 GtkWidget* label;
114 GtkWidget* dialog;
115
116 dialog = gtk_dialog_new_with_buttons (_("About UrlGfe"),
117 parent,
118 (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT),
119 GTK_STOCK_OK,
120 GTK_RESPONSE_OK,
121 NULL);
122 gtk_window_set_default_size (GTK_WINDOW (dialog), 150, 150);
123 vbox = GTK_DIALOG (dialog)->vbox;
124 // icon
125 // image = gtk_image_new_from_file (PACKAGE_PIXMAPS_DIR G_DIR_SEPARATOR_S"urlget_icon.png");
126 // gtk_box_pack_start (GTK_BOX(vbox), image, FALSE, FALSE, 0);
127 label = gtk_label_new ("UrlGfe 0.7 stable");
128 gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 0);
129 label = gtk_label_new (_("Copyright(C) 2002-2004 Plus Huang"));
130 gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 0);
131 label = gtk_label_new ("http://urlget.sourceforge.net/");
132 gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 0);
133 gtk_widget_show_all (vbox);
134
135 gtk_dialog_run (GTK_DIALOG (dialog));
136 gtk_widget_destroy (dialog);
137 }
138
139 // End of utility functions =========================================
140
141
142 // download signal handler ------------------------------------------
on_download_start(MainApp * app)143 static void on_download_start (MainApp* app)
144 {
145 GtkTreeSelection* selection;
146 DownloadListView* download_view;
147 DownloadStore* download_store;
148 Category* category;
149
150 DownloadSetting* setting;
151 DownloadThread* thread;
152
153 GtkTreeIter* iter_array;
154 guint n_iter;
155 guint index;
156
157 gboolean need_active = FALSE;
158
159 if (category_tree_view_get_selected (app->window.category_view,
160 &category,
161 &download_view,
162 &download_store)==FALSE )
163 {
164 return;
165 }
166
167 selection = gtk_tree_view_get_selection (download_view->self);
168
169 download_store_lock (download_store);
170
171 if ( n_iter=tree_selection_get_selected_iters (selection, &iter_array) )
172 {
173 for (index=0; index<n_iter; index++) {
174 gtk_tree_model_get ((GtkTreeModel*)download_store->list_store,
175 iter_array + index,
176 DOWNLOAD_COL_DATA, &setting,
177 DOWNLOAD_COL_THREAD, &thread,
178 -1);
179 if (thread==NULL) {
180 setting->state = DOWNLOAD_STATE_WAITING;
181 download_store_row_changed (download_store, iter_array+index);
182 }
183 }
184 g_free (iter_array);
185 need_active = TRUE;
186 }
187
188 download_store_unlock (download_store);
189
190 if (need_active)
191 category_store_thread_activate_1 (&app->category_store, category);
192 }
193
on_download_stop(MainApp * app)194 static void on_download_stop (MainApp* app)
195 {
196 GtkTreeSelection* selection;
197 DownloadListView* download_view;
198 DownloadStore* download_store;
199 Category* category;
200
201 DownloadSetting* setting;
202 DownloadThread* thread;
203
204 GtkTreeIter* iter_array;
205 guint n_iter;
206 guint index;
207
208 if (category_tree_view_get_selected (app->window.category_view,
209 &category,
210 &download_view,
211 &download_store) == FALSE )
212 {
213 return;
214 }
215
216 selection = gtk_tree_view_get_selection (download_view->self);
217
218 download_store_lock (download_store);
219
220 if ( n_iter=tree_selection_get_selected_iters (selection, &iter_array) )
221 {
222 for (index=0; index<n_iter; index++) {
223 gtk_tree_model_get ((GtkTreeModel*)download_store->list_store,
224 iter_array + index,
225 DOWNLOAD_COL_DATA, &setting,
226 DOWNLOAD_COL_THREAD, &thread,
227 -1);
228 if (thread)
229 download_thread_skip (thread);
230 else {
231 setting->state = DOWNLOAD_STATE_PAUSE;
232 download_store_row_changed (download_store, iter_array+index);
233 }
234 }
235 g_free (iter_array);
236 }
237
238 download_store_unlock (download_store);
239 }
240
on_download_new(MainApp * app)241 static void on_download_new (MainApp* app)
242 {
243 gchar* clip_text = NULL;
244
245 Category* selected_category = NULL;
246 UrlPart urlp;
247
248 // check Clipboard
249 if ( gtk_clipboard_wait_is_text_available (app->clipboard) ) {
250 clip_text = gtk_clipboard_wait_for_text (app->clipboard);
251
252 url_part (&urlp, clip_text);
253 if ( urlp.protocol_beg == NULL ) {
254 g_free (clip_text);
255 clip_text = NULL;
256 }
257 }
258
259 main_app_add_download_from_url (app, clip_text);
260
261 g_free (clip_text);
262 }
263
on_download_batch(MainApp * app)264 static void on_download_batch (MainApp* app)
265 {
266 BatchDialog bat_dialog;
267 gint batch_mode;
268 gint max, min, width;
269 gchar* pattern;
270
271 Download* download_data;
272 gboolean had_selected;
273 Category* selected_category;
274
275 // batch dialog
276 batch_dialog_init (&bat_dialog, app->window.self);
277
278 if ( (batch_mode=batch_dialog_run (&bat_dialog))==BATCH_MODE_NONE ) {
279 batch_dialog_clear (&bat_dialog);
280 return;
281 }
282 if (batch_mode == BATCH_MODE_CHAR) {
283 max = batch_dialog_get_char_max (&bat_dialog);
284 min = batch_dialog_get_char_min (&bat_dialog);
285 width = 0;
286 }
287 else {
288 max = batch_dialog_get_int_max (&bat_dialog);
289 min = batch_dialog_get_int_min (&bat_dialog);
290 width = batch_dialog_get_int_width (&bat_dialog);
291 }
292 pattern = g_strdup (batch_dialog_get_pattern (&bat_dialog) );
293
294 batch_dialog_clear (&bat_dialog);
295
296 // download import dialog
297 // initial
298 download_data = download_new ();
299 had_selected = main_app_get_download_from_user (app,
300 DOWNLOAD_SETTING (download_data),
301 &selected_category,
302 TRUE);
303 if (had_selected) {
304 add_batch_download (selected_category,
305 download_data,
306 pattern,
307 min,
308 max,
309 width);
310 // try to start-up thread.
311 category_store_thread_activate_1 (&app->category_store,
312 selected_category);
313 }
314
315 download_unref (download_data);
316 g_free (pattern);
317 }
318
319 // bugs here
on_download_erase(MainApp * app)320 static void on_download_erase (MainApp* app)
321 {
322 GdkWindow* gdk_win;
323 GdkModifierType mask;
324
325 GtkTreeSelection* selection;
326 DownloadListView* download_view;
327 DownloadStore* download_store;
328 Category* category;
329
330 Download* dl_data;
331 DownloadThread* thread;
332
333 GtkTreeIter* iter_array;
334 guint n_iter;
335 guint index;
336
337 if (category_tree_view_get_selected (app->window.category_view,
338 &category,
339 &download_view,
340 &download_store)==FALSE )
341 {
342 return;
343 }
344
345 selection = gtk_tree_view_get_selection (download_view->self);
346
347 download_store_lock (download_store);
348
349 if ( n_iter=tree_selection_get_selected_iters (selection, &iter_array) )
350 {
351 gdk_win = gtk_widget_get_parent_window ((GtkWidget*)download_view->self);
352 gdk_window_get_pointer (gdk_win, NULL, NULL, &mask);
353
354 for (index=0; index<n_iter; index++) {
355 gtk_tree_model_get ((GtkTreeModel*)download_store->list_store,
356 iter_array + index,
357 DOWNLOAD_COL_DATA, &dl_data,
358 DOWNLOAD_COL_THREAD, &thread,
359 -1);
360 if (thread)
361 download_thread_job_erased (thread);
362 if ( &category->recycled_store == download_store || mask & GDK_SHIFT_MASK)
363 download_store_erase (download_store, iter_array+index);
364 else {
365 download_store_move_to_store (download_store,
366 &category->recycled_store,
367 iter_array + index);
368 }
369 }
370 g_free (iter_array);
371
372 category_changed (category);
373 }
374
375 download_store_unlock (download_store);
376 }
377
on_download_property(MainApp * app)378 static void on_download_property (MainApp* app)
379 {
380 DownloadListView* download_view;
381 DownloadStore* download_store;
382 Download* dl_data;
383 GList* dl_list;
384 GList* node;
385 gint n_iter;
386
387 if (category_tree_view_get_selected (app->window.category_view,
388 NULL,
389 &download_view,
390 &download_store)==FALSE )
391 {
392 return;
393 }
394
395 dl_list = download_list_view_selected_list_copy (download_view, &n_iter);
396
397 if (n_iter) {
398 dl_data = download_new ();
399 download_assign (dl_data, dl_list->data);
400 if (n_iter>1)
401 DOWNLOAD_SETTING (dl_data)->multiple = TRUE;
402 if ( main_app_get_download_from_user (app, DOWNLOAD_SETTING (dl_data),
403 NULL, (n_iter>1) ? TRUE : FALSE) )
404 {
405 for (node=dl_list; node; node=node->next)
406 download_assign (node->data, dl_data);
407 }
408 download_unref (dl_data);
409 }
410
411 download_list_view_selected_list_free (dl_list);
412
413 main_window_update_download_view (&app->window);
414 main_window_text_view_update (&app->window);
415 }
416
on_download_move_to(MainApp * app)417 static void on_download_move_to (MainApp* app)
418 {
419 CategorySelectionDialog* csd;
420 DownloadListView* dlv_src;
421 DownloadListView* dlv_dest;
422 gboolean had_selected;
423
424 had_selected = category_tree_view_get_selected (app->window.category_view,
425 NULL,
426 &dlv_src,
427 NULL );
428
429 csd = category_selection_dialog_new (_("Move selected download to..."),
430 &app->category_store,
431 app->window.self);
432
433 if (gtk_dialog_run (csd->self)==GTK_RESPONSE_OK) {
434 had_selected = category_tree_view_get_selected (csd->category_view,
435 NULL,
436 &dlv_dest,
437 NULL);
438 if (had_selected && dlv_src!=dlv_dest) {
439 main_app_move_selected_download (app, dlv_src, dlv_dest);
440 main_window_text_view_update (&app->window);
441 }
442 }
443
444 category_selection_dialog_destroy (csd);
445
446 category_store_thread_activate (&app->category_store);
447 }
448
on_download_move_top(MainApp * app)449 static void on_download_move_top (MainApp* app)
450 {
451 GtkTreeSelection* selection;
452 DownloadListView* download_view;
453 DownloadStore* download_store;
454 GtkTreeIter* iter_array;
455 guint n_iter;
456
457 if (category_tree_view_get_selected (app->window.category_view,
458 NULL,
459 &download_view,
460 &download_store)==FALSE )
461 {
462 return;
463 }
464
465 selection = gtk_tree_view_get_selection (download_view->self);
466
467 download_store_lock (download_store);
468
469 if ( n_iter=tree_selection_get_selected_iters (selection, &iter_array) )
470 {
471 while (n_iter--) {
472 gtk_list_store_move_after (download_store->list_store,
473 iter_array + n_iter, NULL);
474 }
475 g_free (iter_array);
476 }
477
478 download_store_unlock (download_store);
479 }
480
on_download_move_bottom(MainApp * app)481 static void on_download_move_bottom (MainApp* app)
482 {
483 GtkTreeSelection* selection;
484 DownloadListView* download_view;
485 DownloadStore* download_store;
486 GtkTreeIter* iter_array;
487 guint n_iter;
488 guint index;
489
490 if (category_tree_view_get_selected (app->window.category_view,
491 NULL,
492 &download_view,
493 &download_store)==FALSE )
494 {
495 return;
496 }
497
498 selection = gtk_tree_view_get_selection (download_view->self);
499
500 download_store_lock (download_store);
501
502 if ( n_iter=tree_selection_get_selected_iters (selection, &iter_array) )
503 {
504 for (index=0; index<n_iter; index++) {
505 gtk_list_store_move_before (download_store->list_store,
506 iter_array + index, NULL);
507 }
508 g_free (iter_array);
509 }
510
511 download_store_unlock (download_store);
512 }
513
514 // End of download signal handler ===================================
515
516
517 // category signal handler ------------------------------------------
518
on_category_new(MainApp * app)519 static void on_category_new (MainApp* app)
520 {
521 CategoryDialog* dialog;
522 CategorySetting setting;
523 Category* category;
524
525 dialog = category_dialog_new (app->window.self);
526 category_setting_init (&setting);
527 category_setting_assign (&setting, CATEGORY_SETTING (app->setting));
528 download_setting_view_set_history (DOWNLOAD_SETTING_VIEW (&dialog->setting_view),
529 app->setting->directory_list);
530
531 category_setting_view_set (&dialog->setting_view, &setting);
532
533 if (gtk_dialog_run (GTK_DIALOG (dialog->self))==GTK_RESPONSE_OK) {
534 category_setting_view_get (&dialog->setting_view, &setting);
535 category = category_new_from_setting (&setting);
536 category_store_append (&app->category_store, category);
537 main_app_connect_category_signal (app, category);
538 }
539
540 category_setting_clear (&setting);
541 category_dialog_destroy (dialog);
542 }
543
on_category_erase(MainApp * app)544 static void on_category_erase (MainApp* app)
545 {
546 Category* category;
547 GtkWidget* dialog;
548 gint response;
549
550 if ( category_tree_view_get_selected (app->window.category_view,
551 &category, NULL, NULL)==FALSE )
552 {
553 return;
554 }
555
556 dialog = gtk_message_dialog_new (app->window.self,
557 GTK_DIALOG_DESTROY_WITH_PARENT,
558 GTK_MESSAGE_WARNING,
559 GTK_BUTTONS_YES_NO,
560 _("This will erase category and it's download. Are you sure to erase?"));
561 response = gtk_dialog_run (GTK_DIALOG(dialog));
562 gtk_widget_destroy(dialog);
563
564 if (response == GTK_RESPONSE_YES) {
565 main_window_on_category_erasing (&app->window, category);
566 // category_thread_destroy (category);
567 category_store_erase (&app->category_store, category);
568
569 // check selection when erase category
570 main_window_selection_changed (&app->window);
571 }
572 }
573
on_category_property(MainApp * app)574 static void on_category_property (MainApp* app)
575 {
576 CategoryDialog* dialog;
577 Category* category;
578
579 if ( category_tree_view_get_selected (app->window.category_view,
580 &category, NULL, NULL)==FALSE )
581 {
582 return;
583 }
584
585 dialog = category_dialog_new (app->window.self);
586 download_setting_view_set_history (DOWNLOAD_SETTING_VIEW (&dialog->setting_view),
587 app->setting->directory_list);
588
589 category_setting_view_set (&dialog->setting_view,
590 CATEGORY_SETTING(category));
591
592 if (gtk_dialog_run (GTK_DIALOG (dialog->self))==GTK_RESPONSE_OK) {
593 category_setting_view_get (&dialog->setting_view,
594 CATEGORY_SETTING(category));
595 category_apply_setting (category);
596 category_changed (category);
597 }
598
599 category_dialog_destroy (dialog);
600 category_store_thread_activate_1 (&app->category_store, category);
601 }
602
603 // End of category signal handler ===================================
604
605
606 // global signal handler --------------------------------------------
607
on_set_category_default(MainApp * app)608 static void on_set_category_default (MainApp* app)
609 {
610 CategoryDialog* dialog;
611
612 dialog = category_dialog_new (app->window.self);
613 download_setting_view_set_history (DOWNLOAD_SETTING_VIEW (&dialog->setting_view),
614 app->setting->directory_list);
615
616 category_setting_view_set (&dialog->setting_view,
617 CATEGORY_SETTING(app->setting));
618 category_setting_view_set_multiple (&dialog->setting_view, TRUE);
619
620 if (gtk_dialog_run (GTK_DIALOG (dialog->self))==GTK_RESPONSE_OK) {
621 category_setting_view_get (&dialog->setting_view,
622 CATEGORY_SETTING(app->setting));
623 }
624
625 category_dialog_destroy (dialog);
626 }
627
on_set_global_setting(MainApp * app)628 static void on_set_global_setting (MainApp* app)
629 {
630 GlobalDialog* gd;
631
632 gd = global_dialog_new (app->window.self);
633
634 global_dialog_set (gd, app->setting);
635
636 if (gtk_dialog_run (gd->self)==GTK_RESPONSE_OK)
637 global_dialog_get (gd, app->setting);
638
639 global_dialog_destroy (gd);
640
641 main_app_apply_setting (app);
642 category_store_thread_activate (&app->category_store);
643 }
644 // End of global signal handler =====================================
645
646 // keyboard
on_key_press_event(MainApp * app,GdkEventKey * event,GtkWidget * widget)647 gboolean on_key_press_event(MainApp* app,
648 GdkEventKey *event,
649 GtkWidget *widget)
650 {
651 if (event->keyval==GDK_Delete) {
652 if (widget == (GtkWidget*)app->window.category_view)
653 on_category_erase (app);
654 else
655 on_download_erase (app);
656 }
657 return FALSE;
658 }
659
660 // MainApp
main_app_init(MainApp * app)661 void main_app_init (MainApp* app)
662 {
663 const gchar* home_dir = g_get_home_dir ();
664
665 category_store_init (&app->category_store);
666 main_window_init (&app->window, &app->category_store);
667
668 // clipboard data
669 app->clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
670 app->clipboard_text = NULL;
671 app->clipboard_timer_tag = 0;
672 app->clipboard_monitoring = FALSE;
673 app->clipboard_waiting = FALSE;
674
675 // read setting file
676 if (main_app_read_setting_file (app, urlgfe_get_conf_filename ())==FALSE) {
677 app->setting = global_setting_new ();
678 }
679
680 // read data file
681 if (main_app_read_data_file (app, urlgfe_get_data_filename ())==FALSE) {
682 Category* category = category_new();
683
684 category_setting_set_name (CATEGORY_SETTING (category), "Home");
685 download_setting_set_directory (DOWNLOAD_SETTING (category), home_dir);
686
687 category_store_append (&app->category_store, category);
688 gtk_tree_view_expand_all (app->window.category_view);
689 }
690
691 // window
692 g_signal_connect (app->window.self, "destroy",
693 G_CALLBACK(gtk_main_quit), NULL);
694 g_signal_connect_swapped (app->window.self, "delete-event",
695 G_CALLBACK(main_app_on_delete_event), app);
696 g_signal_connect_swapped (app->window.category_view, "key-press-event",
697 G_CALLBACK (on_key_press_event), app);
698
699
700 // file menu
701 g_signal_connect_swapped (app->window.file_menu.load, "activate",
702 G_CALLBACK(main_app_on_load), app);
703 g_signal_connect_swapped (app->window.file_menu.save, "activate",
704 G_CALLBACK(main_app_on_save), app);
705 g_signal_connect_swapped (app->window.file_menu.save_as, "activate",
706 G_CALLBACK(main_app_on_save_as), app);
707 g_signal_connect_swapped (app->window.file_menu.import_html, "activate",
708 G_CALLBACK(main_app_on_import_html), app);
709 g_signal_connect_swapped (app->window.file_menu.export, "activate",
710 G_CALLBACK(main_app_on_export_url), app);
711
712 // download
713 g_signal_connect_swapped (app->window.button_start, "clicked",
714 G_CALLBACK(on_download_start), app);
715 g_signal_connect_swapped (app->window.button_stop, "clicked",
716 G_CALLBACK(on_download_stop), app);
717 g_signal_connect_swapped (app->window.button_new, "clicked",
718 G_CALLBACK(on_download_new), app);
719 g_signal_connect_swapped (app->window.button_batch, "clicked",
720 G_CALLBACK(on_download_batch), app);
721 g_signal_connect_swapped (app->window.button_erase, "clicked",
722 G_CALLBACK(on_download_erase), app);
723 g_signal_connect_swapped (app->window.button_property, "clicked",
724 G_CALLBACK(on_download_property), app);
725 g_signal_connect_swapped (app->window.button_move_top, "clicked",
726 G_CALLBACK(on_download_move_top), app);
727 g_signal_connect_swapped (app->window.button_move_bottom, "clicked",
728 G_CALLBACK(on_download_move_bottom), app);
729 // CategoryMenu
730 g_signal_connect_swapped (app->window.category_menu.new_category, "activate",
731 G_CALLBACK(on_category_new), app);
732 g_signal_connect_swapped (app->window.category_menu.erase_category, "activate",
733 G_CALLBACK(on_category_erase), app);
734 g_signal_connect_swapped (app->window.category_menu.properties, "activate",
735 G_CALLBACK(on_category_property), app);
736 // DownloadMenu
737 g_signal_connect_swapped (app->window.download_menu.start, "activate",
738 G_CALLBACK(on_download_start), app);
739 g_signal_connect_swapped (app->window.download_menu.stop, "activate",
740 G_CALLBACK(on_download_stop), app);
741 g_signal_connect_swapped (app->window.download_menu.new_download, "activate",
742 G_CALLBACK(on_download_new), app);
743 g_signal_connect_swapped (app->window.download_menu.add_batch, "activate",
744 G_CALLBACK(on_download_batch), app);
745 g_signal_connect_swapped (app->window.download_menu.erase, "activate",
746 G_CALLBACK(on_download_erase), app);
747 g_signal_connect_swapped (app->window.download_menu.properties, "activate",
748 G_CALLBACK(on_download_property), app);
749 g_signal_connect_swapped (app->window.download_menu.move_to, "activate",
750 G_CALLBACK(on_download_move_to), app);
751 g_signal_connect_swapped (app->window.download_menu.move_top, "activate",
752 G_CALLBACK(on_download_move_top), app);
753 g_signal_connect_swapped (app->window.download_menu.move_bottom, "activate",
754 G_CALLBACK(on_download_move_bottom), app);
755 // Global Menu
756 g_signal_connect_swapped (app->window.global_menu.start_job, "activate",
757 G_CALLBACK(category_store_thread_activate),
758 &app->category_store);
759 g_signal_connect_swapped (app->window.global_menu.stop_all, "activate",
760 G_CALLBACK(category_store_thread_stop),
761 &app->category_store);
762 g_signal_connect_swapped (app->window.global_menu.category_default, "activate",
763 G_CALLBACK(on_set_category_default), app);
764 g_signal_connect_swapped (app->window.global_menu.setting, "activate",
765 G_CALLBACK(on_set_global_setting), app);
766
767 // Help Menu
768 g_signal_connect_swapped (app->window.help_menu.about_urlgfe, "activate",
769 G_CALLBACK(show_about_dialog), app->window.self);
770
771 main_window_selection_changed (&app->window);
772
773 // init Drag and Drop
774 main_app_dnd_init (app);
775
776 main_app_apply_setting (app);
777 }
778
main_app_run(MainApp * app)779 void main_app_run (MainApp* app)
780 {
781 gtk_widget_show (GTK_WIDGET (app->window.self));
782 }
783
main_app_on_delete_event(MainApp * app)784 gboolean main_app_on_delete_event (MainApp* app)
785 {
786 GtkWidget* dialog;
787 gint response;
788
789 if (category_store_thread_is_active (&app->category_store)) {
790 dialog = gtk_message_dialog_new (app->window.self,
791 GTK_DIALOG_DESTROY_WITH_PARENT,
792 GTK_MESSAGE_WARNING,
793 GTK_BUTTONS_YES_NO,
794 _("There are still downloading. Are you sure to quit?"));
795 response = gtk_dialog_run (GTK_DIALOG(dialog));
796 gtk_widget_destroy (dialog);
797
798 if (response==GTK_RESPONSE_NO)
799 return TRUE;
800 }
801 category_store_thread_destroy (&app->category_store);
802 main_app_on_save (app);
803
804 return FALSE;
805 }
806
main_app_apply_setting(MainApp * app)807 void main_app_apply_setting (MainApp* app)
808 {
809 app->category_store.n_thread_limit = app->setting->n_active_category;
810 gtk_tree_view_set_headers_visible (app->window.category_view,
811 app->setting->header_category_visible);
812
813 if (app->clipboard_monitoring != app->setting->monitoring_clipboard) {
814 if (app->clipboard_monitoring == TRUE) {
815 g_source_remove (app->clipboard_timer_tag);
816 app->clipboard_timer_tag = 0;
817 }
818 else if (app->clipboard_timer_tag==0) {
819 app->clipboard_timer_tag = g_timeout_add (500,
820 (GSourceFunc)main_app_on_timer, app);
821 }
822 app->clipboard_monitoring = app->setting->monitoring_clipboard;
823 }
824 }
825
main_app_add_download_from_url(MainApp * app,const gchar * url_text)826 void main_app_add_download_from_url (MainApp* app, const gchar* url_text)
827 {
828 Category* selected_category = NULL;
829 Download* download_data;
830 gboolean had_selected;
831
832 download_data = download_new ();
833 download_setting_set_url (DOWNLOAD_SETTING (download_data), url_text);
834
835 had_selected = main_app_get_download_from_user (app,
836 DOWNLOAD_SETTING (download_data),
837 &selected_category,
838 FALSE);
839 if (had_selected) {
840 download_store_add_allocated (&selected_category->waiting_store,
841 download_data);
842 category_store_thread_activate_1 (&app->category_store,
843 selected_category);
844 }
845 else
846 download_unref (download_data);
847 }
848
main_app_get_download_from_user(MainApp * app,DownloadSetting * setting,Category ** selected_category,gboolean multiple)849 gboolean main_app_get_download_from_user (MainApp* app,
850 DownloadSetting* setting,
851 Category** selected_category,
852 gboolean multiple)
853 {
854 DownloadDialog* dd = download_dialog_new (app->window.self);
855 Category* category;
856 gboolean had_input = FALSE;
857
858
859 if (selected_category) {
860 category_tree_view_get_selected (app->window.category_view,
861 &category, NULL, NULL);
862 download_dialog_set_category (dd,
863 &app->category_store,
864 category);
865 }
866
867 download_setting_view_set_history (&dd->setting_view,
868 app->setting->directory_list);
869 download_dialog_import_setting (dd, setting);
870 download_dialog_set_multiple (dd, multiple);
871
872 if (download_dialog_run (dd)==GTK_RESPONSE_OK) {
873 download_dialog_export_setting (dd, setting);
874 global_setting_add_directory (app->setting, setting->directory);
875 had_input = TRUE;
876
877 if (selected_category)
878 *selected_category = dd->selected_category;
879 }
880
881 download_dialog_destroy (dd);
882
883 return had_input;
884 }
885
main_app_move_selected_download(MainApp * app,DownloadListView * dlv_src,DownloadListView * dlv_dest)886 void main_app_move_selected_download (MainApp* app,
887 DownloadListView* dlv_src,
888 DownloadListView* dlv_dest)
889 {
890 guint n_iter, index;
891 GtkTreeIter* iter_array;
892 GtkTreeSelection* selection;
893 DownloadStore* ds_src = dlv_src->store;
894 DownloadStore* ds_dest = dlv_dest->store;
895
896 selection = gtk_tree_view_get_selection (dlv_src->self);
897
898 download_store_lock (ds_src);
899
900 n_iter = tree_selection_get_selected_iters (selection, &iter_array);
901
902 for (index=0; index < n_iter; index++) {
903 download_store_move_to_store (ds_src,
904 ds_dest,
905 iter_array+index);
906 }
907 g_free (iter_array);
908
909 download_store_unlock (ds_src);
910
911 // update CategoryTree
912 gtk_widget_queue_draw (GTK_WIDGET (app->window.category_view));
913
914 category_store_thread_activate (&app->category_store);
915 }
916
main_app_connect_category_signal(MainApp * app,Category * category)917 void main_app_connect_category_signal (MainApp* app,
918 Category* category)
919 {
920 main_window_connect_download_view (&app->window,
921 &category->waiting_view);
922 main_window_connect_download_view (&app->window,
923 &category->completed_view);
924 main_window_connect_download_view (&app->window,
925 &category->recycled_view);
926 g_signal_connect_swapped (category->waiting_view.self, "key-press-event",
927 G_CALLBACK (on_key_press_event), app);
928 g_signal_connect_swapped (category->completed_view.self, "key-press-event",
929 G_CALLBACK (on_key_press_event), app);
930 g_signal_connect_swapped (category->recycled_view.self, "key-press-event",
931 G_CALLBACK (on_key_press_event), app);
932 }
933
934
935