summaryrefslogtreecommitdiffstats
path: root/gnome-autoar/autoar-gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-autoar/autoar-gtk.c')
-rw-r--r--gnome-autoar/autoar-gtk.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/gnome-autoar/autoar-gtk.c b/gnome-autoar/autoar-gtk.c
new file mode 100644
index 0000000..b4c4bb9
--- /dev/null
+++ b/gnome-autoar/autoar-gtk.c
@@ -0,0 +1,472 @@
+/* vim: set sw=2 ts=2 sts=2 et: */
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * autoar-gtk.c
+ * GTK+ user interfaces related to archives
+ *
+ * Copyright (C) 2013 Ting-Wei Lan
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "autoar-gtk.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+
+/* autoar_gtk_format_filter_simple */
+
+enum
+{
+ SIMPLE_COL_FORMAT,
+ SIMPLE_COL_FILTER,
+ SIMPLE_COL_DESCRIPTION,
+ N_SIMPLE_COLS
+};
+
+static char*
+format_filter_full_description (AutoarFormat format,
+ AutoarFilter filter)
+{
+ char *description, *extension, *full_description;
+
+ description = autoar_format_filter_get_description (format, filter);
+ extension = autoar_format_filter_get_extension (format, filter);
+ full_description = g_strdup_printf ("%s (*%s)", description, extension);
+
+ g_free (description);
+ g_free (extension);
+
+ return full_description;
+}
+
+static gboolean
+simple_row_separator_cb (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ void *data)
+{
+ char *description, first_char;
+
+ gtk_tree_model_get (model, iter, SIMPLE_COL_DESCRIPTION, &description, -1);
+ first_char = description != NULL ? *description : '\0';
+ g_free (description);
+
+ if (first_char == '\0')
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+simple_get_variable_row (GtkTreeModel *model,
+ GtkTreeIter *base_iter,
+ GtkTreeIter *dest_iter)
+{
+ GtkTreeIter iter;
+
+ iter = *base_iter;
+ if (!gtk_tree_model_iter_previous (model, &iter) ||
+ !gtk_tree_model_iter_previous (model, &iter) ||
+ !simple_row_separator_cb (model, &iter, NULL)) {
+ /* Create two new rows if it does not exist */
+ GtkListStore *store;
+
+ store = GTK_LIST_STORE (model);
+ gtk_list_store_insert_before (store, dest_iter, base_iter);
+ gtk_list_store_insert_before (store, &iter, dest_iter);
+ gtk_list_store_set (store, &iter,
+ SIMPLE_COL_FORMAT, 0,
+ SIMPLE_COL_FILTER, 0,
+ SIMPLE_COL_DESCRIPTION, "", -1);
+ } else {
+ /* Use the existing row */
+
+ iter = *base_iter;
+ gtk_tree_model_iter_previous (model, &iter);
+ *dest_iter = iter;
+ }
+}
+
+static void
+simple_changed_cb (GtkComboBox *simple,
+ void *data) {
+ GtkTreeIter iter;
+ GtkTreeModel* model;
+ AutoarFormat format;
+
+ if (!gtk_combo_box_get_active_iter (simple, &iter))
+ return;
+
+ model = gtk_combo_box_get_model (simple);
+ gtk_tree_model_get (model, &iter, SIMPLE_COL_FORMAT, &format, -1);
+
+ if (!format) {
+ GtkWidget *dialog_widget;
+ GtkDialog *dialog;
+ GtkWidget *dialog_content;
+
+ GtkWidget *simple_widget;
+ GtkWidget *advanced_widget;
+ int response;
+
+ AutoarFormat format;
+ AutoarFilter filter;
+
+ simple_widget = GTK_WIDGET (simple);
+ dialog_widget =
+ gtk_dialog_new_with_buttons (
+ _("Choose an archive format"),
+ GTK_WINDOW (gtk_widget_get_ancestor (simple_widget, GTK_TYPE_WINDOW)),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ _("OK"), GTK_RESPONSE_ACCEPT, NULL);
+ dialog = GTK_DIALOG (dialog_widget);
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_ACCEPT);
+
+ dialog_content = gtk_dialog_get_content_area (dialog);
+ advanced_widget = autoar_gtk_format_filter_advanced_new ();
+ gtk_container_add (GTK_CONTAINER (dialog_content), advanced_widget);
+ gtk_widget_show_all (dialog_widget);
+
+ response = gtk_dialog_run (dialog);
+ if (response == GTK_RESPONSE_ACCEPT &&
+ gtk_tree_model_iter_previous (model, &iter) &&
+ autoar_gtk_format_filter_advanced_get (advanced_widget, &format, &filter)) {
+ AutoarFormat scan_format;
+ AutoarFilter scan_filter;
+ GtkTreeIter scanner;
+ GtkTreeIter active_row;
+ char *description_string;
+
+ /* Scan the list to find the matching row */
+ gtk_tree_model_get_iter_first (model, &scanner);
+ do {
+ gtk_tree_model_get (model, &scanner,
+ SIMPLE_COL_FORMAT, &scan_format,
+ SIMPLE_COL_FILTER, &scan_filter, -1);
+ if (scan_format == format && scan_filter == filter) {
+ active_row = scanner;
+ goto got_new_active;
+ }
+ } while (gtk_tree_model_iter_next (model, &scanner));
+
+ /* No matching row, so we have to create it */
+ simple_get_variable_row (model, &iter, &active_row);
+ description_string = format_filter_full_description (format, filter);
+ gtk_list_store_set (GTK_LIST_STORE (model), &active_row,
+ SIMPLE_COL_FORMAT, format,
+ SIMPLE_COL_FILTER, filter,
+ SIMPLE_COL_DESCRIPTION, description_string, -1);
+ g_free (description_string);
+
+got_new_active:
+ gtk_combo_box_set_active_iter (simple, &active_row);
+ }
+
+ gtk_widget_destroy (dialog_widget);
+ }
+}
+
+GtkWidget*
+autoar_gtk_format_filter_simple_new (void)
+{
+ GtkWidget *simple_widget;
+ GtkComboBox *simple_combo;
+ GtkCellLayout *simple;
+ GtkCellRenderer *cell_renderer;
+
+ GtkListStore *store;
+ GtkTreeIter iter;
+ int i;
+
+ struct format_filter
+ {
+ AutoarFormat format;
+ AutoarFilter filter;
+ };
+
+ struct format_filter defaults [] = {
+ { AUTOAR_FORMAT_ZIP, AUTOAR_FILTER_NONE },
+ { AUTOAR_FORMAT_TAR, AUTOAR_FILTER_NONE },
+ { AUTOAR_FORMAT_TAR, AUTOAR_FILTER_GZIP },
+ { AUTOAR_FORMAT_TAR, AUTOAR_FILTER_BZIP2 },
+ { AUTOAR_FORMAT_TAR, AUTOAR_FILTER_XZ },
+ { AUTOAR_FORMAT_CPIO, AUTOAR_FILTER_NONE },
+ { AUTOAR_FORMAT_7ZIP, AUTOAR_FILTER_NONE },
+ };
+
+ store = gtk_list_store_new (N_SIMPLE_COLS, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
+ for (i = 0; i < sizeof (defaults) / sizeof (struct format_filter); i++) {
+ char *description;
+
+ gtk_list_store_append (store, &iter);
+
+ description = format_filter_full_description (defaults[i].format,
+ defaults[i].filter);
+ gtk_list_store_set (store, &iter,
+ SIMPLE_COL_FORMAT, defaults[i].format,
+ SIMPLE_COL_FILTER, defaults[i].filter,
+ SIMPLE_COL_DESCRIPTION, description, -1);
+ g_free (description);
+ }
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ SIMPLE_COL_FORMAT, 0,
+ SIMPLE_COL_FILTER, 0,
+ SIMPLE_COL_DESCRIPTION, "", -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ SIMPLE_COL_FORMAT, 0,
+ SIMPLE_COL_FILTER, 0,
+ SIMPLE_COL_DESCRIPTION, _("Other format…"), -1);
+
+ simple_widget = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+ simple = GTK_CELL_LAYOUT (simple_widget);
+ simple_combo = GTK_COMBO_BOX (simple_widget);
+ cell_renderer = gtk_cell_renderer_text_new ();
+
+ gtk_cell_layout_pack_start (simple, cell_renderer, FALSE);
+ gtk_cell_layout_add_attribute (simple, cell_renderer, "text", SIMPLE_COL_DESCRIPTION);
+
+ gtk_combo_box_set_active (simple_combo, 0);
+ gtk_combo_box_set_row_separator_func (simple_combo, simple_row_separator_cb, NULL, NULL);
+ g_signal_connect (simple, "changed", G_CALLBACK (simple_changed_cb), NULL);
+
+ g_object_unref (store);
+
+ return simple_widget;
+}
+
+gboolean
+autoar_gtk_format_filter_simple_get (GtkWidget *simple,
+ AutoarFormat *format,
+ AutoarFilter *filter)
+{
+ GtkComboBox *combo;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (!gtk_combo_box_get_active_iter (combo = GTK_COMBO_BOX (simple), &iter))
+ return FALSE;
+
+ model = gtk_combo_box_get_model (combo);
+ gtk_tree_model_get (model, &iter,
+ SIMPLE_COL_FORMAT, format,
+ SIMPLE_COL_FILTER, filter, -1);
+ return TRUE;
+}
+
+
+/* autoar_gtk_format_filter_advanced */
+
+enum
+{
+ ADVANCED_FORMAT_COL_FORMAT,
+ ADVANCED_FORMAT_COL_DESCRIPTION,
+ N_ADVANCED_FORMAT_COLS
+};
+
+enum
+{
+ ADVANCED_FILTER_COL_FILTER,
+ ADVANCED_FILTER_COL_DESCRIPTION,
+ N_ADVANCED_FILTER_COLS
+};
+
+static void
+advanced_update_description_cb (GtkTreeView *unused_variable,
+ GtkWidget *advanced)
+{
+ AutoarFormat format;
+ AutoarFilter filter;
+ GtkLabel *description;
+ char *description_string;
+
+ if (!autoar_gtk_format_filter_advanced_get (advanced, &format, &filter))
+ return;
+
+ description = GTK_LABEL (gtk_grid_get_child_at (GTK_GRID (advanced), 0, 1));
+ description_string = format_filter_full_description (format, filter);
+ gtk_label_set_text (description, description_string);
+ g_free (description_string);
+}
+
+static GtkTreeModel*
+advanced_format_store (void)
+{
+ GtkListStore *store;
+ int i;
+
+ store = gtk_list_store_new (N_ADVANCED_FORMAT_COLS, G_TYPE_INT, G_TYPE_STRING);
+ for (i = 1; i < AUTOAR_FORMAT_LAST; i++) {
+ GtkTreeIter iter;
+ const char *description;
+
+ gtk_list_store_append (store, &iter);
+ description = autoar_format_get_description (i);
+ gtk_list_store_set (store, &iter,
+ ADVANCED_FORMAT_COL_FORMAT, i,
+ ADVANCED_FORMAT_COL_DESCRIPTION, description, -1);
+ }
+
+ return GTK_TREE_MODEL (store);
+}
+
+static GtkTreeModel*
+advanced_filter_store (void)
+{
+ GtkListStore *store;
+ int i;
+
+ store = gtk_list_store_new (N_ADVANCED_FILTER_COLS, G_TYPE_INT, G_TYPE_STRING);
+ for (i = 1; i < AUTOAR_FILTER_LAST; i++) {
+ GtkTreeIter iter;
+ const char *description;
+
+ gtk_list_store_append (store, &iter);
+ description = autoar_filter_get_description (i);
+ gtk_list_store_set (store, &iter,
+ ADVANCED_FILTER_COL_FILTER, i,
+ ADVANCED_FILTER_COL_DESCRIPTION, description, -1);
+ }
+
+ return GTK_TREE_MODEL (store);
+}
+
+GtkWidget*
+autoar_gtk_format_filter_advanced_new (void)
+{
+ GtkWidget *advanced_widget;
+ GtkGrid *advanced;
+
+ GtkTreeModel *format_model;
+ GtkWidget *format_widget;
+ GtkTreeView *format;
+ GtkTreeSelection *format_selection;
+ GtkCellRenderer *format_renderer;
+ GtkTreePath *format_path;
+
+ GtkTreeModel *filter_model;
+ GtkWidget *filter_widget;
+ GtkTreeView *filter;
+ GtkTreeSelection *filter_selection;
+ GtkCellRenderer *filter_renderer;
+ GtkTreePath *filter_path;
+
+ GtkWidget *description_widget;
+ GtkLabel *description;
+
+ advanced_widget = gtk_grid_new ();
+ advanced = GTK_GRID (advanced_widget);
+ gtk_grid_set_row_spacing (advanced, 5);
+ gtk_grid_set_column_spacing (advanced, 5);
+ gtk_grid_set_column_homogeneous (advanced, TRUE);
+
+ format_model = advanced_format_store ();
+ format_widget = gtk_tree_view_new_with_model (format_model);
+ format = GTK_TREE_VIEW (format_widget);
+ format_selection = gtk_tree_view_get_selection (format);
+ format_renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_selection_set_mode (format_selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_insert_column_with_attributes (format, -1, _("Format"),
+ format_renderer, "text",
+ ADVANCED_FORMAT_COL_DESCRIPTION,
+ NULL);
+ format_path = gtk_tree_path_new_first ();
+ gtk_tree_view_set_cursor (format, format_path, NULL, FALSE);
+ gtk_tree_path_free (format_path);
+ gtk_grid_attach (advanced, format_widget, 0, 0, 1, 1);
+ g_object_unref (format_model);
+
+ filter_model = advanced_filter_store ();
+ filter_widget = gtk_tree_view_new_with_model (filter_model);
+ filter = GTK_TREE_VIEW (filter_widget);
+ filter_selection = gtk_tree_view_get_selection (filter);
+ filter_renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_selection_set_mode (filter_selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_insert_column_with_attributes (filter, -1, _("Filter"),
+ filter_renderer, "text",
+ ADVANCED_FILTER_COL_DESCRIPTION,
+ NULL);
+ filter_path = gtk_tree_path_new_first ();
+ gtk_tree_view_set_cursor (filter, filter_path, NULL, FALSE);
+ gtk_tree_path_free (filter_path);
+ gtk_grid_attach (advanced, filter_widget, 1, 0, 1, 1);
+ g_object_unref (filter_model);
+
+ description_widget = gtk_label_new (NULL);
+ description = GTK_LABEL (description_widget);
+ gtk_label_set_justify (description, GTK_JUSTIFY_CENTER);
+ gtk_grid_attach (advanced, description_widget, 0, 1, 2, 1);
+
+ g_signal_connect (format_widget, "cursor-changed",
+ G_CALLBACK (advanced_update_description_cb), advanced);
+ g_signal_connect (filter_widget, "cursor-changed",
+ G_CALLBACK (advanced_update_description_cb), advanced);
+
+ /* Run the callback now to set the initial text on the label */
+ advanced_update_description_cb (NULL, advanced_widget);
+
+ return advanced_widget;
+}
+
+gboolean
+autoar_gtk_format_filter_advanced_get (GtkWidget *advanced,
+ AutoarFormat *format,
+ AutoarFilter *filter)
+{
+ GtkGrid *grid;
+ GtkTreeIter format_iter, filter_iter;
+ GtkTreeView *format_view, *filter_view;
+ GtkTreePath *format_path, *filter_path;
+ GtkTreeModel *format_model, *filter_model;
+
+ grid = GTK_GRID (advanced);
+ format_view = GTK_TREE_VIEW (gtk_grid_get_child_at (grid, 0, 0));
+ filter_view = GTK_TREE_VIEW (gtk_grid_get_child_at (grid, 1, 0));
+
+ gtk_tree_view_get_cursor (format_view, &format_path, NULL);
+ gtk_tree_view_get_cursor (filter_view, &filter_path, NULL);
+ if (format_path == NULL || filter_path == NULL) {
+ gtk_tree_path_free (format_path);
+ gtk_tree_path_free (filter_path);
+ return FALSE;
+ }
+
+ format_model = gtk_tree_view_get_model (format_view);
+ filter_model = gtk_tree_view_get_model (filter_view);
+ if (!gtk_tree_model_get_iter (format_model, &format_iter, format_path) ||
+ !gtk_tree_model_get_iter (filter_model, &filter_iter, filter_path)) {
+ gtk_tree_path_free (format_path);
+ gtk_tree_path_free (filter_path);
+ return FALSE;
+ }
+ gtk_tree_path_free (format_path);
+ gtk_tree_path_free (filter_path);
+
+ gtk_tree_model_get (format_model, &format_iter,
+ ADVANCED_FORMAT_COL_FORMAT, format, -1);
+ gtk_tree_model_get (filter_model, &filter_iter,
+ ADVANCED_FILTER_COL_FILTER, filter, -1);
+
+ return TRUE;
+}