[gnome-flashback] desktop: add New Folder to desktop menu
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] desktop: add New Folder to desktop menu
- Date: Wed, 13 Nov 2019 02:39:03 +0000 (UTC)
commit eeee72c9b29e395de9f63f135c6d98af95026959
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Wed Nov 13 04:37:52 2019 +0200
desktop: add New Folder to desktop menu
gnome-flashback/libdesktop/Makefile.am | 2 +
.../libdesktop/gf-create-folder-dialog.c | 258 +++++++++++++++++++++
.../libdesktop/gf-create-folder-dialog.h | 35 +++
gnome-flashback/libdesktop/gf-icon-view.c | 189 ++++++++++++++-
gnome-flashback/libdesktop/gf-icon.c | 6 +
gnome-flashback/libdesktop/gf-icon.h | 18 +-
po/POTFILES.in | 1 +
7 files changed, 492 insertions(+), 17 deletions(-)
---
diff --git a/gnome-flashback/libdesktop/Makefile.am b/gnome-flashback/libdesktop/Makefile.am
index cfc0215..744244f 100644
--- a/gnome-flashback/libdesktop/Makefile.am
+++ b/gnome-flashback/libdesktop/Makefile.am
@@ -18,6 +18,8 @@ libdesktop_la_CFLAGS = \
libdesktop_la_SOURCES = \
gf-background.c \
gf-background.h \
+ gf-create-folder-dialog.c \
+ gf-create-folder-dialog.h \
gf-desktop-enums.h \
gf-desktop-window.c \
gf-desktop-window.h \
diff --git a/gnome-flashback/libdesktop/gf-create-folder-dialog.c
b/gnome-flashback/libdesktop/gf-create-folder-dialog.c
new file mode 100644
index 0000000..2057453
--- /dev/null
+++ b/gnome-flashback/libdesktop/gf-create-folder-dialog.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 "gf-create-folder-dialog.h"
+
+#include <glib/gi18n.h>
+
+struct _GfCreateFolderDialog
+{
+ GtkDialog parent;
+
+ GtkWidget *create_button;
+
+ GtkWidget *name_entry;
+
+ GtkWidget *error_revealer;
+ GtkWidget *error_label;
+};
+
+enum
+{
+ VALIDATE,
+
+ LAST_SIGNAL
+};
+
+static guint dialog_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GfCreateFolderDialog, gf_create_folder_dialog, GTK_TYPE_DIALOG)
+
+static void
+cancel_clicked_cb (GtkWidget *widget,
+ GfCreateFolderDialog *self)
+{
+ gtk_widget_destroy (GTK_WIDGET (self));
+}
+
+static void
+create_clicked_cb (GtkWidget *widget,
+ GfCreateFolderDialog *self)
+{
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
+}
+
+static void
+name_changed_cb (GtkEditable *editable,
+ GfCreateFolderDialog *self)
+{
+ GtkRevealer *revealer;
+ const char *text;
+ char *folder_name;
+ char *validate_error;
+ const char *error;
+ gboolean valid;
+
+ revealer = GTK_REVEALER (self->error_revealer);
+ text = gtk_entry_get_text (GTK_ENTRY (self->name_entry));
+ folder_name = g_strdup (text);
+ error = NULL;
+ valid = TRUE;
+
+ folder_name = g_strstrip (folder_name);
+ validate_error = NULL;
+
+ if (*folder_name == '\0')
+ {
+ error = NULL;
+ valid = FALSE;
+ }
+ else if (g_strstr_len (folder_name, -1, "/") != NULL)
+ {
+ error = _("Folder names cannot contain “/”.");
+ valid = FALSE;
+ }
+ else if (g_strcmp0 (folder_name, ".") == 0)
+ {
+ error = _("A folder cannot be called “.”.");
+ valid = FALSE;
+ }
+ else if (g_strcmp0 (folder_name, "..") == 0)
+ {
+ error = _("A folder cannot be called “..”.");
+ valid = FALSE;
+ }
+
+ if (valid)
+ {
+ g_assert_true (error == NULL);
+
+ g_signal_emit (self, dialog_signals[VALIDATE], 0,
+ folder_name, &validate_error);
+
+ if (validate_error != NULL)
+ {
+ error = validate_error;
+ valid = FALSE;
+ }
+ }
+
+ if (error == NULL &&
+ g_str_has_prefix (folder_name, "."))
+ {
+ error = _("Folders with “.” at the beginning of their name are hidden.");
+ }
+
+ gtk_label_set_text (GTK_LABEL (self->error_label), error);
+ gtk_revealer_set_reveal_child (revealer, error != NULL);
+
+ gtk_widget_set_sensitive (self->create_button, valid);
+
+ g_free (validate_error);
+ g_free (folder_name);
+}
+
+static void
+name_activate_cb (GtkWidget *widget,
+ GfCreateFolderDialog *self)
+{
+ if (!gtk_widget_get_sensitive (self->create_button))
+ return;
+
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
+}
+
+static void
+setup_header_bar (GfCreateFolderDialog *self)
+{
+ GtkWidget *header_bar;
+ GtkWidget *cancel_button;
+ GtkStyleContext *style;
+
+ header_bar = gtk_dialog_get_header_bar (GTK_DIALOG (self));
+ gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (header_bar), FALSE);
+ gtk_header_bar_set_title (GTK_HEADER_BAR (header_bar), _("New Folder"));
+
+ cancel_button = gtk_button_new_with_label (_("Cancel"));
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), cancel_button);
+ gtk_widget_show (cancel_button);
+
+ g_signal_connect (cancel_button, "clicked",
+ G_CALLBACK (cancel_clicked_cb),
+ self);
+
+ self->create_button = gtk_button_new_with_label (_("Create"));
+ gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), self->create_button);
+ gtk_widget_show (self->create_button);
+
+ style = gtk_widget_get_style_context (self->create_button);
+ gtk_style_context_add_class (style, GTK_STYLE_CLASS_SUGGESTED_ACTION);
+
+ gtk_widget_set_sensitive (self->create_button, FALSE);
+
+ g_signal_connect (self->create_button, "clicked",
+ G_CALLBACK (create_clicked_cb),
+ self);
+}
+
+static void
+setup_content_area (GfCreateFolderDialog *self)
+{
+ GtkWidget *content;
+ GtkWidget *label;
+
+ content = gtk_dialog_get_content_area (GTK_DIALOG (self));
+
+ g_object_set (content,
+ "margin", 18,
+ "margin-bottom", 12,
+ "spacing", 6,
+ NULL);
+
+ label = gtk_label_new (_("Folder name"));
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_container_add (GTK_CONTAINER (content), label);
+ gtk_widget_show (label);
+
+ self->name_entry = gtk_entry_new ();
+ gtk_container_add (GTK_CONTAINER (content), self->name_entry);
+ gtk_widget_show (self->name_entry);
+
+ g_signal_connect (self->name_entry, "changed",
+ G_CALLBACK (name_changed_cb),
+ self);
+
+ g_signal_connect (self->name_entry, "activate",
+ G_CALLBACK (name_activate_cb),
+ self);
+
+ self->error_revealer = gtk_revealer_new ();
+ gtk_container_add (GTK_CONTAINER (content), self->error_revealer);
+ gtk_widget_show (self->error_revealer);
+
+ self->error_label = gtk_label_new (NULL);
+ gtk_label_set_xalign (GTK_LABEL (self->error_label), 0.0);
+ gtk_container_add (GTK_CONTAINER (self->error_revealer), self->error_label);
+ gtk_widget_show (self->error_label);
+}
+
+static void
+install_signals (void)
+{
+ dialog_signals[VALIDATE] =
+ g_signal_new ("validate", GF_TYPE_CREATE_FOLDER_DIALOG,
+ G_SIGNAL_RUN_LAST, 0,
+ g_signal_accumulator_first_wins,
+ NULL, NULL,
+ G_TYPE_STRING, 1, G_TYPE_STRING);
+}
+
+static void
+gf_create_folder_dialog_class_init (GfCreateFolderDialogClass *self_class)
+{
+ install_signals ();
+}
+
+static void
+gf_create_folder_dialog_init (GfCreateFolderDialog *self)
+{
+ setup_header_bar (self);
+ setup_content_area (self);
+}
+
+GtkWidget *
+gf_create_folder_dialog_new (void)
+{
+ return g_object_new (GF_TYPE_CREATE_FOLDER_DIALOG,
+ "use-header-bar", TRUE,
+ "width-request", 450,
+ "resizable", FALSE,
+ NULL);
+}
+
+char *
+gf_create_folder_dialog_get_folder_name (GfCreateFolderDialog *self)
+{
+ const char *text;
+ char *folder_name;
+
+ text = gtk_entry_get_text (GTK_ENTRY (self->name_entry));
+ folder_name = g_strdup (text);
+
+ return g_strstrip (folder_name);
+}
diff --git a/gnome-flashback/libdesktop/gf-create-folder-dialog.h
b/gnome-flashback/libdesktop/gf-create-folder-dialog.h
new file mode 100644
index 0000000..ffc5669
--- /dev/null
+++ b/gnome-flashback/libdesktop/gf-create-folder-dialog.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 GF_CREATE_FOLDER_DIALOG_H
+#define GF_CREATE_FOLDER_DIALOG_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_CREATE_FOLDER_DIALOG (gf_create_folder_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (GfCreateFolderDialog, gf_create_folder_dialog,
+ GF, CREATE_FOLDER_DIALOG, GtkDialog)
+
+GtkWidget *gf_create_folder_dialog_new (void);
+
+char *gf_create_folder_dialog_get_folder_name (GfCreateFolderDialog *self);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libdesktop/gf-icon-view.c b/gnome-flashback/libdesktop/gf-icon-view.c
index 35cc8cb..75318a9 100644
--- a/gnome-flashback/libdesktop/gf-icon-view.c
+++ b/gnome-flashback/libdesktop/gf-icon-view.c
@@ -21,9 +21,11 @@
#include <gdk/gdkx.h>
#include <glib/gi18n.h>
+#include "gf-create-folder-dialog.h"
#include "gf-desktop-enum-types.h"
#include "gf-icon.h"
#include "gf-monitor-view.h"
+#include "gf-nautilus-gen.h"
#include "gf-utils.h"
typedef struct
@@ -59,6 +61,10 @@ struct _GfIconView
GtkStyleContext *rubberband_style;
GdkRectangle rubberband_rect;
GList *rubberband_icons;
+
+ GfNautilusGen *nautilus;
+
+ GtkWidget *create_folder_dialog;
};
enum
@@ -76,7 +82,8 @@ G_DEFINE_TYPE (GfIconView, gf_icon_view, GTK_TYPE_EVENT_BOX)
static char *
get_required_attributes (void)
{
- return gf_build_attributes_list (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ return gf_build_attributes_list (G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP,
@@ -391,20 +398,120 @@ desktop_changed_cb (GFileMonitor *monitor,
}
}
+static char *
+create_folder_dialog_validate_cb (GfCreateFolderDialog *dialog,
+ const char *folder_name,
+ GfIconView *self)
+{
+ GList *l;
+
+ for (l = self->icons; l != NULL; l = l->next)
+ {
+ GfIconInfo *info;
+ const char *name;
+
+ info = l->data;
+
+ name = gf_icon_get_name (GF_ICON (info->icon));
+
+ if (g_strcmp0 (name, folder_name) == 0)
+ return g_strdup (_("A folder with that name already exists."));
+
+ }
+
+ return NULL;
+}
+
static void
-open_terminal_cb (GtkMenuItem *item,
- GfIconView *self)
+create_folder_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
{
GError *error;
error = NULL;
- if (!gf_launch_desktop_file ("org.gnome.Terminal.desktop", &error))
+ gf_nautilus_gen_call_create_folder_finish (GF_NAUTILUS_GEN (object),
+ res, &error);
+
+ if (error != NULL)
{
- g_warning ("%s", error->message);
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error creating new folder: %s", error->message);
g_error_free (error);
}
}
+static void
+create_folder_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ GfIconView *self)
+{
+ GfCreateFolderDialog *folder_dialog;
+ char *folder_name;
+ GFile *new_file;
+ char *uri;
+
+ if (response_id != GTK_RESPONSE_ACCEPT)
+ return;
+
+ folder_dialog = GF_CREATE_FOLDER_DIALOG (dialog);
+ folder_name = gf_create_folder_dialog_get_folder_name (folder_dialog);
+
+ new_file = g_file_get_child (self->desktop, folder_name);
+ g_free (folder_name);
+
+ uri = g_file_get_uri (new_file);
+ g_object_unref (new_file);
+
+ gf_nautilus_gen_call_create_folder (self->nautilus, uri,
+ self->cancellable,
+ create_folder_cb,
+ NULL);
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ g_free (uri);
+}
+
+static void
+create_folder_dialog_destroy_cb (GtkWidget *widget,
+ GfIconView *self)
+{
+ self->create_folder_dialog = NULL;
+}
+
+static void
+new_folder_cb (GtkMenuItem *item,
+ GfIconView *self)
+{
+ GtkWidget *dialog;
+
+ if (self->nautilus == NULL)
+ return;
+
+ if (self->create_folder_dialog != NULL)
+ {
+ gtk_window_present (GTK_WINDOW (self->create_folder_dialog));
+ return;
+ }
+
+ dialog = gf_create_folder_dialog_new ();
+ self->create_folder_dialog = dialog;
+
+ g_signal_connect (dialog, "validate",
+ G_CALLBACK (create_folder_dialog_validate_cb),
+ self);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (create_folder_dialog_response_cb),
+ self);
+
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (create_folder_dialog_destroy_cb),
+ self);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
static void
change_background_cb (GtkMenuItem *item,
GfIconView *self)
@@ -419,6 +526,20 @@ change_background_cb (GtkMenuItem *item,
}
}
+static void
+open_terminal_cb (GtkMenuItem *item,
+ GfIconView *self)
+{
+ GError *error;
+
+ error = NULL;
+ if (!gf_launch_desktop_file ("org.gnome.Terminal.desktop", &error))
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
static GtkWidget *
create_popup_menu (GfIconView *self)
{
@@ -431,12 +552,12 @@ create_popup_menu (GfIconView *self)
context = gtk_widget_get_style_context (popup_menu);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_CONTEXT_MENU);
- item = gtk_menu_item_new_with_label (_("Open Terminal"));
+ item = gtk_menu_item_new_with_label (_("New Folder"));
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
gtk_widget_show (item);
g_signal_connect (item, "activate",
- G_CALLBACK (open_terminal_cb),
+ G_CALLBACK (new_folder_cb),
self);
item = gtk_separator_menu_item_new ();
@@ -451,6 +572,18 @@ create_popup_menu (GfIconView *self)
G_CALLBACK (change_background_cb),
self);
+ item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+ gtk_widget_show (item);
+
+ item = gtk_menu_item_new_with_label (_("Open Terminal"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect (item, "activate",
+ G_CALLBACK (open_terminal_cb),
+ self);
+
return popup_menu;
}
@@ -771,8 +904,6 @@ enumerate_desktop (GfIconView *self)
attributes = get_required_attributes ();
- self->cancellable = g_cancellable_new ();
-
g_file_enumerate_children_async (self->desktop,
attributes,
G_FILE_QUERY_INFO_NONE,
@@ -784,6 +915,32 @@ enumerate_desktop (GfIconView *self)
g_free (attributes);
}
+static void
+nautilus_ready_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+
+{
+ GError *error;
+ GfNautilusGen *nautilus;
+ GfIconView *self;
+
+ error = NULL;
+ nautilus = gf_nautilus_gen_proxy_new_for_bus_finish (res, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ self = GF_ICON_VIEW (user_data);
+ self->nautilus = nautilus;
+}
+
static GtkWidget *
find_monitor_view_by_monitor (GfIconView *self,
GdkMonitor *monitor)
@@ -1015,6 +1172,10 @@ gf_icon_view_dispose (GObject *object)
g_clear_object (&self->rubberband_style);
g_clear_pointer (&self->rubberband_icons, g_list_free);
+ g_clear_object (&self->nautilus);
+
+ g_clear_pointer (&self->create_folder_dialog, gtk_widget_destroy);
+
G_OBJECT_CLASS (gf_icon_view_parent_class)->dispose (object);
}
@@ -1210,6 +1371,16 @@ gf_icon_view_init (GfIconView *self)
gtk_container_add (GTK_CONTAINER (self), self->fixed);
gtk_widget_show (self->fixed);
+ self->cancellable = g_cancellable_new ();
+
+ gf_nautilus_gen_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.Nautilus",
+ "/org/gnome/Nautilus",
+ self->cancellable,
+ nautilus_ready_cb,
+ self);
+
display = gdk_display_get_default ();
n_monitors = gdk_display_get_n_monitors (display);
diff --git a/gnome-flashback/libdesktop/gf-icon.c b/gnome-flashback/libdesktop/gf-icon.c
index 356e0ad..3d241a8 100644
--- a/gnome-flashback/libdesktop/gf-icon.c
+++ b/gnome-flashback/libdesktop/gf-icon.c
@@ -469,6 +469,12 @@ gf_icon_get_file (GfIcon *self)
return self->file;
}
+const char *
+gf_icon_get_name (GfIcon *self)
+{
+ return g_file_info_get_name (self->info);
+}
+
gboolean
gf_icon_is_hidden (GfIcon *self)
{
diff --git a/gnome-flashback/libdesktop/gf-icon.h b/gnome-flashback/libdesktop/gf-icon.h
index ae43da4..72a0df0 100644
--- a/gnome-flashback/libdesktop/gf-icon.h
+++ b/gnome-flashback/libdesktop/gf-icon.h
@@ -33,18 +33,20 @@ typedef enum
#define GF_TYPE_ICON (gf_icon_get_type ())
G_DECLARE_FINAL_TYPE (GfIcon, gf_icon, GF, ICON, GtkButton)
-GtkWidget *gf_icon_new (GFile *file,
- GFileInfo *info);
+GtkWidget *gf_icon_new (GFile *file,
+ GFileInfo *info);
-GFile *gf_icon_get_file (GfIcon *self);
+GFile *gf_icon_get_file (GfIcon *self);
-gboolean gf_icon_is_hidden (GfIcon *self);
+const char *gf_icon_get_name (GfIcon *self);
-void gf_icon_set_selected (GfIcon *self,
- gboolean selected,
- GfIconSelectedFlags flags);
+gboolean gf_icon_is_hidden (GfIcon *self);
-gboolean gf_icon_get_selected (GfIcon *self);
+void gf_icon_set_selected (GfIcon *self,
+ gboolean selected,
+ GfIconSelectedFlags flags);
+
+gboolean gf_icon_get_selected (GfIcon *self);
G_END_DECLS
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 846e7dd..fea8f1f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,6 +21,7 @@ gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.c
gnome-flashback/libautomount-manager/gsd-automount-manager.c
gnome-flashback/libautomount-manager/gsd-autorun.c
gnome-flashback/libbluetooth-applet/gf-bluetooth-applet.c
+gnome-flashback/libdesktop/gf-create-folder-dialog.c
gnome-flashback/libdesktop/gf-icon.c
gnome-flashback/libdesktop/gf-icon-view.c
gnome-flashback/libend-session-dialog/gf-inhibit-dialog.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]