Implement preview support for GTK file dialog

This adds preview support in GTK file dialog implementation,
this is helpful for a lot of applications
like image viewers, messengers and etc.

[ChangeLog][Platform Specific Changes][Linux] A native GTK
file dialog (created via QFileDialog or QtQuick.Dialogs)
now shows an image preview pane.

Task-number: QTBUG-3796
Task-number: QTBUG-53167
Change-Id: Ib80108c09b84d774440a0445adcccab4b64652ef
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
bb10
Ilya Fedin 2021-04-12 10:16:09 +04:00 committed by Shawn Rutledge
parent 71ba53e3a7
commit 4e71603412
2 changed files with 43 additions and 0 deletions

View File

@ -45,6 +45,7 @@
#include <qcolor.h>
#include <qdebug.h>
#include <qfont.h>
#include <qfileinfo.h>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformfontdatabase.h>
@ -55,6 +56,14 @@
#include <gdk/gdkx.h>
#include <pango/pango.h>
// The size of the preview we display for selected image files. We set height
// larger than width because generally there is more free space vertically
// than horiztonally (setting the preview image will alway expand the width of
// the dialog, but usually not the height). The image's aspect ratio will always
// be preserved.
#define PREVIEW_WIDTH 256
#define PREVIEW_HEIGHT 512
QT_BEGIN_NAMESPACE
class QGtk3Dialog : public QWindow
@ -250,6 +259,10 @@ QGtk3FileDialogHelper::QGtk3FileDialogHelper()
g_signal_connect(GTK_FILE_CHOOSER(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "notify::filter", G_CALLBACK(onFilterChanged), this);
previewWidget = gtk_image_new();
g_signal_connect(G_OBJECT(d->gtkDialog()), "update-preview", G_CALLBACK(onUpdatePreview), this);
gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(d->gtkDialog()), previewWidget);
}
QGtk3FileDialogHelper::~QGtk3FileDialogHelper()
@ -390,6 +403,33 @@ void QGtk3FileDialogHelper::onFilterChanged(QGtk3FileDialogHelper *dialog)
emit dialog->filterSelected(dialog->selectedNameFilter());
}
void QGtk3FileDialogHelper::onUpdatePreview(GtkDialog *gtkDialog, QGtk3FileDialogHelper *helper)
{
gchar *filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(gtkDialog));
if (!filename) {
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
return;
}
// Don't attempt to open anything which isn't a regular file. If a named pipe,
// this may hang.
QFileInfo fileinfo(filename);
if (!fileinfo.exists() || !fileinfo.isFile()) {
g_free(filename);
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
return;
}
// This will preserve the image's aspect ratio.
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size(filename, PREVIEW_WIDTH, PREVIEW_HEIGHT, 0);
g_free(filename);
if (pixbuf) {
gtk_image_set_from_pixbuf(GTK_IMAGE(helper->previewWidget), pixbuf);
g_object_unref(pixbuf);
}
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), pixbuf ? true : false);
}
static GtkFileChooserAction gtkFileChooserAction(const QSharedPointer<QFileDialogOptions> &options)
{
switch (options->fileMode()) {

View File

@ -47,6 +47,7 @@
#include <QtCore/qstring.h>
#include <qpa/qplatformdialoghelper.h>
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkDialog GtkDialog;
typedef struct _GtkFileFilter GtkFileFilter;
@ -108,6 +109,7 @@ private:
static void onSelectionChanged(GtkDialog *dialog, QGtk3FileDialogHelper *helper);
static void onCurrentFolderChanged(QGtk3FileDialogHelper *helper);
static void onFilterChanged(QGtk3FileDialogHelper *helper);
static void onUpdatePreview(GtkDialog *dialog, QGtk3FileDialogHelper *helper);
void applyOptions();
void setNameFilters(const QStringList &filters);
void selectFileInternal(const QUrl &filename);
@ -118,6 +120,7 @@ private:
QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtk3Dialog> d;
GtkWidget *previewWidget;
};
class QGtk3FontDialogHelper : public QPlatformFontDialogHelper