mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
Merge branch 'appdialog' into 'main'
Add GtkAppDialog See merge request GNOME/gtk!5284
This commit is contained in:
commit
e3f805f169
@ -10,6 +10,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *app_picker;
|
||||
|
||||
static void
|
||||
file_opened (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@ -25,12 +27,17 @@ file_opened (GObject *source,
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
name = g_file_get_basename (file);
|
||||
gtk_label_set_label (GTK_LABEL (data), name);
|
||||
g_free (name);
|
||||
|
||||
gtk_widget_set_sensitive (app_picker, TRUE);
|
||||
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -65,6 +72,36 @@ open_file (GtkButton *picker,
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
launch_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileLauncher *launcher = GTK_FILE_LAUNCHER (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gtk_file_launcher_launch_finish (launcher, result, &error))
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
open_app (GtkButton *picker)
|
||||
{
|
||||
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
|
||||
GtkFileLauncher *launcher;
|
||||
GFile *file;
|
||||
|
||||
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
|
||||
gtk_file_launcher_launch (launcher, parent, NULL, launch_done, NULL);
|
||||
|
||||
g_object_unref (launcher);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_pickers (GtkWidget *do_widget)
|
||||
{
|
||||
@ -123,20 +160,17 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_box_append (GTK_BOX (picker), button);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
label = gtk_label_new ("Mail:");
|
||||
label = gtk_label_new ("Application:");
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 4, 1, 1);
|
||||
|
||||
picker = gtk_app_chooser_button_new ("x-scheme-handler/mailto");
|
||||
gtk_app_chooser_button_set_show_dialog_item (GTK_APP_CHOOSER_BUTTON (picker), TRUE);
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 3, 1, 1);
|
||||
app_picker = gtk_button_new_from_icon_name ("emblem-system-symbolic");
|
||||
gtk_widget_set_halign (app_picker, GTK_ALIGN_END);
|
||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
|
||||
gtk_grid_attach (GTK_GRID (table), app_picker, 1, 4, 1, 1);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "gtkalertdialog.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
typedef struct {
|
||||
GtkWindow *parent;
|
||||
GAppLaunchContext *context;
|
||||
@ -96,6 +98,8 @@ window_handle_exported (GtkWindow *window,
|
||||
*
|
||||
* This is the recommended call to be used as it passes information
|
||||
* necessary for sandbox helpers to parent their dialogs properly.
|
||||
*
|
||||
* Deprecated: 4.10: Use [method@Gtk.FileLauncher.launch] instead
|
||||
*/
|
||||
void
|
||||
gtk_show_uri_full (GtkWindow *parent,
|
||||
@ -142,6 +146,8 @@ gtk_show_uri_full (GtkWindow *parent,
|
||||
*
|
||||
* Returns: %TRUE if the URI was shown successfully.
|
||||
* Otherwise, %FALSE is returned and @error is set
|
||||
*
|
||||
* Deprecated: 4.10: Use [method@Gtk.FileLauncher.launch_finish] instead
|
||||
*/
|
||||
gboolean
|
||||
gtk_show_uri_full_finish (GtkWindow *parent,
|
||||
@ -184,6 +190,8 @@ show_uri_done (GObject *object,
|
||||
*
|
||||
* This function launches the default application for showing
|
||||
* a given uri, or shows an error dialog if that fails.
|
||||
*
|
||||
* Deprecated: 4.10: Use [method@Gtk.FileLauncher.launch] instead
|
||||
*/
|
||||
void
|
||||
gtk_show_uri (GtkWindow *parent,
|
@ -29,7 +29,7 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10_FOR(gtk_file_launcher_launch)
|
||||
void gtk_show_uri_full (GtkWindow *parent,
|
||||
const char *uri,
|
||||
guint32 timestamp,
|
||||
@ -37,12 +37,12 @@ void gtk_show_uri_full (GtkWindow *parent,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10_FOR(gtk_file_launcher_launch)
|
||||
gboolean gtk_show_uri_full_finish (GtkWindow *parent,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10_FOR(gtk_file_launcher_launch)
|
||||
void gtk_show_uri (GtkWindow *parent,
|
||||
const char *uri,
|
||||
guint32 timestamp);
|
@ -32,6 +32,7 @@ gtk_deprecated_sources = [
|
||||
'deprecated/gtkinfobar.c',
|
||||
'deprecated/gtkliststore.c',
|
||||
'deprecated/gtkrender.c',
|
||||
'deprecated/gtkshow.c',
|
||||
'deprecated/gtkstylecontext.c',
|
||||
'deprecated/gtktreedatalist.c',
|
||||
'deprecated/gtktreednd.c',
|
||||
@ -88,6 +89,7 @@ gtk_deprecated_headers = [
|
||||
'deprecated/gtkliststore.h',
|
||||
'deprecated/gtkmessagedialog.h',
|
||||
'deprecated/gtkrender.h',
|
||||
'deprecated/gtkshow.h',
|
||||
'deprecated/gtkstylecontext.h',
|
||||
'deprecated/gtktreednd.h',
|
||||
'deprecated/gtktreemodel.h',
|
||||
|
@ -130,6 +130,7 @@
|
||||
#include <gtk/deprecated/gtkfilechooserwidget.h>
|
||||
#include <gtk/gtkfiledialog.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/gtkfilelauncher.h>
|
||||
#include <gtk/gtkfilter.h>
|
||||
#include <gtk/gtkfilterlistmodel.h>
|
||||
#include <gtk/gtkcustomfilter.h>
|
||||
@ -237,7 +238,7 @@
|
||||
#include <gtk/gtkshortcutsshortcut.h>
|
||||
#include <gtk/gtkshortcutswindow.h>
|
||||
#include <gtk/gtkshortcuttrigger.h>
|
||||
#include <gtk/gtkshow.h>
|
||||
#include <gtk/deprecated/gtkshow.h>
|
||||
#include <gtk/gtksignallistitemfactory.h>
|
||||
#include <gtk/gtksingleselection.h>
|
||||
#include <gtk/gtkslicelistmodel.h>
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "gtkorientable.h"
|
||||
#include "gtkscrolledwindow.h"
|
||||
#include "gtktextview.h"
|
||||
#include "gtkshow.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtktogglebutton.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
@ -78,7 +78,7 @@
|
||||
* ![An example GtkAboutDialog](aboutdialog.png)
|
||||
*
|
||||
* About dialogs often contain links and email addresses. `GtkAboutDialog`
|
||||
* displays these as clickable links. By default, it calls [func@Gtk.show_uri]
|
||||
* displays these as clickable links. By default, it calls [method@Gtk.FileLauncher.launch]
|
||||
* when a user clicks one. The behaviour can be overridden with the
|
||||
* [signal@Gtk.AboutDialog::activate-link] signal.
|
||||
*
|
||||
@ -361,7 +361,7 @@ gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
|
||||
* Emitted every time a URL is activated.
|
||||
*
|
||||
* Applications may connect to it to override the default behaviour,
|
||||
* which is to call [func@Gtk.show_uri].
|
||||
* which is to call [method@Gtk.FileLauncher.launch].
|
||||
*
|
||||
* Returns: `TRUE` if the link has been activated
|
||||
*/
|
||||
@ -932,7 +932,17 @@ static gboolean
|
||||
gtk_about_dialog_activate_link (GtkAboutDialog *about,
|
||||
const char *uri)
|
||||
{
|
||||
gtk_show_uri (GTK_WINDOW (about), uri, GDK_CURRENT_TIME);
|
||||
GtkFileLauncher *launcher;
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
|
||||
gtk_file_launcher_launch (launcher, GTK_WINDOW (about), NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (launcher);
|
||||
g_object_unref (file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
||||
#include "gtkcheckbutton.h"
|
||||
#include "gtkwindowgroup.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gtkshow.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkscrollable.h"
|
||||
#include "gtkpopover.h"
|
||||
@ -1370,68 +1370,14 @@ open_folder_cb (GSimpleAction *action,
|
||||
GtkWindow *toplevel = GTK_IS_WINDOW (root) ? GTK_WINDOW (root) : NULL;
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
char *uri;
|
||||
GtkFileLauncher *launcher;
|
||||
|
||||
info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), impl->browse_files_popover_item);
|
||||
file = _gtk_file_info_get_file (info);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
gtk_show_uri (toplevel, uri, GDK_CURRENT_TIME);
|
||||
g_free (uri);
|
||||
|
||||
#else
|
||||
|
||||
if (gdk_should_use_portal ())
|
||||
{
|
||||
g_openuri_portal_open_async (file, TRUE, toplevel, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
GDBusConnection *bus;
|
||||
GVariantBuilder uris_builder;
|
||||
GVariant *result;
|
||||
GError *error = NULL;
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
||||
|
||||
g_variant_builder_init (&uris_builder, G_VARIANT_TYPE ("as"));
|
||||
g_variant_builder_add (&uris_builder, "s", uri);
|
||||
|
||||
result = g_dbus_connection_call_sync (bus,
|
||||
FILE_MANAGER_DBUS_NAME,
|
||||
FILE_MANAGER_DBUS_PATH,
|
||||
FILE_MANAGER_DBUS_IFACE,
|
||||
"ShowFolders",
|
||||
g_variant_new ("(ass)", &uris_builder, ""),
|
||||
NULL, /* ignore returned type */
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER) ||
|
||||
g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
|
||||
g_debug ("No " FILE_MANAGER_DBUS_NAME " available");
|
||||
else
|
||||
g_warning ("Failed to call ShowFolders: %s", error->message);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
if (result)
|
||||
g_variant_unref (result);
|
||||
else
|
||||
gtk_show_uri (toplevel, uri, GDK_CURRENT_TIME);
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
#endif
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
gtk_file_launcher_open_containing_folder (launcher, toplevel, NULL, NULL, NULL);
|
||||
g_object_unref (launcher);
|
||||
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
502
gtk/gtkfilelauncher.c
Normal file
502
gtk/gtkfilelauncher.c
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfilelauncher.h"
|
||||
|
||||
#include "gtkdialogerror.h"
|
||||
#include "gopenuriportal.h"
|
||||
#include "deprecated/gtkshow.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GtkFileLauncher:
|
||||
*
|
||||
* A `GtkFileLauncher` object collects the arguments that are needed to open a uri
|
||||
* with an application.
|
||||
*
|
||||
* Depending on system configuration, user preferences and available APIs, this
|
||||
* may or may not show an app chooser dialog or launch the default application
|
||||
* right away.
|
||||
*
|
||||
* The operation is started with the [method@Gtk.FileLauncher.launch] function.
|
||||
* This API follows the GIO async pattern, and the result can be obtained by
|
||||
* calling [method@Gtk.FileLauncher.launch_finish].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkFileLauncher
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GFile *file;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_FILE = 1,
|
||||
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkFileLauncher, gtk_file_launcher, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_file_launcher_init (GtkFileLauncher *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_launcher_finalize (GObject *object)
|
||||
{
|
||||
//GtkFileLauncher *self = GTK_FILE_LAUNCHER (object);
|
||||
|
||||
G_OBJECT_CLASS (gtk_file_launcher_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_launcher_get_property (GObject *object,
|
||||
unsigned int property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileLauncher *self = GTK_FILE_LAUNCHER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, self->file);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_launcher_set_property (GObject *object,
|
||||
unsigned int property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileLauncher *self = GTK_FILE_LAUNCHER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
gtk_file_launcher_set_file (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_launcher_class_init (GtkFileLauncherClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_file_launcher_finalize;
|
||||
object_class->get_property = gtk_file_launcher_get_property;
|
||||
object_class->set_property = gtk_file_launcher_set_property;
|
||||
|
||||
/**
|
||||
* GtkFileLauncher:file: (attributes org.gtk.Property.get=gtk_file_launcher_get_file org.gtk.Property.set=gtk_file_launcher_set_file)
|
||||
*
|
||||
* The file to launch.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_FILE] =
|
||||
g_param_spec_object ("file", NULL, NULL,
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ API: Constructor */
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_new:
|
||||
* @file: (nullable): the file to open
|
||||
*
|
||||
* Creates a new `GtkFileLauncher` object.
|
||||
*
|
||||
* Returns: the new `GtkFileLauncher`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkFileLauncher *
|
||||
gtk_file_launcher_new (GFile *file)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILE_LAUNCHER,
|
||||
"file", file,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ API: Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_get_file:
|
||||
* @self: a `GtkFileLauncher`
|
||||
*
|
||||
* Gets the file that will be opened.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the file
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GFile *
|
||||
gtk_file_launcher_get_file (GtkFileLauncher *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_LAUNCHER (self), NULL);
|
||||
|
||||
return self->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_set_file:
|
||||
* @self: a `GtkFileLauncher`
|
||||
* @file: a `GFile`
|
||||
*
|
||||
* Sets the file that will be opened.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_launcher_set_file (GtkFileLauncher *self,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_LAUNCHER (self));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
|
||||
if (!g_set_object (&self->file, file))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async implementation */
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
static void
|
||||
open_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GTask *task = G_TASK (data);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_openuri_portal_open_finish (result, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
show_folder_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GDBusConnection *bus = G_DBUS_CONNECTION (source);
|
||||
GTask *task = G_TASK (data);
|
||||
GVariant *res;
|
||||
GError *error = NULL;
|
||||
|
||||
res = g_dbus_connection_call_finish (bus, result, &error);
|
||||
if (res)
|
||||
g_variant_unref (res);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_CANCELLED, "Cancelled by user");
|
||||
else
|
||||
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED, "%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
#define FILE_MANAGER_DBUS_NAME "org.freedesktop.FileManager1"
|
||||
#define FILE_MANAGER_DBUS_IFACE "org.freedesktop.FileManager1"
|
||||
#define FILE_MANAGER_DBUS_PATH "/org/freedesktop/FileManager1"
|
||||
|
||||
static void
|
||||
show_folder (GtkWindow *parent,
|
||||
const char *uri,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDBusConnection *bus;
|
||||
GVariantBuilder uris_builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_STRING_ARRAY);
|
||||
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
||||
|
||||
if (!bus)
|
||||
{
|
||||
g_task_return_new_error (G_TASK (user_data),
|
||||
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
|
||||
"Session bus not available");
|
||||
g_object_unref (G_TASK (user_data));
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_builder_add (&uris_builder, "s", uri);
|
||||
|
||||
g_dbus_connection_call (bus,
|
||||
FILE_MANAGER_DBUS_NAME,
|
||||
FILE_MANAGER_DBUS_PATH,
|
||||
FILE_MANAGER_DBUS_IFACE,
|
||||
"ShowFolders",
|
||||
g_variant_new ("(ass)", &uris_builder, ""),
|
||||
NULL, /* ignore returned type */
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
show_folder_done,
|
||||
user_data);
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
static void
|
||||
show_uri_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWindow *parent = GTK_WINDOW (source);
|
||||
GTask *task = G_TASK (data);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gtk_show_uri_full_finish (parent, result, &error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_CANCELLED, "Cancelled by user");
|
||||
else
|
||||
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED, "%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async API */
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_launch:
|
||||
* @self: a `GtkFileLauncher`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* Launch an application to open the file.
|
||||
*
|
||||
* This may present an app chooser dialog to the user.
|
||||
*
|
||||
* The @callback will be called when the operation is completed.
|
||||
* It should call [method@Gtk.FileLauncher.launch_finish] to obtain
|
||||
* the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_launcher_launch (GtkFileLauncher *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_LAUNCHER (self));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_check_cancellable (task, FALSE);
|
||||
g_task_set_source_tag (task, gtk_file_launcher_launch);
|
||||
|
||||
if (self->file == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
|
||||
"No file to launch");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (g_openuri_portal_is_available ())
|
||||
{
|
||||
g_openuri_portal_open_async (self->file, FALSE, parent, cancellable, open_done, task);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char *uri = g_file_get_uri (self->file);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gtk_show_uri_full (parent, uri, GDK_CURRENT_TIME, cancellable, show_uri_done, task);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_launch_finish:
|
||||
* @self: a `GtkFileLauncher`
|
||||
* @result: a `GAsyncResult`
|
||||
* @error: return location for a [enum@Gtk.DialogError] or [enum@Gio.Error] error
|
||||
*
|
||||
* Finishes the [method@Gtk.FileLauncher.launch] call and
|
||||
* returns the result.
|
||||
*
|
||||
* Returns: `TRUE` if an application was launched,
|
||||
* or `FALSE` and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_launcher_launch_finish (GtkFileLauncher *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_LAUNCHER (self), FALSE);
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_file_launcher_launch, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_open_containing_folder:
|
||||
* @self: a `GtkFileLauncher`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* Launch a file manager to show the file in its parent directory.
|
||||
*
|
||||
* This is only supported native files. It will fail if @file
|
||||
* is e.g. a http:// uri.
|
||||
*
|
||||
* The @callback will be called when the operation is completed.
|
||||
* It should call [method@Gtk.FileLauncher.open_containing_folder_finish]
|
||||
* to obtain the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_LAUNCHER (self));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_check_cancellable (task, FALSE);
|
||||
g_task_set_source_tag (task, gtk_file_launcher_open_containing_folder);
|
||||
|
||||
if (self->file == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
|
||||
"No file to open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_file_is_native (self->file))
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
|
||||
"Operation not supported on non-native files");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (g_openuri_portal_is_available ())
|
||||
{
|
||||
g_openuri_portal_open_async (self->file, TRUE, parent, cancellable, open_done, task);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char *uri = g_file_get_uri (self->file);
|
||||
|
||||
show_folder (parent, uri, cancellable, show_folder_done, task);
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_launcher_open_containing_folder_finish:
|
||||
* @self: a `GtkFileLauncher`
|
||||
* @result: a `GAsyncResult`
|
||||
* @error: return location for a [enum@Gtk.DialogError] or [enum@Gio.Error] error
|
||||
*
|
||||
* Finishes the [method@Gtk.FileLauncher.open_containing_folder]
|
||||
* call and returns the result.
|
||||
*
|
||||
* Returns: `TRUE` if an application was launched,
|
||||
* or `FALSE` and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_launcher_open_containing_folder_finish (GtkFileLauncher *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_LAUNCHER (self), FALSE);
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_file_launcher_open_containing_folder, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* vim:set foldmethod=marker expandtab: */
|
68
gtk/gtkfilelauncher.h
Normal file
68
gtk/gtkfilelauncher.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_LAUNCHER (gtk_file_launcher_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkFileLauncher, gtk_file_launcher, GTK, FILE_LAUNCHER, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkFileLauncher * gtk_file_launcher_new (GFile *file);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GFile * gtk_file_launcher_get_file (GtkFileLauncher *self);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_launcher_set_file (GtkFileLauncher *self,
|
||||
GFile *file);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_launcher_launch (GtkFileLauncher *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_launcher_launch_finish (GtkFileLauncher *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_launcher_open_containing_folder_finish (GtkFileLauncher *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
@ -40,7 +40,7 @@
|
||||
#include "gtkshortcut.h"
|
||||
#include "gtkshortcutcontroller.h"
|
||||
#include "gtkshortcuttrigger.h"
|
||||
#include "gtkshow.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkrenderbackgroundprivate.h"
|
||||
#include "gtkrenderborderprivate.h"
|
||||
@ -2102,11 +2102,17 @@ gtk_label_activate_link (GtkLabel *self,
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
|
||||
GFile *file;
|
||||
GtkFileLauncher *launcher;
|
||||
|
||||
if (!GTK_IS_WINDOW (toplevel))
|
||||
return FALSE;
|
||||
|
||||
gtk_show_uri (GTK_WINDOW (toplevel), uri, GDK_CURRENT_TIME);
|
||||
file = g_file_new_for_uri (uri);
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
gtk_file_launcher_launch (launcher, GTK_WINDOW (toplevel), NULL, NULL, NULL);
|
||||
g_object_unref (launcher);
|
||||
g_object_unref (file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2281,7 +2287,7 @@ gtk_label_class_init (GtkLabelClass *class)
|
||||
* Gets emitted to activate a URI.
|
||||
*
|
||||
* Applications may connect to it to override the default behaviour,
|
||||
* which is to call gtk_show_uri().
|
||||
* which is to call [method@Gtk.FileLauncher.launch].
|
||||
*
|
||||
* Returns: %TRUE if the link has been activated
|
||||
*/
|
||||
|
@ -37,7 +37,7 @@
|
||||
* The URI bound to a `GtkLinkButton` can be set specifically using
|
||||
* [method@Gtk.LinkButton.set_uri].
|
||||
*
|
||||
* By default, `GtkLinkButton` calls [func@Gtk.show_uri] when the button
|
||||
* By default, `GtkLinkButton` calls [method@Gtk.FileLauncher.launch] when the button
|
||||
* is clicked. This behaviour can be overridden by connecting to the
|
||||
* [signal@Gtk.LinkButton::activate-link] signal and returning %TRUE from
|
||||
* the signal handler.
|
||||
@ -65,7 +65,7 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkpopovermenu.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkshow.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtktooltip.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
@ -198,7 +198,7 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
|
||||
*
|
||||
* Emitted each time the `GtkLinkButton` is clicked.
|
||||
*
|
||||
* The default handler will call [func@Gtk.show_uri] with the URI
|
||||
* The default handler will call [method@Gtk.FileLauncher.launch] with the URI
|
||||
* stored inside the [property@Gtk.LinkButton:uri] property.
|
||||
*
|
||||
* To override the default behavior, you can connect to the
|
||||
@ -479,10 +479,17 @@ static gboolean
|
||||
gtk_link_button_activate_link (GtkLinkButton *link_button)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GFile *file;
|
||||
GtkFileLauncher *launcher;
|
||||
|
||||
toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (link_button)));
|
||||
|
||||
gtk_show_uri (GTK_WINDOW (toplevel), link_button->uri, GDK_CURRENT_TIME);
|
||||
file = g_file_new_for_uri (link_button->uri);
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
gtk_file_launcher_launch (launcher, GTK_WINDOW (toplevel), NULL, NULL, NULL);
|
||||
g_object_unref (launcher);
|
||||
g_object_unref (file);
|
||||
|
||||
gtk_link_button_set_visited (link_button, TRUE);
|
||||
|
||||
return TRUE;
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "gtkprintsettings.h"
|
||||
#include "gtkpagesetup.h"
|
||||
#include "gtkprintbackendprivate.h"
|
||||
#include "gtkshow.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
@ -677,9 +677,12 @@ gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
|
||||
GtkWindow *parent,
|
||||
const char *filename)
|
||||
{
|
||||
char *uri;
|
||||
GFile *file;
|
||||
GtkFileLauncher *launcher;
|
||||
|
||||
uri = g_filename_to_uri (filename, NULL, NULL);
|
||||
gtk_show_uri (parent, uri, GDK_CURRENT_TIME);
|
||||
g_free (uri);
|
||||
file = g_file_new_for_path (filename);
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
|
||||
g_object_unref (launcher);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "gtkprinter.h"
|
||||
#include "gtkprintjob.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkfilelauncher.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
|
||||
@ -304,15 +305,17 @@ gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
char * uri;
|
||||
GFile *file;
|
||||
GtkFileLauncher *launcher;
|
||||
|
||||
g_warning ("Error launching preview: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
uri = g_filename_to_uri (filename, NULL, NULL);
|
||||
gtk_show_uri (parent, uri, GDK_CURRENT_TIME);
|
||||
g_free (uri);
|
||||
file = g_file_new_for_path (filename);
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
|
||||
g_object_unref (launcher);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -227,6 +227,7 @@ gtk_public_sources = files([
|
||||
'gtkfilechooserwidget.c',
|
||||
'gtkfiledialog.c',
|
||||
'gtkfilefilter.c',
|
||||
'gtkfilelauncher.c',
|
||||
'gtkfilter.c',
|
||||
'gtkfilterlistmodel.c',
|
||||
'gtkfixed.c',
|
||||
@ -345,7 +346,6 @@ gtk_public_sources = files([
|
||||
'gtkshortcutsshortcut.c',
|
||||
'gtkshortcutswindow.c',
|
||||
'gtkshortcuttrigger.c',
|
||||
'gtkshow.c',
|
||||
'gtksidebarrow.c',
|
||||
'gtksignallistitemfactory.c',
|
||||
'gtksingleselection.c',
|
||||
@ -478,6 +478,7 @@ gtk_public_headers = files([
|
||||
'gtkexpression.h',
|
||||
'gtkfiledialog.h',
|
||||
'gtkfilefilter.h',
|
||||
'gtkfilelauncher.h',
|
||||
'gtkfilter.h',
|
||||
'gtkfilterlistmodel.h',
|
||||
'gtkfixed.h',
|
||||
@ -578,7 +579,6 @@ gtk_public_headers = files([
|
||||
'gtkshortcutsshortcut.h',
|
||||
'gtkshortcutswindow.h',
|
||||
'gtkshortcuttrigger.h',
|
||||
'gtkshow.h',
|
||||
'gtksignallistitemfactory.h',
|
||||
'gtksingleselection.h',
|
||||
'gtksizegroup.h',
|
||||
|
@ -88,6 +88,7 @@ gtk/deprecated/gtkfontbutton.c
|
||||
gtk/deprecated/gtkfontchooser.c
|
||||
gtk/deprecated/gtkiconview.c
|
||||
gtk/deprecated/gtkliststore.c
|
||||
gtk/deprecated/gtkshow.c
|
||||
gtk/deprecated/gtkstylecontext.c
|
||||
gtk/deprecated/gtktreednd.c
|
||||
gtk/deprecated/gtktreemodel.c
|
||||
@ -177,6 +178,7 @@ gtk/gtkfilechooserutils.c
|
||||
gtk/gtkfilechooserwidget.c
|
||||
gtk/gtkfiledialog.c
|
||||
gtk/gtkfilefilter.c
|
||||
gtk/gtkfilelauncher.c
|
||||
gtk/gtkfilesystemmodel.c
|
||||
gtk/gtkfilethumbnail.c
|
||||
gtk/gtkfilter.c
|
||||
@ -298,7 +300,6 @@ gtk/gtkshortcutssection.c
|
||||
gtk/gtkshortcutsshortcut.c
|
||||
gtk/gtkshortcutswindow.c
|
||||
gtk/gtkshortcuttrigger.c
|
||||
gtk/gtkshow.c
|
||||
gtk/gtksidebarrow.c
|
||||
gtk/gtksignallistitemfactory.c
|
||||
gtk/gtksingleselection.c
|
||||
|
Loading…
Reference in New Issue
Block a user