From 05bc48e8f47cc881926ba2b79bd6b0fb1a294c11 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Fri, 5 Dec 2014 14:53:19 +0300 Subject: [PATCH] Make Ctrl+S open save dialog on Gtk backend --- modules/highgui/src/window_gtk.cpp | 97 +++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 4b916e6487..acc0064eb4 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/imgproc.hpp" #ifndef WIN32 @@ -1629,18 +1630,110 @@ CV_IMPL const char* cvGetWindowName( void* window_handle ) return window_name; } +static GtkFileFilter* icvMakeGtkFilter(const char* name, const char* patterns, GtkFileFilter* images) +{ + GtkFileFilter* filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, name); + + while(patterns[0]) + { + gtk_file_filter_add_pattern(filter, patterns); + gtk_file_filter_add_pattern(images, patterns); + patterns += strlen(patterns) + 1; + } + + return filter; +} + +static void icvShowSaveAsDialog(GtkWidget* widget, CvWindow* window) +{ + if (!window || !widget) + return; + + CvImageWidget* image_widget = CV_IMAGE_WIDGET(window->widget); + if (!image_widget || !image_widget->original_image) + return; + + GtkWidget* dialog = gtk_file_chooser_dialog_new("Save As...", + GTK_WINDOW(widget), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); + + cv::String sname = gtk_window_get_title(GTK_WINDOW(window->frame)); + sname = sname.substr(sname.find_last_of("\\/") + 1) + ".png"; + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sname.c_str()); + + GtkFileFilter* filter_all = gtk_file_filter_new(); + gtk_file_filter_set_name(filter_all, "All Files"); + gtk_file_filter_add_pattern(filter_all, "*"); + + GtkFileFilter* filter_images = gtk_file_filter_new(); + gtk_file_filter_set_name(filter_images, "All Images"); + + GtkFileFilter* file_filters[] = { + icvMakeGtkFilter("Portable Network Graphics files (*.png)", "*.png\0", filter_images), + icvMakeGtkFilter("JPEG files (*.jpeg;*.jpg;*.jpe)", "*.jpeg\0*.jpg\0*.jpe\0", filter_images), + icvMakeGtkFilter("Windows bitmap (*.bmp;*.dib)", "*.bmp\0*.dib\0", filter_images), + icvMakeGtkFilter("TIFF Files (*.tiff;*.tif)", "*.tiff\0*.tif\0", filter_images), + icvMakeGtkFilter("JPEG-2000 files (*.jp2)", "*.jp2\0", filter_images), + icvMakeGtkFilter("WebP files (*.webp)", "*.webp\0", filter_images), + icvMakeGtkFilter("Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)", "*.pbm\0*.pgm\0*.ppm\0*.pxm\0*.pnm\0", filter_images), + icvMakeGtkFilter("OpenEXR Image files (*.exr)", "*.exr\0", filter_images), + icvMakeGtkFilter("Radiance HDR (*.hdr;*.pic)", "*.hdr\0*.pic\0", filter_images), + icvMakeGtkFilter("Sun raster files (*.sr;*.ras)", "*.sr\0*.ras\0", filter_images), + filter_images, + filter_all + }; + + for (size_t idx = 0; idx < sizeof(file_filters)/sizeof(file_filters[0]); ++idx) + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filters[idx]); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter_images); + + cv::String filename; + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + char* fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + filename = fname; + g_free(fname); + } + gtk_widget_destroy(dialog); + + if (!filename.empty()) + { + cv::Mat bgr; + cv::cvtColor(cv::cvarrToMat(image_widget->original_image), bgr, cv::COLOR_RGB2BGR); + cv::imwrite(filename, bgr); + } +} + #if defined (GTK_VERSION3) #define GDK_Escape GDK_KEY_Escape #define GDK_Return GDK_KEY_Return #define GDK_Linefeed GDK_KEY_Linefeed #define GDK_Tab GDK_KEY_Tab +#define GDK_s GDK_KEY_s +#define GDK_S GDK_KEY_S #endif //GTK_VERSION3 -static gboolean icvOnKeyPress( GtkWidget * /*widget*/, - GdkEventKey* event, gpointer /*user_data*/ ) +static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer user_data) { int code = 0; + if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S)) + { + try + { + icvShowSaveAsDialog(widget, (CvWindow*)user_data); + } + catch(...) + { + // suppress all exceptions here + } + } + switch( event->keyval ) { case GDK_Escape: