diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp index 62e5dd2..ecabee7 100644 --- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,16 @@ QT_BEGIN_NAMESPACE +// GTK file chooser image preview: thanks to Chromium + +// 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 + class QGtk2Dialog : public QWindow { Q_OBJECT @@ -254,12 +265,21 @@ QGtk2FileDialogHelper::QGtk2FileDialogHelper() 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); + + 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); } QGtk2FileDialogHelper::~QGtk2FileDialogHelper() { } +GtkImage *QGtk2FileDialogHelper::previewImage() const +{ + return GTK_IMAGE(previewWidget); +} + bool QGtk2FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { _dir.clear(); @@ -392,6 +412,33 @@ void QGtk2FileDialogHelper::onCurrentFolderChanged(QGtk2FileDialogHelper *dialog emit dialog->directoryEntered(dialog->directory()); } +void QGtk2FileDialogHelper::onUpdatePreview(GtkDialog *gtkDialog, QGtk2FileDialogHelper *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. See https://crbug.com/534754. + 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(helper->previewImage(), pixbuf); + g_object_unref(pixbuf); + } + gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), pixbuf ? true : false); +} + static GtkFileChooserAction gtkFileChooserAction(const QSharedPointer &options) { switch (options->fileMode()) { diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h index 1410566..ef05e38 100644 --- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h +++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h @@ -41,6 +41,8 @@ #include #include +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkImage GtkImage; typedef struct _GtkDialog GtkDialog; typedef struct _GtkFileFilter GtkFileFilter; @@ -82,6 +84,8 @@ public: QGtk2FileDialogHelper(); ~QGtk2FileDialogHelper(); + GtkImage *previewImage() const; + bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE; void exec() Q_DECL_OVERRIDE; void hide() Q_DECL_OVERRIDE; @@ -101,6 +105,7 @@ private Q_SLOTS: private: static void onSelectionChanged(GtkDialog *dialog, QGtk2FileDialogHelper *helper); static void onCurrentFolderChanged(QGtk2FileDialogHelper *helper); + static void onUpdatePreview(GtkDialog *dialog, QGtk2FileDialogHelper *helper); void applyOptions(); void setNameFilters(const QStringList &filters); @@ -109,6 +114,7 @@ private: QHash _filters; QHash _filterNames; QScopedPointer d; + GtkWidget *previewWidget; }; class QGtk2FontDialogHelper : public QPlatformFontDialogHelper