[file-roller/wip/gtk4: 34/54] new archive: added a custom location button
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller/wip/gtk4: 34/54] new archive: added a custom location button
- Date: Sun, 2 Oct 2022 17:56:50 +0000 (UTC)
commit 365e93f6de970a257cb899f081bc94e4ea7080e1
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Oct 1 21:56:11 2022 +0200
new archive: added a custom location button
src/fr-location-button.c | 266 +++++++++++++++++++++++++++++++++++++++++++
src/fr-location-button.h | 50 ++++++++
src/fr-new-archive-dialog.c | 9 +-
src/meson.build | 2 +
src/ui/new-archive-dialog.ui | 69 +++++------
5 files changed, 362 insertions(+), 34 deletions(-)
---
diff --git a/src/fr-location-button.c b/src/fr-location-button.c
new file mode 100644
index 00000000..4b609413
--- /dev/null
+++ b/src/fr-location-button.c
@@ -0,0 +1,266 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * File-Roller
+ *
+ * Copyright (C) 2022 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "gtk-utils.h"
+#include "glib-utils.h"
+#include "fr-location-button.h"
+
+
+enum {
+ PROP_0,
+ PROP_TITLE,
+};
+
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+static guint fr_location_button_signals[LAST_SIGNAL] = { 0 };
+
+
+typedef struct {
+ GFile *location;
+ GtkWidget *label;
+ GtkWidget *icon;
+ GtkFileChooserNative *chooser;
+ char *title;
+} FrLocationButtonPrivate;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (FrLocationButton, fr_location_button, GTK_TYPE_BUTTON)
+
+
+static void
+fr_location_button_finalize (GObject *object)
+{
+ FrLocationButton *self = FR_LOCATION_BUTTON (object);
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ _g_object_unref (private->chooser);
+ g_free (private->title);
+
+ G_OBJECT_CLASS (fr_location_button_parent_class)->finalize (object);
+}
+
+
+static void
+gth_location_button_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ FrLocationButton *self = FR_LOCATION_BUTTON (object);
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ switch (property_id) {
+ case PROP_TITLE:
+ g_free (private->title);
+ private->title = g_value_dup_string (value);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void
+gth_location_button_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ FrLocationButton *self = FR_LOCATION_BUTTON (object);
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ switch (property_id) {
+ case PROP_TITLE:
+ g_value_set_string (value, private->title);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void
+fr_location_button_class_init (FrLocationButtonClass *klass)
+{
+ GObjectClass *object_class;
+
+ fr_location_button_parent_class = g_type_class_peek_parent (klass);
+
+ object_class = (GObjectClass*) klass;
+ object_class->set_property = gth_location_button_set_property;
+ object_class->get_property = gth_location_button_get_property;
+ object_class->finalize = fr_location_button_finalize;
+
+ fr_location_button_signals[CHANGED] =
+ g_signal_newv ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ /* class_closure = */ NULL,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0, NULL);
+
+ g_object_class_install_property (object_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "Title",
+ "The file chooser title",
+ NULL,
+ G_PARAM_READWRITE));
+
+}
+
+
+static void
+location_changed (FrLocationButton *self) {
+ g_signal_emit (self, fr_location_button_signals[CHANGED], 0, NULL);
+}
+
+
+static void
+file_chooser_response_cb (GtkNativeDialog *native,
+ int response,
+ gpointer user_data)
+{
+ FrLocationButton *self = user_data;
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ if (response == GTK_RESPONSE_ACCEPT) {
+ GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (private->chooser));
+ if (file != NULL) {
+ fr_location_button_set_location (self, file);
+ location_changed (self);
+ g_object_unref (file);
+ }
+ }
+
+ g_object_unref (private->chooser);
+ private->chooser = NULL;
+}
+
+
+static void
+clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ FrLocationButton *self = user_data;
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ if (private->chooser != NULL)
+ return;
+
+ private->chooser = gtk_file_chooser_native_new (private->title,
+ GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ _GTK_LABEL_OPEN,
+ _GTK_LABEL_CANCEL);
+ gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (private->chooser), TRUE);
+ if (private->location != NULL)
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (private->chooser), private->location, NULL);
+ g_signal_connect (private->chooser,
+ "response",
+ G_CALLBACK (file_chooser_response_cb),
+ self);
+ gtk_native_dialog_show (GTK_NATIVE_DIALOG (private->chooser));
+}
+
+
+static void
+fr_location_button_init (FrLocationButton *self)
+{
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ private->chooser = NULL;
+ private->title = NULL;
+
+ gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
+
+ GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+ gtk_button_set_child (GTK_BUTTON (self), box);
+
+ private->icon = gtk_image_new ();
+ gtk_box_append (GTK_BOX (box), private->icon);
+
+ private->label = gtk_label_new (private->title);
+ gtk_box_append (GTK_BOX (box), private->label);
+
+ g_signal_connect (self,
+ "clicked",
+ G_CALLBACK (clicked_cb),
+ self);
+}
+
+
+GtkWidget *
+fr_location_button_new (const char *title)
+{
+ return g_object_new (FR_TYPE_LOCATION_BUTTON,
+ "title", title,
+ NULL);
+}
+
+
+GFile *
+fr_location_button_get_location (FrLocationButton *self)
+{
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+ return _g_object_ref (private->location);
+}
+
+
+void
+fr_location_button_set_location (FrLocationButton *self,
+ GFile *location)
+{
+ FrLocationButtonPrivate *private = fr_location_button_get_instance_private (self);
+
+ _g_object_unref (private->location);
+ private->location = g_object_ref (location);
+
+ GFileInfo *info = g_file_query_info (private->location,
+ "standard::display-name,standard::icon,standard::symbolic-icon",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info != NULL) {
+ gtk_label_set_text (GTK_LABEL (private->label), g_file_info_get_display_name (info));
+ gtk_image_set_from_gicon (GTK_IMAGE (private->icon), g_file_info_get_symbolic_icon (info));
+ g_object_unref (info);
+ }
+ else {
+ char *name = g_file_get_uri (private->location);
+ gtk_label_set_text (GTK_LABEL (private->label), name);
+ gtk_image_set_from_icon_name (GTK_IMAGE (private->icon), "folder-symbolic");
+ g_free (name);
+ }
+}
diff --git a/src/fr-location-button.h b/src/fr-location-button.h
new file mode 100644
index 00000000..e7f253a9
--- /dev/null
+++ b/src/fr-location-button.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * File-Roller
+ *
+ * Copyright (C) 2022 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FR_LOCATION_BUTTON_H
+#define FR_LOCATION_BUTTON_H
+
+#include <gtk/gtk.h>
+
+#define FR_TYPE_LOCATION_BUTTON (fr_location_button_get_type ())
+G_DECLARE_FINAL_TYPE (FrLocationButton, fr_location_button, FR, LOCATION_BUTTON, GtkButton)
+
+struct _FrLocationButton {
+ GtkButton parent_class;
+};
+
+struct _FrLocationButtonClass {
+ GtkButtonClass parent_class;
+ void (* changed) (FrLocationButton *location_button);
+};
+
+GtkWidget * fr_location_button_new (const char *title);
+
+/**
+ * fr_location_button_get_location:
+ * Returns: (transfer full)
+ */
+GFile * fr_location_button_get_location (FrLocationButton *dialog);
+
+void fr_location_button_set_location (FrLocationButton *dialog,
+ GFile *location);
+
+#endif /* FR_LOCATION_BUTTON_H */
diff --git a/src/fr-new-archive-dialog.c b/src/fr-new-archive-dialog.c
index ae2867b9..428cd131 100644
--- a/src/fr-new-archive-dialog.c
+++ b/src/fr-new-archive-dialog.c
@@ -26,6 +26,7 @@
#include <gio/gio.h>
#include "file-utils.h"
#include "fr-init.h"
+#include "fr-location-button.h"
#include "fr-new-archive-dialog.h"
#include "glib-utils.h"
#include "gtk-utils.h"
@@ -48,6 +49,7 @@ struct _FrNewArchiveDialog {
gboolean can_create_volumes;
GFile *original_file;
GList *files_to_add;
+ GtkWidget *location_button;
};
@@ -211,6 +213,9 @@ _fr_new_archive_dialog_construct (FrNewArchiveDialog *self,
_g_object_unref (self->original_file);
self->original_file = _g_object_ref (original_file);
+ self->location_button = fr_location_button_new (_("Location"));
+ gtk_box_append (GTK_BOX (GET_WIDGET ("parent_filechooserbutton_container")), self->location_button);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("location_label")), self->location_button);
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), GET_WIDGET ("content"));
gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
@@ -247,7 +252,7 @@ _fr_new_archive_dialog_construct (FrNewArchiveDialog *self,
if (folder == NULL)
folder = _g_file_get_home ();
- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (GET_WIDGET ("parent_filechooserbutton")),
folder, NULL);
+ fr_location_button_set_location (FR_LOCATION_BUTTON (self->location_button), folder);
gtk_expander_set_expanded (GTK_EXPANDER (GET_WIDGET ("other_options_expander")),
g_settings_get_boolean (self->settings, PREF_NEW_EXPAND_OPTIONS));
@@ -419,7 +424,7 @@ fr_new_archive_dialog_get_file (FrNewArchiveDialog *self,
/* File */
n_format = get_selected_format (self);
- parent = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (GET_WIDGET ("parent_filechooserbutton")));
+ parent = fr_location_button_get_location (FR_LOCATION_BUTTON (self->location_button));
if (parent == NULL) {
GtkWidget *msg_dialog = _gtk_error_dialog_new (
GTK_WINDOW (self),
diff --git a/src/meson.build b/src/meson.build
index ca149be7..5cdb8fb2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -40,6 +40,7 @@ source_files = files(
'fr-file-selector-dialog.c',
'fr-init.c',
'fr-location-bar.c',
+ 'fr-location-button.c',
'fr-new-archive-dialog.c',
'fr-process.c',
'fr-window-actions-callbacks.c',
@@ -83,6 +84,7 @@ fr_headers = files(
'fr-file-selector-dialog.h',
'fr-init.h',
'fr-location-bar.h',
+ 'fr-location-button.h',
'fr-new-archive-dialog.h',
'fr-process.h',
'fr-window-actions-callbacks.h',
diff --git a/src/ui/new-archive-dialog.ui b/src/ui/new-archive-dialog.ui
index 91d0ef62..f9380932 100644
--- a/src/ui/new-archive-dialog.ui
+++ b/src/ui/new-archive-dialog.ui
@@ -10,7 +10,7 @@
<child>
<object class="GtkBox" id="box1">
<property name="orientation">vertical</property>
- <property name="spacing">12</property>
+ <property name="spacing">24</property>
<child>
<object class="GtkBox" id="box7">
<property name="orientation">vertical</property>
@@ -52,12 +52,11 @@
<object class="GtkLabel" id="location_label">
<property name="label" translatable="1">_Location:</property>
<property name="use_underline">1</property>
- <property name="mnemonic_widget">parent_filechooserbutton</property>
<property name="halign">start</property>
</object>
</child>
<child>
- <object class="GtkBox" id="parent_filechooserbutton">
+ <object class="GtkBox" id="parent_filechooserbutton_container">
</object>
</child>
</object>
@@ -73,7 +72,7 @@
<object class="GtkBox" id="box4">
<property name="margin_top">6</property>
<property name="orientation">vertical</property>
- <property name="spacing">6</property>
+ <property name="spacing">12</property>
<child>
<object class="GtkBox" id="box5">
<property name="margin_top">12</property>
@@ -97,41 +96,47 @@
</object>
</child>
<child>
- <object class="GtkCheckButton" id="encrypt_header_checkbutton">
- <property name="label" translatable="1">_Encrypt the file list too</property>
- <property name="focusable">1</property>
- <property name="use_underline">1</property>
- <property name="halign">start</property>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="volume_box">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkCheckButton" id="volume_checkbutton">
- <property name="label" translatable="1" comments="this is part of a sentence, for
example "split into volumes of 10.0 MB", where MB stands for megabyte.">Split into _volumes
of</property>
+ <object class="GtkCheckButton" id="encrypt_header_checkbutton">
+ <property name="label" translatable="1">_Encrypt the file list too</property>
<property name="focusable">1</property>
<property name="use_underline">1</property>
- <property name="halign">center</property>
- </object>
- </child>
- <child>
- <object class="GtkSpinButton" id="volume_spinbutton">
- <property name="halign">center</property>
- <property name="focusable">1</property>
- <property name="width_chars">4</property>
- <property name="text" translatable="1">10,0</property>
- <property name="adjustment">volume_adjustment</property>
- <property name="climb_rate">1</property>
- <property name="digits">1</property>
- <property name="numeric">1</property>
- <property name="value">10</property>
+ <property name="halign">start</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="label50">
- <property name="halign">center</property>
- <property name="label" translatable="1" comments="MB means megabytes">MB</property>
+ <object class="GtkBox" id="volume_box">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="volume_checkbutton">
+ <property name="label" translatable="1" comments="this is part of a sentence, for
example "split into volumes of 10.0 MB", where MB stands for megabyte.">Split into _volumes
of</property>
+ <property name="focusable">1</property>
+ <property name="use_underline">1</property>
+ <property name="halign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="volume_spinbutton">
+ <property name="halign">center</property>
+ <property name="focusable">1</property>
+ <property name="width_chars">4</property>
+ <property name="text" translatable="1">10,0</property>
+ <property name="adjustment">volume_adjustment</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">1</property>
+ <property name="numeric">1</property>
+ <property name="value">10</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label50">
+ <property name="halign">center</property>
+ <property name="label" translatable="1" comments="MB means megabytes">MB</property>
+ </object>
+ </child>
</object>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]