Improve some sieve-related translations
[claws.git] / src / plugins / archive / archiver_gtk.c
blobb352634cceeb9d23d49b3179bf5ca699edbfe66c
1 /* vim: set textwidth=80 tabstop=4 */
3 /*
4 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
5 * Copyright (C) 1999-2022 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 GtkWidget *dialog;
936 gchar* file;
937 gint newpos = 0;
938 struct ArchivePage* page = (struct ArchivePage *) data;
940 dialog = gtk_file_chooser_dialog_new(
941 _("Select file name for archive [suffix should reflect archive like .tgz]"),
942 NULL,
943 GTK_FILE_CHOOSER_ACTION_SAVE,
944 _("_Cancel"), GTK_RESPONSE_CANCEL,
945 _("_Apply"), GTK_RESPONSE_APPLY,
946 NULL);
948 if (archiver_prefs.save_folder)
949 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
950 archiver_prefs.save_folder);
951 else
952 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
953 get_home_dir());
954 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_APPLY) {
955 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
956 if (file) {
957 gtk_editable_delete_text(GTK_EDITABLE(page->file), 0, -1);
958 gtk_editable_insert_text(GTK_EDITABLE(page->file),
959 file, strlen(file), &newpos);
960 page->name = g_strdup(file);
961 g_free(file);
962 page->force_overwrite = TRUE;
965 gtk_widget_destroy(dialog);
966 debug_print("Name for archive: %s\n",
967 gtk_entry_get_text(GTK_ENTRY(page->file)));
970 void set_progress_file_label(const gchar* file) {
971 debug_print("IsLabel: %s, Update label: %s\n",
972 GTK_IS_WIDGET(progress->file_label)? "Yes" : "No", file);
973 if (GTK_IS_WIDGET(progress->file_label))
974 gtk_label_set_text(GTK_LABEL(progress->file_label), file);
977 void set_progress_print_all(guint fraction, guint total, guint step) {
978 gchar* text_count;
980 if (GTK_IS_WIDGET(progress->progress)) {
981 if ((fraction - progress->position) % step == 0) {
982 debug_print("frac: %d, total: %d, step: %d, prog->pos: %d\n",
983 fraction, total, step, progress->position);
984 gtk_progress_bar_set_fraction(
985 GTK_PROGRESS_BAR(progress->progress),
986 (total == 0) ? 0 : (gfloat)fraction / (gfloat)total);
987 text_count = g_strdup_printf(_("%ld of %ld"),
988 (long) fraction, (long) total);
989 gtk_progress_bar_set_text(
990 GTK_PROGRESS_BAR(progress->progress), text_count);
991 g_free(text_count);
992 progress->position = fraction;
993 GTK_EVENTS_FLUSH();
998 void archiver_gtk_show() {
999 GtkWidget* dialog;
1000 GtkWidget* frame;
1001 GtkWidget* vbox1;
1002 GtkWidget* hbox1;
1003 GtkWidget* folder_label;
1004 GtkWidget* folder_select;
1005 GtkWidget* file_label;
1006 GtkWidget* file_select;
1007 GtkWidget* gzip_radio_btn;
1008 GtkWidget* bzip_radio_btn;
1009 GtkWidget* compress_radio_btn;
1010 #if ARCHIVE_VERSION_NUMBER >= 2006990
1011 GtkWidget* lzma_radio_btn;
1012 GtkWidget* xz_radio_btn;
1013 #endif
1014 #if ARCHIVE_VERSION_NUMBER >= 3000000
1015 GtkWidget* lzip_radio_btn;
1016 #endif
1017 #if ARCHIVE_VERSION_NUMBER >= 3001000
1018 GtkWidget* lrzip_radio_btn;
1019 GtkWidget* lzop_radio_btn;
1020 GtkWidget* grzip_radio_btn;
1021 #endif
1022 #if ARCHIVE_VERSION_NUMBER >= 3001900
1023 GtkWidget* lz4_radio_btn;
1024 #endif
1025 GtkWidget* no_radio_btn;
1026 GtkWidget* shar_radio_btn;
1027 GtkWidget* pax_radio_btn;
1028 GtkWidget* cpio_radio_btn;
1029 GtkWidget* tar_radio_btn;
1030 GtkWidget* content_area;
1031 struct ArchivePage* page;
1032 MainWindow* mainwin = mainwindow_get_mainwindow();
1034 /*debug_set_mode(TRUE);*/
1035 progress = init_progress();
1037 page = init_archive_page();
1039 dialog = gtk_dialog_new_with_buttons (
1040 _("Create Archive"),
1041 GTK_WINDOW(mainwin->window),
1042 GTK_DIALOG_DESTROY_WITH_PARENT,
1043 _("_Cancel"),
1044 GTK_RESPONSE_CANCEL,
1045 _("_OK"),
1046 GTK_RESPONSE_ACCEPT,
1047 NULL);
1049 g_signal_connect (
1050 dialog,
1051 "response",
1052 G_CALLBACK(archiver_dialog_cb),
1053 page);
1055 frame = gtk_frame_new(_("Enter Archiver arguments"));
1056 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1057 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1058 content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1059 gtk_container_add(GTK_CONTAINER(content_area), frame);
1061 vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
1062 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 4);
1063 gtk_container_add(GTK_CONTAINER(frame), vbox1);
1065 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1066 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1067 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1069 folder_label = gtk_label_new(_("Folder to archive"));
1070 gtk_box_pack_start(GTK_BOX(hbox1), folder_label, FALSE, FALSE, 0);
1072 page->folder = gtk_entry_new();
1073 gtk_widget_set_name(page->folder, "folder");
1074 gtk_box_pack_start(GTK_BOX(hbox1), page->folder, TRUE, TRUE, 0);
1075 CLAWS_SET_TIP(page->folder,
1076 _("Folder which is the root of the archive"));
1078 folder_select = gtkut_get_browse_directory_btn(_("_Browse"));
1079 gtk_box_pack_start(GTK_BOX(hbox1), folder_select, FALSE, FALSE, 0);
1080 CLAWS_SET_TIP(folder_select,
1081 _("Click this button to select a folder which is to be root of the archive"));
1083 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1084 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1085 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1087 file_label = gtk_label_new(_("Name for archive"));
1088 gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1090 page->file = gtk_entry_new();
1091 gtk_widget_set_name(page->file, "file");
1092 gtk_box_pack_start(GTK_BOX(hbox1), page->file, TRUE, TRUE, 0);
1093 CLAWS_SET_TIP(page->file, _("Archive location and name"));
1095 file_select = gtkut_get_browse_directory_btn(_("_Select"));
1096 gtk_box_pack_start(GTK_BOX(hbox1), file_select, FALSE, FALSE, 0);
1097 CLAWS_SET_TIP(file_select,
1098 _("Click this button to select a name and location for the archive"));
1100 frame = gtk_frame_new(_("Choose compression"));
1101 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1102 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1103 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1105 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1106 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1107 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1109 gzip_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "G_ZIP");
1110 gtk_widget_set_name(gzip_radio_btn, "GZIP");
1111 gtk_box_pack_start(GTK_BOX(hbox1), gzip_radio_btn, FALSE, FALSE, 0);
1112 archiver_set_tooltip(gzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GZIP"));
1114 bzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1115 GTK_RADIO_BUTTON(gzip_radio_btn), "BZIP_2");
1116 gtk_widget_set_name(bzip_radio_btn, "BZIP");
1117 gtk_box_pack_start(GTK_BOX(hbox1), bzip_radio_btn, FALSE, FALSE, 0);
1118 archiver_set_tooltip(bzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "BZIP2"));
1120 compress_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1121 GTK_RADIO_BUTTON(gzip_radio_btn), "Com_press");
1122 gtk_widget_set_name(compress_radio_btn, "COMPRESS");
1123 gtk_box_pack_start(GTK_BOX(hbox1), compress_radio_btn, FALSE, FALSE, 0);
1124 archiver_set_tooltip(compress_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "COMPRESS"));
1126 #if ARCHIVE_VERSION_NUMBER >= 2006990
1127 lzma_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1128 GTK_RADIO_BUTTON(gzip_radio_btn), "_LZMA");
1129 gtk_widget_set_name(lzma_radio_btn, "LZMA");
1130 gtk_box_pack_start(GTK_BOX(hbox1), lzma_radio_btn, FALSE, FALSE, 0);
1131 archiver_set_tooltip(lzma_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZMA"));
1133 xz_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1134 GTK_RADIO_BUTTON(gzip_radio_btn), "_XZ");
1135 gtk_widget_set_name(xz_radio_btn, "XZ");
1136 gtk_box_pack_start(GTK_BOX(hbox1), xz_radio_btn, FALSE, FALSE, 0);
1137 archiver_set_tooltip(xz_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "XZ"));
1138 #endif
1140 #if ARCHIVE_VERSION_NUMBER >= 3000000
1141 lzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1142 GTK_RADIO_BUTTON(gzip_radio_btn), "_LZIP");
1143 gtk_widget_set_name(lzip_radio_btn, "LZIP");
1144 gtk_box_pack_start(GTK_BOX(hbox1), lzip_radio_btn, FALSE, FALSE, 0);
1145 archiver_set_tooltip(lzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZIP"));
1146 #endif
1148 #if ARCHIVE_VERSION_NUMBER >= 3001000
1149 lrzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1150 GTK_RADIO_BUTTON(gzip_radio_btn), "L_RZIP");
1151 gtk_widget_set_name(lrzip_radio_btn, "LRZIP");
1152 gtk_box_pack_start(GTK_BOX(hbox1), lrzip_radio_btn, FALSE, FALSE, 0);
1153 archiver_set_tooltip(lrzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LRZIP"));
1155 lzop_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1156 GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_OP");
1157 gtk_widget_set_name(lzop_radio_btn, "LZOP");
1158 gtk_box_pack_start(GTK_BOX(hbox1), lzop_radio_btn, FALSE, FALSE, 0);
1159 archiver_set_tooltip(lzop_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZOP"));
1161 grzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1162 GTK_RADIO_BUTTON(gzip_radio_btn), "_GRZIP");
1163 gtk_widget_set_name(grzip_radio_btn, "GRZIP");
1164 gtk_box_pack_start(GTK_BOX(hbox1), grzip_radio_btn, FALSE, FALSE, 0);
1165 archiver_set_tooltip(grzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GRZIP"));
1166 #endif
1168 #if ARCHIVE_VERSION_NUMBER >= 3001900
1169 lz4_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1170 GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_4");
1171 gtk_widget_set_name(lz4_radio_btn, "LZ4");
1172 gtk_box_pack_start(GTK_BOX(hbox1), lz4_radio_btn, FALSE, FALSE, 0);
1173 archiver_set_tooltip(lz4_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZ4"));
1174 #endif
1176 no_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1177 GTK_RADIO_BUTTON(gzip_radio_btn), _("_None"));
1178 gtk_widget_set_name(no_radio_btn, "NONE");
1179 gtk_box_pack_start(GTK_BOX(hbox1), no_radio_btn, FALSE, FALSE, 0);
1180 archiver_set_tooltip(no_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "NO"));
1182 page->compress_methods =
1183 gtk_radio_button_get_group(GTK_RADIO_BUTTON(gzip_radio_btn));
1185 switch (archiver_prefs.compression) {
1186 case COMPRESSION_GZIP:
1187 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gzip_radio_btn), TRUE);
1188 break;
1189 case COMPRESSION_BZIP:
1190 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bzip_radio_btn), TRUE);
1191 break;
1192 case COMPRESSION_COMPRESS:
1193 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compress_radio_btn), TRUE);
1194 break;
1195 #if ARCHIVE_VERSION_NUMBER >= 2006990
1196 case COMPRESSION_LZMA:
1197 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzma_radio_btn), TRUE);
1198 break;
1199 case COMPRESSION_XZ:
1200 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xz_radio_btn), TRUE);
1201 break;
1202 #endif
1203 #if ARCHIVE_VERSION_NUMBER >= 3000000
1204 case COMPRESSION_LZIP:
1205 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzip_radio_btn), TRUE);
1206 break;
1207 #endif
1208 #if ARCHIVE_VERSION_NUMBER >= 3001000
1209 case COMPRESSION_LRZIP:
1210 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lrzip_radio_btn), TRUE);
1211 break;
1212 case COMPRESSION_LZOP:
1213 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzop_radio_btn), TRUE);
1214 break;
1215 case COMPRESSION_GRZIP:
1216 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grzip_radio_btn), TRUE);
1217 break;
1218 #endif
1219 #if ARCHIVE_VERSION_NUMBER >= 3001900
1220 case COMPRESSION_LZ4:
1221 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lz4_radio_btn), TRUE);
1222 break;
1223 #endif
1224 case COMPRESSION_NONE:
1225 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(no_radio_btn), TRUE);
1226 break;
1229 frame = gtk_frame_new(_("Choose format"));
1230 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1231 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1232 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1234 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1235 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1236 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1238 tar_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "_TAR");
1239 gtk_widget_set_name(tar_radio_btn, "TAR");
1240 gtk_box_pack_start(GTK_BOX(hbox1), tar_radio_btn, FALSE, FALSE, 0);
1241 archiver_set_tooltip(tar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "TAR"));
1243 shar_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1244 GTK_RADIO_BUTTON(tar_radio_btn), "S_HAR");
1245 gtk_widget_set_name(shar_radio_btn, "SHAR");
1246 gtk_box_pack_start(GTK_BOX(hbox1), shar_radio_btn, FALSE, FALSE, 0);
1247 archiver_set_tooltip(shar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "SHAR"));
1249 cpio_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1250 GTK_RADIO_BUTTON(tar_radio_btn), "CP_IO");
1251 gtk_widget_set_name(cpio_radio_btn, "CPIO");
1252 gtk_box_pack_start(GTK_BOX(hbox1), cpio_radio_btn, FALSE, FALSE, 0);
1253 archiver_set_tooltip(cpio_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "CPIO"));
1255 pax_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1256 GTK_RADIO_BUTTON(tar_radio_btn), "PA_X");
1257 gtk_widget_set_name(pax_radio_btn, "PAX");
1258 gtk_box_pack_start(GTK_BOX(hbox1), pax_radio_btn, FALSE, FALSE, 0);
1259 archiver_set_tooltip(pax_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "PAX"));
1261 page->archive_formats =
1262 gtk_radio_button_get_group(GTK_RADIO_BUTTON(tar_radio_btn));
1264 switch (archiver_prefs.format) {
1265 case FORMAT_TAR:
1266 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tar_radio_btn), TRUE);
1267 break;
1268 case FORMAT_SHAR:
1269 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shar_radio_btn), TRUE);
1270 break;
1271 case FORMAT_CPIO:
1272 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cpio_radio_btn), TRUE);
1273 break;
1274 case FORMAT_PAX:
1275 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pax_radio_btn), TRUE);
1276 break;
1279 frame = gtk_frame_new(_("Miscellaneous options"));
1280 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1281 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1282 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1284 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1285 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1286 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1288 page->recursive = gtk_check_button_new_with_mnemonic(_("_Recursive"));
1289 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->recursive), archiver_prefs.recursive);
1290 gtk_box_pack_start(GTK_BOX(hbox1), page->recursive, FALSE, FALSE, 0);
1291 CLAWS_SET_TIP(page->recursive,
1292 _("Choose this option to include subfolders in the archive"));
1294 page->md5sum = gtk_check_button_new_with_mnemonic(_("_MD5sum"));
1295 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->md5sum), archiver_prefs.md5sum);
1296 gtk_box_pack_start(GTK_BOX(hbox1), page->md5sum, FALSE, FALSE, 0);
1297 CLAWS_SET_TIP(page->md5sum,
1298 _("Choose this option to add MD5 checksums for each file in the archive.\n"
1299 "Be aware though, that this dramatically increases the time it\n"
1300 "will take to create the archive"));
1302 page->rename_files = gtk_check_button_new_with_mnemonic(_("R_ename"));
1303 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->rename_files), archiver_prefs.rename);
1304 gtk_box_pack_start(GTK_BOX(hbox1), page->rename_files, FALSE, FALSE, 0);
1305 CLAWS_SET_TIP(page->rename_files,
1306 _("Choose this option to use descriptive names for each file in the archive.\n"
1307 "The naming scheme: date_from@to@subject.\n"
1308 "Names will be truncated to max 96 characters"));
1310 page->unlink_files = gtk_check_button_new_with_mnemonic(_("_Delete"));
1311 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->unlink_files), archiver_prefs.unlink);
1312 gtk_box_pack_start(GTK_BOX(hbox1), page->unlink_files, FALSE, FALSE, 0);
1313 CLAWS_SET_TIP(page->unlink_files,
1314 _("Choose this option to delete mails after archiving\n"
1315 "At this point only handles IMAP4, Local mbox and POP3"));
1318 frame = gtk_frame_new(_("Selection options"));
1319 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1320 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1321 gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1323 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
1324 gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1325 gtk_container_add(GTK_CONTAINER(frame), hbox1);
1327 file_label = gtk_label_new(_("Select mails before"));
1328 gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1330 page->isoDate = gtk_entry_new();
1331 gtk_widget_set_name(page->isoDate, "isoDate");
1332 gtk_box_pack_start(GTK_BOX(hbox1), page->isoDate, TRUE, TRUE, 0);
1333 CLAWS_SET_TIP(page->isoDate,
1334 _("Select emails before a certain date\n"
1335 "Date must comply to ISO-8601 [YYYY-MM-DD]"));
1337 g_signal_connect(G_OBJECT(folder_select), "clicked",
1338 G_CALLBACK(foldersel_cb), page);
1339 g_signal_connect(G_OBJECT(file_select), "clicked",
1340 G_CALLBACK(filesel_cb), page);
1341 g_signal_connect(G_OBJECT(page->folder), "activate",
1342 G_CALLBACK(entry_change_cb), page);
1343 g_signal_connect(G_OBJECT(page->file), "activate",
1344 G_CALLBACK(entry_change_cb), page);
1346 gtk_widget_show_all(dialog);
1349 void archiver_gtk_done(struct ArchivePage* page, GtkWidget* widget) {
1350 dispose_archive_page(page);
1351 free(progress);
1352 gtk_widget_destroy(widget);
1353 /*debug_set_mode(FALSE);*/