add RFE 4686, 'use gtk native filechooser'
[claws.git] / src / plugins / archive / archiver_gtk.c
blob9ede629106cfc8d0be1ac57d5049701ddc922930
1 /* vim: set textwidth=80 tabstop=4 */
3 /*
4 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
5 * Copyright (C) 1999-2023 Michael Rasmussen and the Claws Mail Team
7 * This program 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 ii*
12 * This program 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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #include "claws-features.h"
25 #endif
27 #include <glib.h>
28 #include <glib/gi18n.h>
30 #include "defs.h"
32 #include <gtk/gtk.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <errno.h>
38 #include "gtk/gtkutils.h"
39 #include "common/claws.h"
40 #include "common/version.h"
41 #include "common/md5.h"
42 #include "plugin.h"
43 #include "mainwindow.h"
44 #include "file-utils.h"
45 #include "utils.h"
46 #include "prefs.h"
47 #include "folder.h"
48 #include "foldersel.h"
49 #include "procmsg.h"
50 #include "procheader.h"
51 #include "libarchive_archive.h"
52 #include "archiver.h"
53 #include "archiver_prefs.h"
54 #include "alertpanel.h"
56 #include <archive.h>
58 typedef struct _progress_widget progress_widget;
59 struct _progress_widget {
60 GtkWidget* progress_dialog;
61 GtkWidget* frame;
62 GtkWidget* vbox1;
63 GtkWidget* hbox1;
64 GtkWidget* add_label;
65 GtkWidget* file_label;
66 GtkWidget* progress;
67 guint position;
70 typedef enum {
71 A_FILE_OK = 1 << 0,
72 A_FILE_EXISTS = 1 << 1,
73 A_FILE_IS_LINK = 1 << 2,
74 A_FILE_IS_DIR = 1 << 3,
75 A_FILE_NO_WRITE = 1 << 4,
76 A_FILE_UNKNOWN = 1 << 5
77 } AFileTest;
79 static progress_widget* progress = NULL;
81 static progress_widget* init_progress() {
82 progress_widget* ptr = malloc(sizeof(*ptr));
84 debug_print("creating progress struct\n");
85 ptr->progress_dialog = NULL;
86 ptr->frame = NULL;
87 ptr->vbox1 = NULL;
88 ptr->hbox1 = NULL;
89 ptr->add_label = NULL;
90 ptr->file_label = NULL;
91 ptr->progress = NULL;
92 ptr->position = 0;
94 return ptr;
97 static void progress_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
98 struct ArchivePage* page = (struct ArchivePage *) data;
100 debug_print("Cancel operation\n");
101 stop_archiving();
102 page->cancelled = TRUE;
103 archive_free_file_list(page->md5, page->rename);
104 gtk_widget_destroy(widget);
107 static void create_progress_dialog(struct ArchivePage* page) {
108 gchar* title = g_strdup_printf("%s %s", _("Archiving"), page->path);
109 MainWindow* mainwin = mainwindow_get_mainwindow();
110 GtkWidget *content_area;
112 progress->position = 0;
113 progress->progress_dialog = gtk_dialog_new_with_buttons (
114 title,
115 GTK_WINDOW(mainwin->window),
116 GTK_DIALOG_DESTROY_WITH_PARENT,
117 _("_Cancel"),
118 GTK_RESPONSE_CANCEL,
119 NULL);
121 g_signal_connect (
122 progress->progress_dialog,
123 "response",
124 G_CALLBACK(progress_dialog_cb),
125 page);
127 progress->frame = gtk_frame_new(_("Press Cancel button to stop archiving"));
128 gtk_frame_set_shadow_type(GTK_FRAME(progress->frame),
129 GTK_SHADOW_ETCHED_OUT);
130 gtk_container_set_border_width(GTK_CONTAINER(progress->frame), 4);
131 content_area = gtk_dialog_get_content_area(GTK_DIALOG(progress->progress_dialog));
132 gtk_container_add(GTK_CONTAINER(content_area), progress->frame);
134 progress->vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
135 gtk_container_set_border_width (GTK_CONTAINER (progress->vbox1), 4);
136 gtk_container_add(GTK_CONTAINER(progress->frame), progress->vbox1);
138 progress->hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
139 gtk_container_set_border_width(GTK_CONTAINER(progress->hbox1), 8);
140 gtk_box_pack_start(GTK_BOX(progress->vbox1),
141 progress->hbox1, FALSE, FALSE, 0);
143 progress->add_label = gtk_label_new(_("Archiving:"));
144 gtk_box_pack_start(GTK_BOX(progress->hbox1),
145 progress->add_label, FALSE, FALSE, 0);
147 progress->file_label = gtk_label_new("");
148 gtk_label_set_ellipsize(GTK_LABEL(progress->file_label),
149 PANGO_ELLIPSIZE_START);
150 gtk_box_pack_start(GTK_BOX(progress->hbox1),
151 progress->file_label, TRUE, TRUE, 0);
153 progress->hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
154 gtk_container_set_border_width(GTK_CONTAINER(progress->hbox1), 8);
155 gtk_box_pack_start(GTK_BOX(progress->vbox1),
156 progress->hbox1, FALSE, FALSE, 0);
158 progress->progress = gtk_progress_bar_new();
159 gtk_box_pack_start(GTK_BOX(progress->hbox1),
160 progress->progress, TRUE, TRUE, 0);
161 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress->progress), 0.25);
163 gtk_window_set_default_size(GTK_WINDOW(progress->progress_dialog), 400, 80);
164 gtk_widget_show_all(progress->progress_dialog);
167 static struct ArchivePage* init_archive_page() {
168 struct ArchivePage* page = malloc(sizeof(struct ArchivePage));
170 debug_print("creating ArchivePage\n");
171 page->path = NULL;
172 page->name = NULL;
173 page->file = NULL;
174 page->folder = NULL;
175 page->response = FALSE;
176 page->force_overwrite = FALSE;
177 page->compress_methods = NULL;
178 page->archive_formats = NULL;
179 page->recursive = NULL;
180 page->cancelled = FALSE;
181 page->md5 = FALSE;
182 page->md5sum = NULL;
183 page->rename = FALSE;
184 page->rename_files = NULL;
185 page->isoDate = NULL;
186 page->unlink_files = NULL;
187 page->unlink = FALSE;
189 return page;
192 static void dispose_archive_page(struct ArchivePage* page) {
193 debug_print("freeing ArchivePage\n");
194 if (page->path)
195 g_free(page->path);
196 page->path = NULL;
197 if (page->name)
198 g_free(page->name);
199 page->name = NULL;
200 g_free(page);
203 static gboolean valid_file_name(gchar* file) {
204 int i;
206 for (i = 0; INVALID_UNIX_CHARS[i] != '\0'; i++) {
207 if (g_utf8_strchr(file, g_utf8_strlen(file, -1), INVALID_UNIX_CHARS[i]))
208 return FALSE;
210 return TRUE;
213 static COMPRESS_METHOD get_compress_method(GSList* btn) {
214 const gchar* name;
216 while (btn) {
217 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn->data))) {
218 name = gtk_widget_get_name(GTK_WIDGET(btn->data));
219 if (strcmp("GZIP", name) == 0) {
220 debug_print("GZIP compression enabled\n");
221 return GZIP;
223 else if (strcmp("BZIP", name) == 0) {
224 debug_print("BZIP2 compression enabled\n");
225 return BZIP2;
227 else if (strcmp("COMPRESS", name) == 0) {
228 debug_print("COMPRESS compression enabled\n");
229 return COMPRESS;
231 #if ARCHIVE_VERSION_NUMBER >= 2006990
232 else if (strcmp("LZMA", name) == 0) {
233 debug_print("LZMA compression enabled\n");
234 return LZMA;
236 else if (strcmp("XZ", name) == 0) {
237 debug_print("XZ compression enabled\n");
238 return XZ;
240 #endif
241 #if ARCHIVE_VERSION_NUMBER >= 3000000
242 else if (strcmp("LZIP", name) == 0) {
243 debug_print("LZIP compression enabled\n");
244 return LZIP;
246 #endif
247 #if ARCHIVE_VERSION_NUMBER >= 3001000
248 else if (strcmp("LRZIP", name) == 0) {
249 debug_print("LRZIP compression enabled\n");
250 return LRZIP;
252 else if (strcmp("LZOP", name) == 0) {
253 debug_print("LZOP compression enabled\n");
254 return LZOP;
256 else if (strcmp("GRZIP", name) == 0) {
257 debug_print("GRZIP compression enabled\n");
258 return GRZIP;
260 #endif
261 #if ARCHIVE_VERSION_NUMBER >= 3001900
262 else if (strcmp("LZ4", name) == 0) {
263 debug_print("LZ4 compression enabled\n");
264 return LZ4;
266 #endif
267 else if (strcmp("NONE", name) == 0) {
268 debug_print("Compression disabled\n");
269 return NO_COMPRESS;
272 btn = g_slist_next(btn);
274 return NO_COMPRESS;
277 static ARCHIVE_FORMAT get_archive_format(GSList* btn) {
278 const gchar* name;
280 while (btn) {
281 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn->data))) {
282 name = gtk_widget_get_name(GTK_WIDGET(btn->data));
283 if (strcmp("TAR", name) == 0) {
284 debug_print("TAR archive enabled\n");
285 return TAR;
287 else if (strcmp("SHAR", name) == 0) {
288 debug_print("SHAR archive enabled\n");
289 return SHAR;
291 else if (strcmp("PAX", name) == 0) {
292 debug_print("PAX archive enabled\n");
293 return PAX;
295 else if (strcmp("CPIO", name) == 0) {
296 debug_print("CPIO archive enabled\n");
297 return CPIO;
300 btn = g_slist_next(btn);
302 return NO_FORMAT;
305 static void create_md5sum(const gchar* file, const gchar* md5_file) {
306 int fd;
307 gchar* text = NULL;
308 gchar* md5sum = malloc(33);
310 debug_print("Creating md5sum file: %s\n", md5_file);
311 if (md5_hex_digest_file(md5sum, (const unsigned char *) file) == -1) {
312 free(md5sum);
313 return;
315 debug_print("md5sum: %s\n", md5sum);
316 if ((fd =
317 open(md5_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
318 FILE_OP_ERROR(md5_file, "create");
319 free(md5sum);
320 return;
322 text = g_strrstr_len(file, strlen(file), "/");
323 if (text) {
324 text++;
325 text = g_strdup_printf("%s %s\n", md5sum, text);
327 else
328 text = g_strdup_printf("%s %s\n", md5sum, file);
329 g_free(md5sum);
330 debug_print("md5sum: %s\n", text);
331 if (write(fd, text, strlen(text)) < 0)
332 FILE_OP_ERROR(md5_file, "write");
333 close(fd);
334 g_free(text);
337 static gchar* descriptive_file_name(
338 struct ArchivePage* page, const gchar* file, MsgInfo *msginfo) {
339 gchar* new_file = NULL;
340 gchar *name, *p, *to, *from, *date, *subject;
342 debug_print("renaming file\n");
343 p = g_strrstr_len(file, strlen(file), "/");
344 p = g_strndup(file, p - file);
345 if (!p)
346 return NULL;
347 if (msginfo->to) {
348 to = g_strdup(msginfo->to);
349 extract_address(to);
351 else
352 to = g_strdup("");
353 if (msginfo->from) {
354 from = g_strdup(msginfo->from);
355 extract_address(from);
357 else
358 from = g_strdup("");
359 if (msginfo->date) {
360 date = g_strdup(msginfo->date);
361 subst_for_shellsafe_filename(date);
362 /* if not on windows we need to subst some more */
363 subst_chars(date, ":", '_');
365 else
366 date = g_strdup("");
367 if (msginfo->subject) {
368 subject = g_strdup(msginfo->subject);
369 subst_for_shellsafe_filename(subject);
370 /* if not on windows we need to subst some more */
371 subst_chars(subject, ":", '_');
373 else
374 subject = g_strdup("");
375 name = g_strdup_printf("%s_%s@%s@%s", date, from, to, subject);
376 /* ensure file name is not larger than 96 chars (max file name size
377 * is 100 chars but reserve for .md5)
379 if (strlen(name) > 96)
380 name[96] = 0;
382 new_file = g_strconcat(p, "/", name, NULL);
384 g_free(name);
385 g_free(p);
386 g_free(to);
387 g_free(from);
388 g_free(date);
389 g_free(subject);
391 debug_print("New_file: %s\n", new_file);
392 if (link(file, new_file) != 0) {
393 if (errno != EEXIST) {
394 FILE_OP_ERROR(new_file, "link");
395 g_free(new_file);
396 new_file = g_strdup(file);
397 page->rename = FALSE;
401 return new_file;
404 static void walk_folder(struct ArchivePage* page, FolderItem* item,
405 gboolean recursive) {
406 FolderItem* child;
407 GSList *msglist;
408 GSList *cur;
409 MsgInfo *msginfo;
410 GNode* node;
411 int count;
412 gchar* md5_file = NULL;
413 gchar* text = NULL;
414 gchar* file = NULL;
415 MsgTrash* msg_trash = NULL;
416 const gchar* date = NULL;
418 if (recursive && ! page->cancelled) {
419 debug_print("Scanning recursive\n");
420 node = item->node->children;
421 while(node && ! page->cancelled) {
422 debug_print("Number of nodes: %d\n", g_node_n_children(node));
423 if (node->data) {
424 child = FOLDER_ITEM(node->data);
425 debug_print("new node: %d messages\n", child->total_msgs);
426 walk_folder(page, child, recursive);
428 node = node->next;
431 if (! page->cancelled) {
432 date = gtk_entry_get_text(GTK_ENTRY(page->isoDate));
433 debug_print("cut-off date: %s\n", date);
434 count = 0;
435 page->files += item->total_msgs;
436 msglist = folder_item_get_msg_list(item);
437 msg_trash = new_msg_trash(item);
438 for (cur = msglist; cur && ! page->cancelled; cur = cur->next) {
439 msginfo = (MsgInfo *) cur->data;
440 debug_print("%s_%s_%s_%s\n",
441 msginfo->date, msginfo->to, msginfo->from, msginfo->subject);
442 file = folder_item_fetch_msg(item, msginfo->msgnum);
443 if (date && strlen(date) > 0 && !before_date(msginfo->date_t, date)) {
444 page->files--;
445 continue;
447 page->total_size += msginfo->size;
448 /*debug_print("Processing: %s\n", file);*/
449 if (file) {
450 if (page->unlink) {
451 archive_add_msg_mark(msg_trash, msginfo);
453 if (page->rename) {
454 file = descriptive_file_name(page, file, msginfo);
455 if (!file) {
456 /* Could not create a descriptive name */
457 file = folder_item_fetch_msg(item, msginfo->msgnum);
460 if (page->md5) {
461 md5_file = g_strdup_printf("%s.md5", file);
462 create_md5sum(file, md5_file);
463 archive_add_file(md5_file);
464 g_free(md5_file);
466 archive_add_file(file);
467 if (page->rename)
468 g_free(file);
470 if (count % 350 == 0) {
471 debug_print("pulse progressbar\n");
472 text = g_strdup_printf(
473 "Scanning %s: %d files", item->name, count);
474 gtk_progress_bar_set_text(
475 GTK_PROGRESS_BAR(progress->progress), text);
476 g_free(text);
477 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress->progress));
478 GTK_EVENTS_FLUSH();
480 count++;
482 procmsg_msg_list_free(msglist);
486 static AFileTest file_is_writeable(struct ArchivePage* page) {
487 int fd;
489 if (g_file_test(page->name, G_FILE_TEST_EXISTS) &&
490 ! page->force_overwrite)
491 return A_FILE_EXISTS;
492 if (g_file_test(page->name, G_FILE_TEST_IS_SYMLINK))
493 return A_FILE_IS_LINK;
494 if (g_file_test(page->name, G_FILE_TEST_IS_DIR))
495 return A_FILE_IS_DIR;
496 if ((fd = open(page->name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) {
497 switch (errno) {
498 case EACCES: return A_FILE_NO_WRITE;
499 case EEXIST: return A_FILE_OK;
500 default: return A_FILE_UNKNOWN;
503 else {
504 close(fd);
505 claws_unlink(page->name);
507 return A_FILE_OK;
510 static gboolean archiver_save_files(struct ArchivePage* page) {
511 FolderItem* item;
512 COMPRESS_METHOD method;
513 ARCHIVE_FORMAT format;
514 gboolean recursive;
515 guint orig_file;
516 GSList* list = NULL;
517 const gchar* res = NULL;
518 AFileTest perm;
519 gchar* msg = NULL;
520 gboolean folder_not_set;
521 gboolean file_not_set;
523 /* check if folder to archive and target archive filename are set */
524 folder_not_set = (*gtk_entry_get_text(GTK_ENTRY(page->folder)) == '\0');
525 file_not_set = (*gtk_entry_get_text(GTK_ENTRY(page->file)) == '\0');
526 if (folder_not_set || file_not_set) {
527 alertpanel_error(_("Some uninitialized data prevents from starting\n"
528 "the archiving process:\n"
529 "%s%s"),
530 folder_not_set ? _("\n- the folder to archive is not set") : "",
531 file_not_set ? _("\n- the name for archive is not set") : "");
532 return FALSE;
534 /* sync page struct info with folder and archive name edit widgets */
535 if (page->path) {
536 g_free(page->path);
537 page->path = NULL;
539 page->path = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->folder)));
540 g_strstrip(page->path);
541 debug_print("page->path: %s\n", page->path);
543 if (page->name) {
544 g_free(page->name);
545 page->name = NULL;
547 page->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->file)));
548 g_strstrip(page->name);
549 debug_print("page->name: %s\n", page->name);
551 if ((perm = file_is_writeable(page)) != A_FILE_OK) {
552 switch (perm) {
553 case A_FILE_EXISTS:
554 msg = g_strdup_printf(_("%s: Exists. Continue anyway?"), page->name);
555 break;
556 case A_FILE_IS_LINK:
557 msg = g_strdup_printf(_("%s: Is a link. Cannot continue"), page->name);
558 break;
559 case A_FILE_IS_DIR:
560 msg = g_strdup_printf(_("%s: Is a directory. Cannot continue"), page->name);
561 break;
562 case A_FILE_NO_WRITE:
563 msg = g_strdup_printf(_("%s: Missing permissions. Cannot continue"), page->name);
564 break;
565 case A_FILE_UNKNOWN:
566 msg = g_strdup_printf(_("%s: Unknown error. Cannot continue"), page->name);
567 break;
568 default:
569 break;
571 if (perm == A_FILE_EXISTS) {
572 AlertValue aval;
574 aval = alertpanel_full(_("Creating archive"), msg,
575 NULL, _("_Cancel"), NULL, _("_OK"), NULL, NULL,
576 ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING);
577 g_free(msg);
578 if (aval != G_ALERTALTERNATE)
579 return FALSE;
580 } else {
581 alertpanel_error("%s", msg);
582 g_free(msg);
583 return FALSE;
586 if (! valid_file_name(page->name)) {
587 alertpanel_error(_("Not a valid file name:\n%s."), page->name);
588 return FALSE;
590 item = folder_find_item_from_identifier(page->path);
591 if (! item) {
592 alertpanel_error(_("Not a valid Claws Mail folder:\n%s."), page->name);
593 return FALSE;
595 page->files = 0;
596 page->total_size = 0;
597 page->rename = gtk_toggle_button_get_active(
598 GTK_TOGGLE_BUTTON(page->rename_files));
599 recursive = gtk_toggle_button_get_active(
600 GTK_TOGGLE_BUTTON(page->recursive));
601 page->md5 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->md5sum));
602 page->unlink = gtk_toggle_button_get_active(
603 GTK_TOGGLE_BUTTON(page->unlink_files));
604 create_progress_dialog(page);
605 walk_folder(page, item, recursive);
606 if (page->cancelled)
607 return FALSE;
608 list = archive_get_file_list();
609 orig_file = (page->md5) ? page->files * 2 : page->files;
610 debug_print("md5: %d, orig: %d, md5: %d\n",
611 page->md5, page->files, orig_file);
612 if (orig_file != g_slist_length(list)) {
613 AlertValue aval;
615 msg = g_strdup_printf(
616 _("Adding files in folder failed\n"
617 "Files in folder: %d\n"
618 "Files in list: %d\n"
619 "\nContinue anyway?"),
620 orig_file, g_slist_length(list));
621 aval = alertpanel_full(_("Creating archive"), msg,
622 NULL, _("_Cancel"), NULL, _("_OK"), NULL, NULL,
623 ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING);
624 g_free(msg);
625 if (aval != G_ALERTALTERNATE) {
626 archive_free_file_list(page->md5, page->rename);
627 return FALSE;
630 method = get_compress_method(page->compress_methods);
631 format = get_archive_format(page->archive_formats);
632 if ((res = archive_create(page->name, list, method, format)) != NULL) {
633 alertpanel_error(_("Archive creation error:\n%s"), res);
634 archive_free_file_list(page->md5, page->rename);
635 return FALSE;
637 if (page->unlink) {
638 archive_free_archived_files();
640 return TRUE;
643 static void entry_change_cb(GtkWidget* widget, gpointer data) {
644 const gchar* name = gtk_widget_get_name(widget);
645 struct ArchivePage* page = (struct ArchivePage *) data;
647 if (strcmp("folder", name) == 0) {
648 page->path = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
649 debug_print("page->folder = %s\n", page->path);
651 else if (strcmp("file", name) == 0) {
652 page->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
653 page->force_overwrite = FALSE;
654 debug_print("page->name = %s\n", page->name);
658 static void show_result(struct ArchivePage* page) {
660 enum {
661 STRING1,
662 STRING2,
663 N_COLUMNS
666 GStatBuf st;
667 GtkListStore* list;
668 GtkTreeIter iter;
669 GtkTreeView* view;
670 GtkTreeViewColumn* header;
671 GtkCellRenderer* renderer;
672 GtkWidget* dialog;
673 GtkWidget* content_area;
674 gchar* msg = NULL;
675 gchar* method = NULL;
676 gchar* format = NULL;
678 MainWindow* mainwin = mainwindow_get_mainwindow();
680 switch (get_compress_method(page->compress_methods)) {
681 case GZIP:
682 method = g_strdup("GZIP");
683 break;
684 case BZIP2:
685 method = g_strdup("BZIP2");
686 break;
687 case COMPRESS:
688 method = g_strdup("Compress");
689 break;
690 #if ARCHIVE_VERSION_NUMBER >= 2006990
691 case LZMA:
692 method = g_strdup("LZMA");
693 break;
694 case XZ:
695 method = g_strdup("XZ");
696 break;
697 #endif
698 #if ARCHIVE_VERSION_NUMBER >= 3000000
699 case LZIP:
700 method = g_strdup("LZIP");
701 break;
702 #endif
703 #if ARCHIVE_VERSION_NUMBER >= 3001000
704 case LRZIP:
705 method = g_strdup("LRZIP");
706 break;
707 case LZOP:
708 method = g_strdup("LZOP");
709 break;
710 case GRZIP:
711 method = g_strdup("GRZIP");
712 break;
713 #endif
714 #if ARCHIVE_VERSION_NUMBER >= 3001900
715 case LZ4:
716 method = g_strdup("LZ4");
717 break;
718 #endif
719 case NO_COMPRESS:
720 method = g_strdup("No Compression");
721 break;
724 switch (get_archive_format(page->archive_formats)) {
725 case TAR:
726 format = g_strdup("TAR");
727 break;
728 case SHAR:
729 format = g_strdup("SHAR");
730 break;
731 case PAX:
732 format = g_strdup("PAX");
733 break;
734 case CPIO:
735 format = g_strdup("CPIO");
736 break;
737 case NO_FORMAT:
738 format = g_strdup("NO FORMAT");
741 if (g_stat(page->name, &st) == -1) {
742 alertpanel_error("Could not get size of archive file '%s'.", page->name);
743 return;
745 dialog = gtk_dialog_new_with_buttons(
746 _("Archive result"),
747 GTK_WINDOW(mainwin->window),
748 GTK_DIALOG_DESTROY_WITH_PARENT,
749 _("_OK"),
750 GTK_RESPONSE_NONE,
751 NULL);
752 g_signal_connect_swapped(
753 dialog,
754 "response",
755 G_CALLBACK(gtk_widget_destroy),
756 dialog);
758 list = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
760 view = g_object_new(
761 GTK_TYPE_TREE_VIEW,
762 "model", list,
763 "rules-hint", FALSE,
764 "headers-clickable", FALSE,
765 "reorderable", FALSE,
766 "enable-search", FALSE,
767 NULL);
769 renderer = gtk_cell_renderer_text_new();
771 header = gtk_tree_view_column_new_with_attributes(
772 _("Attributes"), renderer, "text", STRING1, NULL);
773 gtk_tree_view_append_column(view, header);
775 header = gtk_tree_view_column_new_with_attributes(
776 _("Values"), renderer, "text", STRING2, NULL);
777 gtk_tree_view_append_column(view, header);
779 content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
780 gtk_container_add(
781 GTK_CONTAINER(content_area), GTK_WIDGET(view));
783 gtk_list_store_append(list, &iter);
784 gtk_list_store_set(
785 list, &iter,
786 STRING1, _("Archive"),
787 STRING2, page->name, -1);
789 gtk_list_store_append(list, &iter);
790 gtk_list_store_set(
791 list, &iter,
792 STRING1, _("Archive format"),
793 STRING2, format, -1);
794 g_free(format);
796 gtk_list_store_append(list, &iter);
797 gtk_list_store_set(
798 list, &iter,
799 STRING1, _("Compression method"),
800 STRING2, method, -1);
801 g_free(method);
803 gtk_list_store_append(list, &iter);
804 msg = g_strdup_printf("%d", (page->md5) ? page->files * 2 : page->files);
805 gtk_list_store_set(
806 list, &iter,
807 STRING1, _("Number of files"),
808 STRING2, msg, -1);
809 g_free(msg);
811 gtk_list_store_append(list, &iter);
812 msg = g_strdup_printf("%d byte(s)", (guint) st.st_size);
813 gtk_list_store_set(
814 list, &iter,
815 STRING1, _("Archive Size"),
816 STRING2, msg, -1);
817 g_free(msg);
819 gtk_list_store_append(list, &iter);
820 msg = g_strdup_printf("%d byte(s)", page->total_size);
821 gtk_list_store_set(
822 list, &iter,
823 STRING1, _("Folder Size"),
824 STRING2, msg, -1);
825 g_free(msg);
827 gtk_list_store_append(list, &iter);
828 msg = g_strdup_printf("%d%%",
829 (guint)((st.st_size * 100) / page->total_size));
830 gtk_list_store_set(
831 list, &iter,
832 STRING1, _("Compression level"),
833 STRING2, msg, -1);
834 g_free(msg);
836 gtk_list_store_append(list, &iter);
837 msg = g_strdup_printf("%s", (page->md5) ? _("Yes") : _("No"));
838 gtk_list_store_set(
839 list, &iter,
840 STRING1, _("MD5 checksum"),
841 STRING2, msg, -1);
842 g_free(msg);
844 gtk_list_store_append(list, &iter);
845 msg = g_strdup_printf("%s", (page->rename) ? _("Yes") : _("No"));
846 gtk_list_store_set(
847 list, &iter,
848 STRING1, _("Descriptive names"),
849 STRING2, msg, -1);
850 g_free(msg);
852 gtk_list_store_append(list, &iter);
853 msg = g_strdup_printf("%s", (page->unlink) ? _("Yes") : _("No"));
854 gtk_list_store_set(
855 list, &iter,
856 STRING1, _("Delete selected files"),
857 STRING2, msg, -1);
858 g_free(msg);
860 msg = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->isoDate)));
861 if (msg) {
862 gtk_list_store_append(list, &iter);
863 gtk_list_store_set(
864 list, &iter,
865 STRING1, _("Select mails before"),
866 STRING2, msg, -1);
868 g_free(msg);
870 gtk_window_set_default_size(GTK_WINDOW(dialog), 320, 260);
872 gtk_widget_show_all(dialog);
875 static void archiver_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
876 struct ArchivePage* page = (struct ArchivePage *) data;
877 gboolean result = FALSE;
879 switch (action) {
880 case GTK_RESPONSE_ACCEPT:
881 debug_print("User chose OK\n");
882 page->response = TRUE;
883 break;
884 default:
885 debug_print("User chose CANCEL\n");
886 page->response = FALSE;
887 archiver_gtk_done(page, widget);
888 return;
890 debug_print("Settings:\naction: %d\n", page->response);
891 if (page->response) {
892 debug_print("Settings:\nfolder: %s\nname: %s\n",
893 (page->path) ? page->path : "(null)",
894 (page->name) ? page->name : "(null)");
895 result = archiver_save_files(page);
896 debug_print("Result->archiver_save_files: %d\n", result);
897 if (progress->progress_dialog &&
898 GTK_IS_WIDGET(progress->progress_dialog))
899 gtk_widget_destroy(progress->progress_dialog);
900 if (result && ! page->cancelled) {
901 show_result(page);
902 archive_free_file_list(page->md5, page->rename);
903 archiver_gtk_done(page, widget);
904 return;
906 if (page->cancelled) {
907 archiver_gtk_done(page, widget);
908 archiver_gtk_show();
913 static void foldersel_cb(GtkWidget *widget, gpointer data)
915 FolderItem *item;
916 gchar *item_id;
917 gint newpos = 0;
918 struct ArchivePage* page = (struct ArchivePage *) data;
920 item = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, FALSE,
921 _("Select folder to archive"));
922 if (item && (item_id = folder_item_get_identifier(item)) != NULL) {
923 gtk_editable_delete_text(GTK_EDITABLE(page->folder), 0, -1);
924 gtk_editable_insert_text(GTK_EDITABLE(page->folder),
925 item_id, strlen(item_id), &newpos);
926 page->path = g_strdup(item_id);
927 g_free(item_id);
929 debug_print("Folder to archive: %s\n",
930 gtk_entry_get_text(GTK_ENTRY(page->folder)));
933 static void filesel_cb(GtkWidget *widget, gpointer data)
935 GtkFileChooserNative *dialog;
936 gchar* file;
937 gint newpos = 0;
938 struct ArchivePage* page = (struct ArchivePage *) data;
940 dialog = gtk_file_chooser_native_new(
941 _("Select file name for archive [suffix should reflect archive like .tgz]"),
942 NULL,
943 GTK_FILE_CHOOSER_ACTION_SAVE,
944 _("_Apply"),
945 _("_Cancel"));
947 if (archiver_prefs.save_folder)
948 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
949 archiver_prefs.save_folder);
950 else
951 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
952 get_home_dir());
953 if (gtk_native_dialog_run (GTK_NATIVE_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
954 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
955 if (file) {
956 gtk_editable_delete_text(GTK_EDITABLE(page->file), 0, -1);
957 gtk_editable_insert_text(GTK_EDITABLE(page->file),
958 file, strlen(file), &newpos);
959 page->name = g_strdup(file);
960 g_free(file);
961 page->force_overwrite = TRUE;
964 g_object_unref(dialog);
965 debug_print("Name for archive: %s\n",
966 gtk_entry_get_text(GTK_ENTRY(page->file)));
969 void set_progress_file_label(const gchar* file) {
970 debug_print("IsLabel: %s, Update label: %s\n",
971 GTK_IS_WIDGET(progress->file_label)? "Yes" : "No", file);
972 if (GTK_IS_WIDGET(progress->file_label))
973 gtk_label_set_text(GTK_LABEL(progress->file_label), file);
976 void set_progress_print_all(guint fraction, guint total, guint step) {
977 gchar* text_count;
979 if (GTK_IS_WIDGET(progress->progress)) {
980 if ((fraction - progress->position) % step == 0) {
981 debug_print("frac: %d, total: %d, step: %d, prog->pos: %d\n",
982 fraction, total, step, progress->position);
983 gtk_progress_bar_set_fraction(
984 GTK_PROGRESS_BAR(progress->progress),
985 (total == 0) ? 0 : (gfloat)fraction / (gfloat)total);
986 text_count = g_strdup_printf(_("%ld of %ld"),
987 (long) fraction, (long) total);
988 gtk_progress_bar_set_text(
989 GTK_PROGRESS_BAR(progress->progress), text_count);
990 g_free(text_count);
991 progress->position = fraction;
992 GTK_EVENTS_FLUSH();
997 void archiver_gtk_show() {
998 GtkWidget* dialog;
999 GtkWidget* frame;
1000 GtkWidget* vbox1;
1001 GtkWidget* hbox1;
1002 GtkWidget* folder_label;
1003 GtkWidget* folder_select;
1004 GtkWidget* file_label;
1005 GtkWidget* file_select;
1006 GtkWidget* gzip_radio_btn;
1007 GtkWidget* bzip_radio_btn;
1008 GtkWidget* compress_radio_btn;
1009 #if ARCHIVE_VERSION_NUMBER >= 2006990
1010 GtkWidget* lzma_radio_btn;
1011 GtkWidget* xz_radio_btn;
1012 #endif
1013 #if ARCHIVE_VERSION_NUMBER >= 3000000
1014 GtkWidget* lzip_radio_btn;
1015 #endif
1016 #if ARCHIVE_VERSION_NUMBER >= 3001000
1017 GtkWidget* lrzip_radio_btn;
1018 GtkWidget* lzop_radio_btn;
1019 GtkWidget* grzip_radio_btn;
1020 #endif
1021 #if ARCHIVE_VERSION_NUMBER >= 3001900
1022 GtkWidget* lz4_radio_btn;
1023 #endif
1024 GtkWidget* no_radio_btn;
1025 GtkWidget* shar_radio_btn;
1026 GtkWidget* pax_radio_btn;
1027 GtkWidget* cpio_radio_btn;
1028 GtkWidget* tar_radio_btn;
1029 GtkWidget* content_area;
1030 struct ArchivePage* page;
1031 MainWindow* mainwin = mainwindow_get_mainwindow();
1033 /*debug_set_mode(TRUE);*/
1034 progress = init_progress();
1036 page = init_archive_page();
1038 dialog = gtk_dialog_new_with_buttons (
1039 _("Create Archive"),
1040 GTK_WINDOW(mainwin->window),
1041 GTK_DIALOG_DESTROY_WITH_PARENT,
1042 _("_Cancel"),
1043 GTK_RESPONSE_CANCEL,
1044 _("_OK"),
1045 GTK_RESPONSE_ACCEPT,
1046 NULL);
1048 g_signal_connect (
1049 dialog,
1050 "response",
1051 G_CALLBACK(archiver_dialog_cb),
1052 page);
1054 frame = gtk_frame_new(_("Enter Archiver arguments"));
1055 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1056 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1057 content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1058 gtk_container_add(GTK_CONTAINER(content_area), frame);
1060 vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
1061 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 4);
1062 gtk_container_add(GTK_CONTAINER(frame), vbox1);
1064 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1065 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1066 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1068 folder_label = gtk_label_new(_("Folder to archive"));
1069 gtk_box_pack_start(GTK_BOX(hbox1), folder_label, FALSE, FALSE, 0);
1071 page->folder = gtk_entry_new();
1072 gtk_widget_set_name(page->folder, "folder");
1073 gtk_box_pack_start(GTK_BOX(hbox1), page->folder, TRUE, TRUE, 0);
1074 CLAWS_SET_TIP(page->folder,
1075 _("Folder which is the root of the archive"));
1077 folder_select = gtkut_get_browse_directory_btn(_("_Browse"));
1078 gtk_box_pack_start(GTK_BOX(hbox1), folder_select, FALSE, FALSE, 0);
1079 CLAWS_SET_TIP(folder_select,
1080 _("Click this button to select a folder which is to be root of the archive"));
1082 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1083 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1084 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1086 file_label = gtk_label_new(_("Name for archive"));
1087 gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1089 page->file = gtk_entry_new();
1090 gtk_widget_set_name(page->file, "file");
1091 gtk_box_pack_start(GTK_BOX(hbox1), page->file, TRUE, TRUE, 0);
1092 CLAWS_SET_TIP(page->file, _("Archive location and name"));
1094 file_select = gtkut_get_browse_directory_btn(_("_Select"));
1095 gtk_box_pack_start(GTK_BOX(hbox1), file_select, FALSE, FALSE, 0);
1096 CLAWS_SET_TIP(file_select,
1097 _("Click this button to select a name and location for the archive"));
1099 frame = gtk_frame_new(_("Choose compression"));
1100 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1101 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1102 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1104 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1105 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1106 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1108 gzip_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "G_ZIP");
1109 gtk_widget_set_name(gzip_radio_btn, "GZIP");
1110 gtk_box_pack_start(GTK_BOX(hbox1), gzip_radio_btn, FALSE, FALSE, 0);
1111 archiver_set_tooltip(gzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GZIP"));
1113 bzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1114 GTK_RADIO_BUTTON(gzip_radio_btn), "BZIP_2");
1115 gtk_widget_set_name(bzip_radio_btn, "BZIP");
1116 gtk_box_pack_start(GTK_BOX(hbox1), bzip_radio_btn, FALSE, FALSE, 0);
1117 archiver_set_tooltip(bzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "BZIP2"));
1119 compress_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1120 GTK_RADIO_BUTTON(gzip_radio_btn), "Com_press");
1121 gtk_widget_set_name(compress_radio_btn, "COMPRESS");
1122 gtk_box_pack_start(GTK_BOX(hbox1), compress_radio_btn, FALSE, FALSE, 0);
1123 archiver_set_tooltip(compress_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "COMPRESS"));
1125 #if ARCHIVE_VERSION_NUMBER >= 2006990
1126 lzma_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1127 GTK_RADIO_BUTTON(gzip_radio_btn), "_LZMA");
1128 gtk_widget_set_name(lzma_radio_btn, "LZMA");
1129 gtk_box_pack_start(GTK_BOX(hbox1), lzma_radio_btn, FALSE, FALSE, 0);
1130 archiver_set_tooltip(lzma_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZMA"));
1132 xz_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1133 GTK_RADIO_BUTTON(gzip_radio_btn), "_XZ");
1134 gtk_widget_set_name(xz_radio_btn, "XZ");
1135 gtk_box_pack_start(GTK_BOX(hbox1), xz_radio_btn, FALSE, FALSE, 0);
1136 archiver_set_tooltip(xz_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "XZ"));
1137 #endif
1139 #if ARCHIVE_VERSION_NUMBER >= 3000000
1140 lzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1141 GTK_RADIO_BUTTON(gzip_radio_btn), "_LZIP");
1142 gtk_widget_set_name(lzip_radio_btn, "LZIP");
1143 gtk_box_pack_start(GTK_BOX(hbox1), lzip_radio_btn, FALSE, FALSE, 0);
1144 archiver_set_tooltip(lzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZIP"));
1145 #endif
1147 #if ARCHIVE_VERSION_NUMBER >= 3001000
1148 lrzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1149 GTK_RADIO_BUTTON(gzip_radio_btn), "L_RZIP");
1150 gtk_widget_set_name(lrzip_radio_btn, "LRZIP");
1151 gtk_box_pack_start(GTK_BOX(hbox1), lrzip_radio_btn, FALSE, FALSE, 0);
1152 archiver_set_tooltip(lrzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LRZIP"));
1154 lzop_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1155 GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_OP");
1156 gtk_widget_set_name(lzop_radio_btn, "LZOP");
1157 gtk_box_pack_start(GTK_BOX(hbox1), lzop_radio_btn, FALSE, FALSE, 0);
1158 archiver_set_tooltip(lzop_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZOP"));
1160 grzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1161 GTK_RADIO_BUTTON(gzip_radio_btn), "_GRZIP");
1162 gtk_widget_set_name(grzip_radio_btn, "GRZIP");
1163 gtk_box_pack_start(GTK_BOX(hbox1), grzip_radio_btn, FALSE, FALSE, 0);
1164 archiver_set_tooltip(grzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GRZIP"));
1165 #endif
1167 #if ARCHIVE_VERSION_NUMBER >= 3001900
1168 lz4_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1169 GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_4");
1170 gtk_widget_set_name(lz4_radio_btn, "LZ4");
1171 gtk_box_pack_start(GTK_BOX(hbox1), lz4_radio_btn, FALSE, FALSE, 0);
1172 archiver_set_tooltip(lz4_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZ4"));
1173 #endif
1175 no_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1176 GTK_RADIO_BUTTON(gzip_radio_btn), _("_None"));
1177 gtk_widget_set_name(no_radio_btn, "NONE");
1178 gtk_box_pack_start(GTK_BOX(hbox1), no_radio_btn, FALSE, FALSE, 0);
1179 archiver_set_tooltip(no_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "NO"));
1181 page->compress_methods =
1182 gtk_radio_button_get_group(GTK_RADIO_BUTTON(gzip_radio_btn));
1184 switch (archiver_prefs.compression) {
1185 case COMPRESSION_GZIP:
1186 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gzip_radio_btn), TRUE);
1187 break;
1188 case COMPRESSION_BZIP:
1189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bzip_radio_btn), TRUE);
1190 break;
1191 case COMPRESSION_COMPRESS:
1192 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compress_radio_btn), TRUE);
1193 break;
1194 #if ARCHIVE_VERSION_NUMBER >= 2006990
1195 case COMPRESSION_LZMA:
1196 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzma_radio_btn), TRUE);
1197 break;
1198 case COMPRESSION_XZ:
1199 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xz_radio_btn), TRUE);
1200 break;
1201 #endif
1202 #if ARCHIVE_VERSION_NUMBER >= 3000000
1203 case COMPRESSION_LZIP:
1204 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzip_radio_btn), TRUE);
1205 break;
1206 #endif
1207 #if ARCHIVE_VERSION_NUMBER >= 3001000
1208 case COMPRESSION_LRZIP:
1209 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lrzip_radio_btn), TRUE);
1210 break;
1211 case COMPRESSION_LZOP:
1212 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzop_radio_btn), TRUE);
1213 break;
1214 case COMPRESSION_GRZIP:
1215 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grzip_radio_btn), TRUE);
1216 break;
1217 #endif
1218 #if ARCHIVE_VERSION_NUMBER >= 3001900
1219 case COMPRESSION_LZ4:
1220 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lz4_radio_btn), TRUE);
1221 break;
1222 #endif
1223 case COMPRESSION_NONE:
1224 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(no_radio_btn), TRUE);
1225 break;
1228 frame = gtk_frame_new(_("Choose format"));
1229 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1230 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1231 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1233 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1234 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1235 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1237 tar_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "_TAR");
1238 gtk_widget_set_name(tar_radio_btn, "TAR");
1239 gtk_box_pack_start(GTK_BOX(hbox1), tar_radio_btn, FALSE, FALSE, 0);
1240 archiver_set_tooltip(tar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "TAR"));
1242 shar_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1243 GTK_RADIO_BUTTON(tar_radio_btn), "S_HAR");
1244 gtk_widget_set_name(shar_radio_btn, "SHAR");
1245 gtk_box_pack_start(GTK_BOX(hbox1), shar_radio_btn, FALSE, FALSE, 0);
1246 archiver_set_tooltip(shar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "SHAR"));
1248 cpio_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1249 GTK_RADIO_BUTTON(tar_radio_btn), "CP_IO");
1250 gtk_widget_set_name(cpio_radio_btn, "CPIO");
1251 gtk_box_pack_start(GTK_BOX(hbox1), cpio_radio_btn, FALSE, FALSE, 0);
1252 archiver_set_tooltip(cpio_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "CPIO"));
1254 pax_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1255 GTK_RADIO_BUTTON(tar_radio_btn), "PA_X");
1256 gtk_widget_set_name(pax_radio_btn, "PAX");
1257 gtk_box_pack_start(GTK_BOX(hbox1), pax_radio_btn, FALSE, FALSE, 0);
1258 archiver_set_tooltip(pax_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "PAX"));
1260 page->archive_formats =
1261 gtk_radio_button_get_group(GTK_RADIO_BUTTON(tar_radio_btn));
1263 switch (archiver_prefs.format) {
1264 case FORMAT_TAR:
1265 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tar_radio_btn), TRUE);
1266 break;
1267 case FORMAT_SHAR:
1268 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shar_radio_btn), TRUE);
1269 break;
1270 case FORMAT_CPIO:
1271 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cpio_radio_btn), TRUE);
1272 break;
1273 case FORMAT_PAX:
1274 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pax_radio_btn), TRUE);
1275 break;
1278 frame = gtk_frame_new(_("Miscellaneous options"));
1279 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1280 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1281 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1283 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1284 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1285 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1287 page->recursive = gtk_check_button_new_with_mnemonic(_("_Recursive"));
1288 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->recursive), archiver_prefs.recursive);
1289 gtk_box_pack_start(GTK_BOX(hbox1), page->recursive, FALSE, FALSE, 0);
1290 CLAWS_SET_TIP(page->recursive,
1291 _("Choose this option to include subfolders in the archive"));
1293 page->md5sum = gtk_check_button_new_with_mnemonic(_("_MD5sum"));
1294 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->md5sum), archiver_prefs.md5sum);
1295 gtk_box_pack_start(GTK_BOX(hbox1), page->md5sum, FALSE, FALSE, 0);
1296 CLAWS_SET_TIP(page->md5sum,
1297 _("Choose this option to add MD5 checksums for each file in the archive.\n"
1298 "Be aware though, that this dramatically increases the time it\n"
1299 "will take to create the archive"));
1301 page->rename_files = gtk_check_button_new_with_mnemonic(_("R_ename"));
1302 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->rename_files), archiver_prefs.rename);
1303 gtk_box_pack_start(GTK_BOX(hbox1), page->rename_files, FALSE, FALSE, 0);
1304 CLAWS_SET_TIP(page->rename_files,
1305 _("Choose this option to use descriptive names for each file in the archive.\n"
1306 "The naming scheme: date_from@to@subject.\n"
1307 "Names will be truncated to max 96 characters"));
1309 page->unlink_files = gtk_check_button_new_with_mnemonic(_("_Delete"));
1310 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->unlink_files), archiver_prefs.unlink);
1311 gtk_box_pack_start(GTK_BOX(hbox1), page->unlink_files, FALSE, FALSE, 0);
1312 CLAWS_SET_TIP(page->unlink_files,
1313 _("Choose this option to delete mails after archiving\n"
1314 "At this point only handles IMAP4, Local mbox and POP3"));
1317 frame = gtk_frame_new(_("Selection options"));
1318 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1319 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1320 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1322 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1323 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1324 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1326 file_label = gtk_label_new(_("Select mails before"));
1327 gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1329 page->isoDate = gtk_entry_new();
1330 gtk_widget_set_name(page->isoDate, "isoDate");
1331 gtk_box_pack_start(GTK_BOX(hbox1), page->isoDate, TRUE, TRUE, 0);
1332 CLAWS_SET_TIP(page->isoDate,
1333 _("Select emails before a certain date\n"
1334 "Date must comply to ISO-8601 [YYYY-MM-DD]"));
1336 g_signal_connect(G_OBJECT(folder_select), "clicked",
1337 G_CALLBACK(foldersel_cb), page);
1338 g_signal_connect(G_OBJECT(file_select), "clicked",
1339 G_CALLBACK(filesel_cb), page);
1340 g_signal_connect(G_OBJECT(page->folder), "activate",
1341 G_CALLBACK(entry_change_cb), page);
1342 g_signal_connect(G_OBJECT(page->file), "activate",
1343 G_CALLBACK(entry_change_cb), page);
1345 gtk_widget_show_all(dialog);
1348 void archiver_gtk_done(struct ArchivePage* page, GtkWidget* widget) {
1349 dispose_archive_page(page);
1350 free(progress);
1351 gtk_widget_destroy(widget);
1352 /*debug_set_mode(FALSE);*/