diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2013-08-26 16:43:06 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-08-26 16:46:24 +0800 |
commit | 75d9c28e60e6daa99cd47904ba35168106376fcc (patch) | |
tree | a6e940b77bada52f2e4baec3042af301dad3e355 | |
parent | b35405a565388698c80ad49f0794f3568b02e831 (diff) | |
download | gsoc2013-libgnome-autoar-75d9c28e60e6daa99cd47904ba35168106376fcc.tar.gz gsoc2013-libgnome-autoar-75d9c28e60e6daa99cd47904ba35168106376fcc.tar.zst gsoc2013-libgnome-autoar-75d9c28e60e6daa99cd47904ba35168106376fcc.zip |
Add widgets to select archive format and filter
-rw-r--r-- | gnome-autoar/Makefile.am | 2 | ||||
-rw-r--r-- | gnome-autoar/autoar-format-filter.c | 2 | ||||
-rw-r--r-- | gnome-autoar/autoar-gtk.c | 472 | ||||
-rw-r--r-- | gnome-autoar/autoar-gtk.h | 47 | ||||
-rw-r--r-- | gnome-autoar/autoar.h | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/test-ui.c | 61 |
7 files changed, 589 insertions, 3 deletions
diff --git a/gnome-autoar/Makefile.am b/gnome-autoar/Makefile.am index 155032d..58853c0 100644 --- a/gnome-autoar/Makefile.am +++ b/gnome-autoar/Makefile.am @@ -16,6 +16,7 @@ libgnome_autoar_h_sources = \ autoar-create.h \ autoar-extract.h \ autoar-format-filter.h \ + autoar-gtk.h \ autoar-pref.h \ $(NULL) libgnome_autoar_c_sources = \ @@ -23,6 +24,7 @@ libgnome_autoar_c_sources = \ autoar-create.c \ autoar-extract.c \ autoar-format-filter.c \ + autoar-gtk.c \ autoar-pref.c \ $(NULL) libgnome_autoar_generated_sources = \ diff --git a/gnome-autoar/autoar-format-filter.c b/gnome-autoar/autoar-format-filter.c index 5bb9619..eab5d8b 100644 --- a/gnome-autoar/autoar-format-filter.c +++ b/gnome-autoar/autoar-format-filter.c @@ -83,7 +83,7 @@ static AutoarFormatDescription autoar_format_description[] = { static AutoarFilterDescription autoar_filter_description[] = { { AUTOAR_FILTER_NONE, ARCHIVE_FILTER_NONE, "", "", - "", "" }, + "", "None" }, { AUTOAR_FILTER_COMPRESS, ARCHIVE_FILTER_COMPRESS, "Z", "compress", "application/x-compress", "UNIX-compressed" }, { AUTOAR_FILTER_GZIP, ARCHIVE_FILTER_GZIP, "gz", "gzip", 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; +} diff --git a/gnome-autoar/autoar-gtk.h b/gnome-autoar/autoar-gtk.h new file mode 100644 index 0000000..9102d7d --- /dev/null +++ b/gnome-autoar/autoar-gtk.h @@ -0,0 +1,47 @@ +/* vim: set sw=2 ts=2 sts=2 et: */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * autoar-gtk.h + * 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. + * + */ + +#ifndef AUTOAR_UI_H +#define AUTOAR_UI_H + +#include <gtk/gtk.h> + +#include "autoar-format-filter.h" + +G_BEGIN_DECLS + +GtkWidget *autoar_gtk_format_filter_simple_new (void); +gboolean autoar_gtk_format_filter_simple_get (GtkWidget *simple, + AutoarFormat *format, + AutoarFilter *filter); + +GtkWidget *autoar_gtk_format_filter_advanced_new (void); +gboolean autoar_gtk_format_filter_advanced_get (GtkWidget *advanced, + AutoarFormat *format, + AutoarFilter *filter); + +G_END_DECLS + +#endif /* AUTOAR_UI_H */ diff --git a/gnome-autoar/autoar.h b/gnome-autoar/autoar.h index 90b9405..8bb47b6 100644 --- a/gnome-autoar/autoar.h +++ b/gnome-autoar/autoar.h @@ -29,7 +29,7 @@ #include <gnome-autoar/autoar-create.h> #include <gnome-autoar/autoar-format-filter.h> #include <gnome-autoar/autoar-extract.h> +#include <gnome-autoar/autoar-gtk.h> #include <gnome-autoar/autoar-pref.h> -/* #include <autoarchive/autoar-ui.h> */ #endif /* AUTOARCHIVE_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 2b432af..c96ef9a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,7 +2,7 @@ NULL = -noinst_PROGRAMS = test-extract test-pref test-create +noinst_PROGRAMS = test-extract test-pref test-create test-ui test_cflags = \ $(DEPENDENCIES_CFLAGS) \ @@ -27,3 +27,7 @@ test_pref_LDADD = $(test_libs) test_create_SOURCES = test-create.c test_create_CFLAGS = $(test_cflags) test_create_LDADD = $(test_libs) + +test_ui_SOURCES = test-ui.c +test_ui_CFLAGS = $(test_cflags) +test_ui_LDADD = $(test_libs) diff --git a/tests/test-ui.c b/tests/test-ui.c new file mode 100644 index 0000000..ad69adb --- /dev/null +++ b/tests/test-ui.c @@ -0,0 +1,61 @@ +/* vim: set sw=2 ts=2 sts=2 et: */ + +#include <gnome-autoar/autoar.h> +#include <gtk/gtk.h> +#include <stdio.h> +#include <stdlib.h> + +static gboolean +before_deleted (GtkWindow *window, + GdkEvent *event, + GtkWidget *simple) +{ + AutoarFormat format; + AutoarFilter filter; + char *str; + + autoar_gtk_format_filter_simple_get (simple, &format, &filter); + if (!format || !filter) { + GtkWidget *warning; + warning = gtk_message_dialog_new (window, + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Your choice is not valid!"); + gtk_dialog_run (GTK_DIALOG (warning)); + gtk_widget_destroy (warning); + + return TRUE; + } + + puts (str = autoar_format_filter_get_description (format, filter)); + free (str); + puts (str = autoar_format_filter_get_extension (format, filter)); + free (str); + + gtk_main_quit(); + return FALSE; +} + +int +main (int argc, + char *argv[]) +{ + GtkWidget *window; + GtkWidget *simple; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), argv[0]); + + simple = autoar_gtk_format_filter_simple_new (); + gtk_container_add (GTK_CONTAINER (window), simple); + g_signal_connect (window, "delete-event", G_CALLBACK (before_deleted), simple); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} |