diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp index 62e5dd2..3e609f7 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 @@ -70,18 +81,24 @@ Q_SIGNALS: protected: static void onResponse(QGtk2Dialog *dialog, int response); + static void onUpdatePreview(QGtk2Dialog *dialog); private slots: void onParentWindowDestroyed(); private: GtkWidget *gtkWidget; + GtkWidget *previewWidget; }; QGtk2Dialog::QGtk2Dialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) { g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this); g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); + + previewWidget = gtk_image_new(); + g_signal_connect_swapped(G_OBJECT(gtkWidget), "update-preview", G_CALLBACK(onUpdatePreview), this); + gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(gtkWidget), previewWidget); } QGtk2Dialog::~QGtk2Dialog() @@ -151,6 +168,32 @@ void QGtk2Dialog::onResponse(QGtk2Dialog *dialog, int response) emit dialog->reject(); } +void QGtk2Dialog::onUpdatePreview(QGtk2Dialog *dialog) { + gchar *filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(dialog->gtkWidget)); + if (!filename) { + gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(dialog->gtkWidget), 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(dialog->gtkWidget), 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(dialog->previewWidget), pixbuf); + g_object_unref(pixbuf); + } + gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(dialog->gtkWidget), pixbuf ? true : false); +} + void QGtk2Dialog::onParentWindowDestroyed() { // The QGtk2*DialogHelper classes own this object. Make sure the parent doesn't delete it.