diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6d49dfab5..8f40c6979 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -187,7 +187,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } } - if (((todo & ALL) == ALL) || panningRelatedChange || (highDetailNeeded && options.prevdemo != PD_Sidecar)) { + if (((todo & ALL) == ALL) || (todo & M_MONITOR) || panningRelatedChange || (highDetailNeeded && options.prevdemo != PD_Sidecar)) { bwAutoR = bwAutoG = bwAutoB = -9000.f; if (todo == CROP && ipf.needsPCVignetting()) { @@ -1022,11 +1022,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) // process crop, if needed for (size_t i = 0; i < crops.size(); i++) - if (crops[i]->hasListener() && (panningRelatedChange || crops[i]->get_skip() == 1)) { + if (crops[i]->hasListener() && (panningRelatedChange || (todo & M_MONITOR) || crops[i]->get_skip() == 1)) { crops[i]->update(todo); // may call ourselves } - if (panningRelatedChange) { + if (panningRelatedChange || (todo & M_MONITOR)) { progress("Conversion to RGB...", 100 * readyphase / numofphases); if ((todo != CROP && todo != MINUPDATE) || (todo & M_MONITOR)) { @@ -1575,7 +1575,6 @@ void ImProcCoordinator::process() || params.raw != nextParams.raw || params.retinex != nextParams.retinex || params.wavelet != nextParams.wavelet - || params.dirpyrequalizer != nextParams.dirpyrequalizer; params = nextParams; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 1a9e08b94..b73fb2f6f 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -363,15 +363,12 @@ void BatchQueuePanel::pathFolderButtonPressed () // since these settings are shared with editorpanel : void BatchQueuePanel::pathFolderChanged () { - options.savePathFolder = outdirFolder->get_filename(); } -void BatchQueuePanel::formatChanged (Glib::ustring f) +void BatchQueuePanel::formatChanged(const Glib::ustring& format) { - - options.saveFormatBatch = saveFormatPanel->getFormat (); - + options.saveFormatBatch = saveFormatPanel->getFormat(); } bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 497bc166e..d765e23dc 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -72,7 +72,7 @@ public: void saveOptions (); void pathFolderChanged (); void pathFolderButtonPressed (); - void formatChanged (Glib::ustring f); + void formatChanged(const Glib::ustring& format) override; void updateTab (int qsize, int forceOrientation = 0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical bool handleShortcutKey (GdkEventKey* event); diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 69d7a98b4..374b755ae 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -267,15 +267,22 @@ void CropWindow::flawnOver (bool isFlawnOver) this->isFlawnOver = isFlawnOver; } -void CropWindow::scroll (int state, GdkScrollDirection direction, int x, int y) +void CropWindow::scroll (int state, GdkScrollDirection direction, int x, int y, double deltaX, double deltaY) { + double delta = 0.0; + if (abs(deltaX) > abs(deltaY)) { + delta = deltaX; + } else { + delta = deltaY; + } + bool isUp = direction == GDK_SCROLL_UP || (direction == GDK_SCROLL_SMOOTH && delta < 0.0); if ((state & GDK_CONTROL_MASK) && onArea(ColorPicker, x, y)) { // resizing a color picker - if (direction == GDK_SCROLL_UP) { + if (isUp) { hoveredPicker->incSize(); updateHoveredPicker(); iarea->redraw (); - }else if (direction == GDK_SCROLL_DOWN) { + } else { hoveredPicker->decSize(); updateHoveredPicker(); iarea->redraw (); @@ -287,9 +294,9 @@ void CropWindow::scroll (int state, GdkScrollDirection direction, int x, int y) screenCoordToImage(newCenterX, newCenterY, newCenterX, newCenterY); - if (direction == GDK_SCROLL_UP && !isMaxZoom()) { + if (isUp && !isMaxZoom()) { zoomIn (true, newCenterX, newCenterY); - } else if (direction == GDK_SCROLL_DOWN && !isMinZoom()) { + } else if (!isUp && !isMinZoom()) { zoomOut (true, newCenterX, newCenterY); } } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index 9f0dfb7f4..66f9b9097 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -187,7 +187,7 @@ public: bool isInside (int x, int y); - void scroll (int state, GdkScrollDirection direction, int x, int y); + void scroll (int state, GdkScrollDirection direction, int x, int y, double deltaX=0.0, double deltaY=0.0); void buttonPress (int button, int num, int state, int x, int y); void buttonRelease (int button, int num, int state, int x, int y); void pointerMoved (int bstate, int x, int y); diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 980b94765..a2b38760b 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -945,6 +945,9 @@ bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) double step = adjust->get_step_increment(); double value2 = 0.; + printf("MyScrolledwindow::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); + if (event->direction == GDK_SCROLL_DOWN) { value2 = value + step; @@ -962,6 +965,13 @@ bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) value2 = lower; } + if (value2 != value) { + scroll->set_value(value2); + } + } else if (event->direction == GDK_SCROLL_SMOOTH) { + if (abs(event->delta_y) > 0.1) { + value2 = rtengine::LIM(value + (event->delta_y > 0 ? step : -step), lower, upper); + } if (value2 != value) { scroll->set_value(value2); } @@ -1010,6 +1020,9 @@ bool MyScrolledToolbar::on_scroll_event (GdkEventScroll* event) double step = adjust->get_step_increment() * 2; double value2 = 0.; + printf("MyScrolledToolbar::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); + if (event->direction == GDK_SCROLL_DOWN) { value2 = rtengine::min(value + step, upper); if (value2 != value) { @@ -1057,11 +1070,14 @@ MyComboBoxText::MyComboBoxText (bool has_entry) : Gtk::ComboBoxText(has_entry) minimumWidth = naturalWidth = 70; Gtk::CellRendererText* cellRenderer = dynamic_cast(get_first_cell()); cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE; + add_events(Gdk::SCROLL_MASK|Gdk::SMOOTH_SCROLL_MASK); } bool MyComboBoxText::on_scroll_event (GdkEventScroll* event) { + printf("MyComboboxText::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::ComboBoxText::on_scroll_event(event); @@ -1219,6 +1235,8 @@ bool MySpinButton::on_scroll_event (GdkEventScroll* event) bool MyHScale::on_scroll_event (GdkEventScroll* event) { + printf("MyHScale::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::HScale::on_scroll_event(event); @@ -1343,7 +1361,7 @@ void MyFileChooserButton::set_filter(const Glib::RefPtr &filter { cur_filter_ = filter; } - + std::vector> MyFileChooserButton::list_filters() { diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index b2b938139..cd148acff 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -77,7 +77,7 @@ void ImageArea::on_realize() // This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3 add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); #else - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); #endif Cairo::FontOptions cfo; @@ -302,9 +302,12 @@ bool ImageArea::on_button_press_event (GdkEventButton* event) bool ImageArea::on_scroll_event (GdkEventScroll* event) { + printf("ImageArea::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); + CropWindow* cw = getCropWindow (event->x, event->y); if (cw) { - cw->scroll (event->state, event->direction, event->x, event->y); + cw->scroll (event->state, event->direction, event->x, event->y, event->delta_x, event->delta_y); } return true; diff --git a/rtgui/options.cc b/rtgui/options.cc index c0a9e06bc..1444fffc0 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -1354,17 +1354,10 @@ void Options::readFromFile(Glib::ustring fname) FileBrowserToolbarSingleRow = keyFile.get_boolean ("GUI", "FileBrowserToolbarSingleRow"); } -#if defined(__linux__) && ((GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION > 18) || GTK_MAJOR_VERSION > 3) - // Cannot scroll toolbox with mousewheel when HideTPVScrollbar=true #3413 - hideTPVScrollbar = false; -#else - if (keyFile.has_key("GUI", "HideTPVScrollbar")) { hideTPVScrollbar = keyFile.get_boolean("GUI", "HideTPVScrollbar"); } -#endif - if (keyFile.has_key("GUI", "HistogramWorking")) { rtSettings.HistogramWorking = keyFile.get_boolean("GUI", "HistogramWorking"); } diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index f00d2f1c1..6f651a4a8 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -932,11 +932,6 @@ Gtk::Widget* Preferences::getGeneralPanel() setExpandAlignProperties(hb4label, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); ckbHideTPVScrollbar = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_TP_VSCROLLBAR"))); setExpandAlignProperties(ckbHideTPVScrollbar, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); -#if defined(__linux__) && ((GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION > 18) || GTK_MAJOR_VERSION > 3) - // Cannot scroll toolbox with mousewheel when HideTPVScrollbar=true #3413 - ckbHideTPVScrollbar->set_active(false); - ckbHideTPVScrollbar->set_sensitive(false); -#endif workflowGrid->attach_next_to(*hb4label, *ckbFileBrowserToolbarSingleRow, Gtk::POS_BOTTOM, 1, 1); workflowGrid->attach_next_to(*ckbHideTPVScrollbar, *hb4label, Gtk::POS_RIGHT, 1, 1); ckbAutoSaveTpOpen = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_AUTOSAVE_TP_OPEN"))); diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index 5c7cce997..f9dba53ac 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -34,7 +34,7 @@ void PreviewWindow::on_realize () { Gtk::DrawingArea::on_realize (); - add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); } void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index 7067e8ed1..f2a7206b9 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -16,15 +16,36 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include + #include "saveasdlg.h" -#include "multilangmgr.h" + #include "guiutils.h" +#include "multilangmgr.h" #include "rtimage.h" #include "../rtengine/utils.h" extern Options options; +namespace +{ + +Glib::ustring getCurrentFilename(const Gtk::FileChooserWidget* fchooser) +{ + Glib::ustring res = fchooser->get_filename(); + + // NB: There seem to be a bug in Gtkmm2.22 / FileChooserWidget : if you suppress the filename entry and + // click on a folder in the list, the filename field is empty but get_filename will return the folder's path :/ + if (Glib::file_test(res, Glib::FILE_TEST_IS_DIR)) { + res = fchooser->get_current_name(); + } + + return res; +} + +} + SaveAsDialog::SaveAsDialog (const Glib::ustring &initialDir, Gtk::Window* parent) : Gtk::Dialog (M("GENERAL_SAVE"), *parent) { @@ -219,13 +240,7 @@ SaveFormat SaveAsDialog::getFormat () void SaveAsDialog::okPressed () { - fname = fchooser->get_filename(); - - // NB: There seem to be a bug in Gtkmm2.22 / FileChooserWidget : if you suppress the filename entry and - // click on a folder in the list, the filename field is empty but get_filename will return the folder's path :/ - if (Glib::file_test(fname, Glib::FILE_TEST_IS_DIR)) { - fname = fchooser->get_current_name(); - } + fname = getCurrentFilename(fchooser); // Checking if the filename field is empty. The user have to click Cancel if he don't want to specify a filename if (fname.empty()) { @@ -246,9 +261,18 @@ void SaveAsDialog::okPressed () // Extension is either empty or unfamiliar fname += '.' + formatOpts->getFormat().format; } else if ( - !rtengine::hasJpegExtension(fname) - && !rtengine::hasTiffExtension(fname) - && !rtengine::hasPngExtension(fname) + ( + formatOpts->getFormat().format == "jpg" + && !rtengine::hasJpegExtension(fname) + ) + || ( + formatOpts->getFormat().format == "tif" + && !rtengine::hasTiffExtension(fname) + ) + || ( + formatOpts->getFormat().format == "png" + && !rtengine::hasPngExtension(fname) + ) ) { // Create dialog to warn user that the filename may have two extensions on the end Gtk::MessageDialog msgd( @@ -283,15 +307,42 @@ void SaveAsDialog::cancelPressed () response (Gtk::RESPONSE_CANCEL); } -void SaveAsDialog::formatChanged (Glib::ustring f) +void SaveAsDialog::formatChanged(const Glib::ustring& format) { + const auto sanitize_suffix = + [this, format](const std::function& has_suffix) + { + const Glib::ustring name = getCurrentFilename(fchooser); - if (f == "jpg") { + if (!has_suffix(name)) { + fchooser->set_current_name(removeExtension(Glib::path_get_basename(name)) + '.' + format); + } + }; + + if (format == "jpg") { fchooser->set_filter (filter_jpg); - } else if (f == "png") { + sanitize_suffix( + [](const Glib::ustring& filename) + { + return rtengine::hasJpegExtension(filename); + } + ); + } else if (format == "png") { fchooser->set_filter (filter_png); - } else if (f == "tif") { + sanitize_suffix( + [](const Glib::ustring& filename) + { + return rtengine::hasPngExtension(filename); + } + ); + } else if (format == "tif") { fchooser->set_filter (filter_tif); + sanitize_suffix( + [](const Glib::ustring& filename) + { + return rtengine::hasTiffExtension(filename); + } + ); } } diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 073be23f4..e02be340f 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -62,7 +62,7 @@ public: void okPressed (); void cancelPressed (); - void formatChanged (Glib::ustring f); + void formatChanged(const Glib::ustring& format) override; bool keyPressed (GdkEventKey* event); }; diff --git a/rtgui/saveformatpanel.h b/rtgui/saveformatpanel.h index 47011be18..7c4dbf33f 100644 --- a/rtgui/saveformatpanel.h +++ b/rtgui/saveformatpanel.h @@ -28,8 +28,8 @@ class FormatChangeListener { public: - virtual ~FormatChangeListener () {} - virtual void formatChanged (Glib::ustring f) {} + virtual ~FormatChangeListener() = default; + virtual void formatChanged(const Glib::ustring& format) = 0; }; class SaveFormatPanel : public Gtk::Grid, public AdjusterListener diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index 829aec9f7..814c3e53e 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -68,26 +68,59 @@ void ThumbBrowserBase::scrollChanged () } } -void ThumbBrowserBase::scroll (int direction) +void ThumbBrowserBase::scroll (int direction, double deltaX, double deltaY) { + double delta = 0.0; + if (abs(deltaX) > abs(deltaY)) { + delta = deltaX; + } else { + delta = deltaY; + } + double coef = direction == GDK_SCROLL_DOWN || (direction == GDK_SCROLL_SMOOTH && delta > 0.0) ? +1.0 : -1.0; + // GUI already acquired when here - if (direction == GDK_SCROLL_UP || direction == GDK_SCROLL_DOWN) { + if (direction == GDK_SCROLL_UP || direction == GDK_SCROLL_DOWN || direction == GDK_SCROLL_SMOOTH) { if (arrangement == TB_Vertical) { - vscroll.set_value (vscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_step_increment()); + double currValue = vscroll.get_value(); + double newValue = rtengine::LIM(currValue + coef * vscroll.get_adjustment()->get_step_increment(), + vscroll.get_adjustment()->get_lower (), + vscroll.get_adjustment()->get_upper()); + if (newValue != currValue) { + vscroll.set_value (newValue); + } } else { - hscroll.set_value (hscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_step_increment()); + double currValue = hscroll.get_value(); + double newValue = rtengine::LIM(currValue + coef * hscroll.get_adjustment()->get_step_increment(), + hscroll.get_adjustment()->get_lower(), + hscroll.get_adjustment()->get_upper()); + if (newValue != currValue) { + hscroll.set_value (newValue); + } } } } void ThumbBrowserBase::scrollPage (int direction) { + // GUI already acquired when here // GUI already acquired when here if (direction == GDK_SCROLL_UP || direction == GDK_SCROLL_DOWN) { if (arrangement == TB_Vertical) { - vscroll.set_value (vscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment()); + double currValue = vscroll.get_value(); + double newValue = rtengine::LIM(currValue + (direction == GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment(), + vscroll.get_adjustment()->get_lower(), + vscroll.get_adjustment()->get_upper()); + if (newValue != currValue) { + vscroll.set_value (newValue); + } } else { - hscroll.set_value (hscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_page_increment()); + double currValue = hscroll.get_value(); + double newValue = rtengine::LIM(currValue + (direction == GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_page_increment(), + hscroll.get_adjustment()->get_lower(), + hscroll.get_adjustment()->get_upper()); + if (newValue != currValue) { + hscroll.set_value (newValue); + } } } } @@ -682,7 +715,7 @@ void ThumbBrowserBase::Internal::on_realize() bgs = style->get_background_color(Gtk::STATE_FLAG_SELECTED); set_can_focus(true); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK | Gdk::KEY_PRESS_MASK); set_has_tooltip (true); signal_query_tooltip().connect( sigc::mem_fun(*this, &ThumbBrowserBase::Internal::on_query_tooltip) ); } @@ -920,7 +953,10 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) { // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) - parent->scroll (event->direction); + printf("ThumbBrowserBase::Internal::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", + event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); + + parent->scroll (event->direction, event->delta_x, event->delta_y); return true; } diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index d4d7e63e2..02bea3646 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -138,7 +138,7 @@ public: enum Arrangement {TB_Horizontal, TB_Vertical}; void configScrollBars (); void scrollChanged (); - void scroll (int direction); + void scroll (int direction, double deltaX=0.0, double deltaY=0.0); void scrollPage (int direction); private: