diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index fbe2be4c6c..7bd53c4446 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -85,6 +85,8 @@ BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(nullptr), fileCa BatchQueue::~BatchQueue () { + idle_register.destroy(); + MYWRITERLOCK(l, entryRW); // The listener merges parameters with old values, so delete afterwards @@ -937,7 +939,7 @@ void BatchQueue::notifyListener (bool queueEmptied) } params->queueEmptied = queueEmptied; params->queueError = false; - add_idle (bqnotifylistenerUI, params); + idle_register.add(bqnotifylistenerUI, params); } } @@ -967,6 +969,6 @@ void BatchQueue::error (Glib::ustring msg) params->queueEmptied = false; params->queueError = true; params->queueErrorMessage = msg; - add_idle (bqnotifylistenerUI, params); + idle_register.add(bqnotifylistenerUI, params); } } diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index f7376680b4..68373838ed 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -36,37 +36,12 @@ class BatchQueueListener }; class FileCatalog; -class BatchQueue : public ThumbBrowserBase, + +class BatchQueue final : + public ThumbBrowserBase, public rtengine::BatchProcessingListener, public LWButtonListener { - -protected: - int getMaxThumbnailHeight() const; - void saveThumbnailHeight (int height); - int getThumbnailHeight (); - - BatchQueueEntry* processing; // holds the currently processed image - FileCatalog* fileCatalog; - int sequence; // holds the current sequence index - - Glib::ustring nameTemplate; - - MyImageMenuItem* cancel; - MyImageMenuItem* head; - MyImageMenuItem* tail; - Gtk::MenuItem* selall; - Gtk::MenuItem* open; - Glib::RefPtr pmaccelgroup; - Gtk::Menu pmenu; - - BatchQueueListener* listener; - - Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); - Glib::ustring getTempFilenameForParams( const Glib::ustring &filename ); - bool saveBatchQueue (); - void notifyListener (bool queueEmptied); - public: explicit BatchQueue (FileCatalog* aFileCatalog); ~BatchQueue (); @@ -106,6 +81,34 @@ class BatchQueue : public ThumbBrowserBase, static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence = 0); static int calcMaxThumbnailHeight(); + +protected: + int getMaxThumbnailHeight() const; + void saveThumbnailHeight (int height); + int getThumbnailHeight (); + + Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); + Glib::ustring getTempFilenameForParams( const Glib::ustring &filename ); + bool saveBatchQueue (); + void notifyListener (bool queueEmptied); + + BatchQueueEntry* processing; // holds the currently processed image + FileCatalog* fileCatalog; + int sequence; // holds the current sequence index + + Glib::ustring nameTemplate; + + MyImageMenuItem* cancel; + MyImageMenuItem* head; + MyImageMenuItem* tail; + Gtk::MenuItem* selall; + Gtk::MenuItem* open; + Glib::RefPtr pmaccelgroup; + Gtk::Menu pmenu; + + BatchQueueListener* listener; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index dab459a140..67dd9f64a2 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -364,23 +364,25 @@ BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LAB } BlackWhite::~BlackWhite () { + idle_register.destroy(); + delete luminanceCEG; delete beforeCurveCEG; delete afterCurveCEG; } -int BWChangedUI (void* data) -{ - (static_cast(data))->BWComputed_ (); - return 0; -} - void BlackWhite::BWChanged (double redbw, double greenbw, double bluebw) { nextredbw = redbw; nextgreenbw = greenbw; nextbluebw = bluebw; - add_idle (BWChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->BWComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool BlackWhite::BWComputed_ () diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index e38258b044..5f0ffec44d 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -28,10 +28,64 @@ #include "mycurve.h" #include "colorprovider.h" -class BlackWhite : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoBWListener, public CurveListener, public ColorProvider +class BlackWhite final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoBWListener, + public CurveListener, + public ColorProvider { +public: + + BlackWhite (); + ~BlackWhite (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void autoOpenCurve (); + void setEditProvider (EditDataProvider *provider); + + void autoch_toggled (); + void neutral_pressed (); + + void updateRGBLabel (); + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool bwadd, bool bwgadd); + void trimValues (rtengine::procparams::ProcParams* pp); + void enabledcc_toggled (); + void enabledChanged (); + void methodChanged (); + void filterChanged (); + void settingChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void BWChanged (double redbw, double greenbw, double bluebw); + bool BWComputed_ (); + void curveChanged (CurveEditor* ce); + void curveMode1Changed (); + bool curveMode1Changed_ (); + void curveMode1Changed2 (); + bool curveMode1Changed2_ (); + void algoChanged (); + + Glib::ustring getSettingString (); + Glib::ustring getFilterString (); + Glib::ustring getalgoString (); + +private: + void showLuminance(); + void hideLuminance(); + void showFilter(); + void hideFilter(); + void showEnabledCC(); + void hideEnabledCC(); + void showMixer(int nChannels, bool RGBIsSensitive = true); + void hideMixer(); + void showGamma(); + void hideGamma(); -protected: FlatCurveEditor* luminanceCurve; Gtk::HSeparator* luminanceSep; CurveEditorGroup* luminanceCEG; @@ -85,55 +139,7 @@ class BlackWhite : public ToolParamBlock, public AdjusterListener, public Foldab double nextgreenbw; double nextbluebw; - void showLuminance(); - void hideLuminance(); - void showFilter(); - void hideFilter(); - void showEnabledCC(); - void hideEnabledCC(); - void showMixer(int nChannels, bool RGBIsSensitive = true); - void hideMixer(); - void showGamma(); - void hideGamma(); - -public: - - BlackWhite (); - ~BlackWhite (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void autoOpenCurve (); - void setEditProvider (EditDataProvider *provider); - - void autoch_toggled (); - void neutral_pressed (); - - void updateRGBLabel (); - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool bwadd, bool bwgadd); - void trimValues (rtengine::procparams::ProcParams* pp); - void enabledcc_toggled (); - void enabledChanged (); - void methodChanged (); - void filterChanged (); - void settingChanged (); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - void BWChanged (double redbw, double greenbw, double bluebw); - bool BWComputed_ (); - void curveChanged (CurveEditor* ce); - void curveMode1Changed (); - bool curveMode1Changed_ (); - void curveMode1Changed2 (); - bool curveMode1Changed2_ (); - void algoChanged (); - - Glib::ustring getSettingString (); - Glib::ustring getFilterString (); - Glib::ustring getalgoString (); - + IdleRegister idle_register; }; #endif diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 7421711eb0..68ab74d950 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -19,6 +19,7 @@ #include "cachemanager.h" #include +#include #include #include diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index 528047a22c..a198dd1f56 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -424,6 +424,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", ColorAppearance::~ColorAppearance () { + idle_register.destroy(); + delete curveEditorG; delete curveEditorG2; delete curveEditorG3; @@ -1002,15 +1004,17 @@ void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdit } } -int autoCamChangedUI (void* data) -{ - (static_cast(data))->autoCamComputed_ (); - return 0; -} + void ColorAppearance::autoCamChanged (double ccam) { nextCcam = ccam; - add_idle (autoCamChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->autoCamComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorAppearance::autoCamComputed_ () @@ -1023,15 +1027,17 @@ bool ColorAppearance::autoCamComputed_ () return false; } -int adapCamChangedUI (void* data) -{ - (static_cast(data))->adapCamComputed_ (); - return 0; -} + void ColorAppearance::adapCamChanged (double cadap) { nextCadap = cadap; - add_idle (adapCamChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->adapCamComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorAppearance::adapCamComputed_ () diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 1560e275e7..e7b7e072d8 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -28,10 +28,61 @@ #include "guiutils.h" #include "colorprovider.h" -class ColorAppearance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider +class ColorAppearance final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoCamListener, + public CurveListener, + public ColorProvider { +public: + ColorAppearance (); + ~ColorAppearance (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void adjusterChanged (Adjuster* a, double newval); + void adjusterAutoToggled (Adjuster* a, bool newval); +// void adjusterAdapToggled (Adjuster* a, bool newval); + void enabledChanged (); + void surroundChanged (); + void wbmodelChanged (); + void algoChanged (); + void surrsource_toggled (); + void gamut_toggled (); +// void badpix_toggled (); + void datacie_toggled (); + void tonecie_toggled (); +// void sharpcie_toggled (); + void autoCamChanged (double ccam); + bool autoCamComputed_ (); + void adapCamChanged (double cadap); + bool adapCamComputed_ (); + + void curveChanged (CurveEditor* ce); + void curveMode1Changed (); + bool curveMode1Changed_ (); + void curveMode2Changed (); + bool curveMode2Changed_ (); + void curveMode3Changed (); + bool curveMode3Changed_ (); + + void expandCurve (bool isExpanded); + bool isCurveExpanded (); + void autoOpenCurve (); + + void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd); + void trimValues (rtengine::procparams::ProcParams* pp); + void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller); + +private: + bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); + bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); -protected: Glib::RefPtr bgTTips; Glib::RefPtr srTTips; Glib::RefPtr bgPixbuf; @@ -83,56 +134,10 @@ class ColorAppearance : public ToolParamBlock, public AdjusterListener, public F bool lastAutoAdapscen; bool lastsurr; bool lastgamut; -// bool lastbadpix; bool lastdatacie; bool lasttonecie; -// bool lastsharpcie; - bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); - bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); - -public: - - ColorAppearance (); - ~ColorAppearance (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void adjusterChanged (Adjuster* a, double newval); - void adjusterAutoToggled (Adjuster* a, bool newval); -// void adjusterAdapToggled (Adjuster* a, bool newval); - void enabledChanged (); - void surroundChanged (); - void wbmodelChanged (); - void algoChanged (); - void surrsource_toggled (); - void gamut_toggled (); -// void badpix_toggled (); - void datacie_toggled (); - void tonecie_toggled (); -// void sharpcie_toggled (); - void autoCamChanged (double ccam); - bool autoCamComputed_ (); - void adapCamChanged (double cadap); - bool adapCamComputed_ (); - - void curveChanged (CurveEditor* ce); - void curveMode1Changed (); - bool curveMode1Changed_ (); - void curveMode2Changed (); - bool curveMode2Changed_ (); - void curveMode3Changed (); - bool curveMode3Changed_ (); - - void expandCurve (bool isExpanded); - bool isCurveExpanded (); - void autoOpenCurve (); - - void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd); - void trimValues (rtengine::procparams::ProcParams* pp); - void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller); + IdleRegister idle_register; }; #endif diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index ceec0092f7..d471ef787a 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -324,6 +324,8 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR ColorToning::~ColorToning() { + idle_register.destroy(); + delete colorCurveEditorG; delete opacityCurveEditorG; delete clCurveEditorG; @@ -650,19 +652,18 @@ void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, doubl Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE") + ": %1" + "\n" + M("TP_COLORTONING_STRENGTH") + ": %2"), int(newTop), int(newBottom))); } -int CTChanged_UI (void* data) -{ - (static_cast(data))->CTComp_ (); - return 0; -} - - void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot) { nextbw = bwct; nextsatth = satthres; nextsatpr = satprot; - add_idle (CTChanged_UI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->CTComp_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorToning::CTComp_ () diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index e344473019..7f1290bf61 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -13,12 +13,43 @@ #include "thresholdadjuster.h" #include "colorprovider.h" -class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener, public CurveListener, public ColorProvider, - public ThresholdAdjusterListener, public AdjusterListener +class ColorToning final : + public ToolParamBlock, + public FoldableToolPanel, + public rtengine::AutoColorTonListener, + public CurveListener, + public ColorProvider, + public ThresholdAdjusterListener, + public AdjusterListener { +public: + ColorToning (); + ~ColorToning(); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void trimValues (rtengine::procparams::ProcParams* pp); + void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); + void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); + void neutral_pressed (); + //void neutralCurves_pressed (); + void autoColorTonChanged (int bwct, int satthres, int satprot); + bool CTComp_ (); + + void enabledChanged (); + void curveChanged (CurveEditor* ce); + void autosatChanged (); + void autoOpenCurve (); + void methodChanged (); + void twocolorChanged (bool changedbymethod); + void twoColorChangedByGui (); + void lumamodeChanged (); + + void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); -protected: - //Gtk::HSeparator* splitSep; +private: Gtk::HSeparator* satLimiterSep; Gtk::HSeparator* colorSep; CurveEditorGroup* colorCurveEditorG; @@ -57,7 +88,6 @@ class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rte Gtk::Image* irg; Gtk::Button* neutral; - //Gtk::Button* neutralCurves; Gtk::HBox* neutrHBox; Gtk::HBox* chromaHbox; Gtk::Label* chroLabel; @@ -75,32 +105,7 @@ class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rte bool lastLumamode; sigc::connection lumamodeConn; -public: - ColorToning (); - ~ColorToning(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void trimValues (rtengine::procparams::ProcParams* pp); - void adjusterChanged (Adjuster* a, double newval); - void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); - void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); - void neutral_pressed (); - //void neutralCurves_pressed (); - void autoColorTonChanged (int bwct, int satthres, int satprot); - bool CTComp_ (); - - void enabledChanged (); - void curveChanged (CurveEditor* ce); - void autosatChanged (); - void autoOpenCurve (); - void methodChanged (); - void twocolorChanged (bool changedbymethod); - void twoColorChangedByGui (); - void lumamodeChanged (); - - void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + IdleRegister idle_register; }; #endif diff --git a/rtgui/crop.cc b/rtgui/crop.cc index a69c71ed82..83efb6a37a 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -25,6 +25,9 @@ using namespace rtengine::procparams; extern Options options; +namespace +{ + class RefreshSpinHelper { @@ -35,6 +38,22 @@ class RefreshSpinHelper : crop(_crop), notify(_notify) {} }; +int refreshSpinsUI (void* data) +{ + RefreshSpinHelper* rsh = static_cast(data); + rsh->crop->refreshSpins (rsh->notify); + delete rsh; + return 0; +} + +int notifyListenerUI (void* data) +{ + static_cast(data)->notifyListener(); + return 0; +} + +} + Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true) { @@ -252,6 +271,11 @@ Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true) show_all (); } +Crop::~Crop() +{ + idle_register.destroy(); +} + void Crop::writeOptions () { @@ -508,32 +532,18 @@ void Crop::enabledChanged () } } -int notifyListenerUI (void* data) -{ - (static_cast(data))->notifyListener (); - return 0; -} - -int refreshSpinsUI (void* data) -{ - RefreshSpinHelper* rsh = static_cast(data); - rsh->crop->refreshSpins (rsh->notify); - delete rsh; - return 0; -} - void Crop::hFlipCrop () { nx = maxw - nx - nw; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::vFlipCrop () { ny = maxh - ny - nh; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::rotateCrop (int deg, bool hflip, bool vflip) @@ -573,7 +583,7 @@ void Crop::rotateCrop (int deg, bool hflip, bool vflip) } lastRotationDeg = deg; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::positionChanged () @@ -587,7 +597,7 @@ void Crop::positionChanged () int W = nw; int H = nh; cropMoved (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } void Crop::widthChanged () @@ -600,7 +610,7 @@ void Crop::widthChanged () int W = (int)w->get_value (); int H = nh; cropWidth2Resized (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } void Crop::heightChanged () @@ -613,7 +623,7 @@ void Crop::heightChanged () int W = nw; int H = (int)h->get_value (); cropHeight2Resized (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } // Fixed ratio toggle button @@ -665,7 +675,7 @@ void Crop::adjustCropToRatio() } // This will save the options - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, true)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, true)); } void Crop::refreshSize () @@ -737,28 +747,28 @@ void Crop::setDimensions (int mw, int mh) refreshSize (); } -struct setdimparams { - Crop* crop; - int x; - int y; -}; - -int sizeChangedUI (void* data) -{ - setdimparams* params = static_cast(data); - params->crop->setDimensions (params->x, params->y); - delete params; - return 0; -} - void Crop::sizeChanged (int x, int y, int ow, int oh) { - - setdimparams* params = new setdimparams; - params->x = x; - params->y = y; - params->crop = this; - add_idle (sizeChangedUI, params); + struct Params { + Crop* crop; + int x; + int y; + }; + + Params* const params = new Params{ + this, + x, + y + }; + + const auto func = [](gpointer data) -> gboolean { + Params* const params = static_cast(data); + params->crop->setDimensions(params->x, params->y); + delete params; + return FALSE; + }; + + idle_register.add(func, params); } bool Crop::refreshSpins (bool notify) @@ -822,7 +832,7 @@ void Crop::cropMoved (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -866,7 +876,7 @@ void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) @@ -906,7 +916,7 @@ void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) @@ -949,7 +959,7 @@ void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) @@ -989,7 +999,7 @@ void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) @@ -1031,7 +1041,7 @@ void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) @@ -1071,7 +1081,7 @@ void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) @@ -1111,7 +1121,7 @@ void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) @@ -1148,7 +1158,7 @@ void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropInit (int &x, int &y, int &w, int &h) @@ -1266,13 +1276,12 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropManipReady () { - - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } double Crop::getRatio () diff --git a/rtgui/crop.h b/rtgui/crop.h index 077903836f..e0bad8b367 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -33,44 +33,20 @@ class CropPanelListener virtual void cropSelectRequested() = 0; }; -class CropRatio -{ - -public: +struct CropRatio { Glib::ustring label; double value; }; -class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolPanel, public rtengine::SizeListener +class Crop final : + public ToolParamBlock, + public CropGUIListener, + public FoldableToolPanel, + public rtengine::SizeListener { -protected: - Gtk::CheckButton* fixr; - MyComboBoxText* ratio; - MyComboBoxText* orientation; - MyComboBoxText* guide; - Gtk::Button* selectCrop; - CropPanelListener* clistener; - int opt; - MySpinButton* x; - MySpinButton* y; - MySpinButton* w; - MySpinButton* h; - MySpinButton* ppi; - Gtk::Label* sizecm; - Gtk::Label* sizein; - Gtk::VBox* ppibox; - Gtk::VBox* sizebox; - int maxw, maxh; - double nx, ny; - int nw, nh; - int lastRotationDeg; - sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn; - bool wDirty, hDirty, xDirty, yDirty, lastFixRatio; - void adjustCropToRatio(); - std::vector cropratio; - public: - Crop (); + Crop(); + ~Crop(); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); @@ -116,6 +92,34 @@ class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolP void hFlipCrop (); void vFlipCrop (); void rotateCrop (int deg, bool hflip, bool vflip); + +private: + Gtk::CheckButton* fixr; + MyComboBoxText* ratio; + MyComboBoxText* orientation; + MyComboBoxText* guide; + Gtk::Button* selectCrop; + CropPanelListener* clistener; + int opt; + MySpinButton* x; + MySpinButton* y; + MySpinButton* w; + MySpinButton* h; + MySpinButton* ppi; + Gtk::Label* sizecm; + Gtk::Label* sizein; + Gtk::VBox* ppibox; + Gtk::VBox* sizebox; + int maxw, maxh; + double nx, ny; + int nw, nh; + int lastRotationDeg; + sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn; + bool wDirty, hDirty, xDirty, yDirty, lastFixRatio; + void adjustCropToRatio(); + std::vector cropratio; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index bb59efe13d..42c6eb7567 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -38,14 +38,15 @@ CropHandler::CropHandler () displayHandler(nullptr) { - chi = new CropHandlerIdleHelper; - chi->destroyed = false; - chi->pending = 0; - chi->cropHandler = this; + idle_helper = new IdleHelper; + idle_helper->destroyed = false; + idle_helper->pending = 0; + idle_helper->cropHandler = this; } CropHandler::~CropHandler () { + idle_register.destroy(); if (ipc) { ipc->delSizeListener (this); @@ -61,10 +62,10 @@ CropHandler::~CropHandler () cimg.lock (); - if (chi->pending) { - chi->destroyed = true; + if (idle_helper->pending) { + idle_helper->destroyed = true; } else { - delete chi; + delete idle_helper; } cimg.unlock (); @@ -292,83 +293,6 @@ void CropHandler::getPosition (int& x, int& y) } -int createpixbufs (void* data) -{ - - CropHandlerIdleHelper* chi = static_cast(data); - - if (chi->destroyed) { - if (chi->pending == 1) { - delete chi; - } else { - chi->pending--; - } - - return 0; - } - - CropHandler* ch = chi->cropHandler; - - ch->cimg.lock (); - ch->cropPixbuf.clear (); - - if (!ch->enabled) { - delete [] ch->cropimg; - ch->cropimg = nullptr; - delete [] ch->cropimgtrue; - ch->cropimgtrue = nullptr; - ch->cimg.unlock (); - return 0; - } - - if (ch->cropimg) { - if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) { - // calculate final image size - int czoom = ch->zoom < 1000 ? 1000 : ch->zoom; - int imw = ch->cropimg_width * czoom / 1000; - int imh = ch->cropimg_height * czoom / 1000; - - if (imw > ch->ww) { - imw = ch->ww; - } - - if (imh > ch->wh) { - imh = ch->wh; - } - - Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); - ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); - tmpPixbuf.clear (); - - Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); - ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); - tmpPixbuftrue.clear (); - } - - delete [] ch->cropimg; - ch->cropimg = nullptr; - delete [] ch->cropimgtrue; - ch->cropimgtrue = nullptr; - } - - ch->cimg.unlock (); - - if (ch->displayHandler) { - ch->displayHandler->cropImageUpdated (); - - if (ch->initial) { - ch->displayHandler->initialImageArrived (); - ch->initial = false; - } - } - - chi->pending--; - - return 0; -} - void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp, rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) { @@ -408,8 +332,84 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp ciw = aw; cih = ah; cis = askip; - chi->pending++; - add_idle (createpixbufs, chi); + idle_helper->pending++; + + const auto func = [](gpointer data) -> gboolean { + IdleHelper* const idle_helper = static_cast(data); + + if (idle_helper->destroyed) { + if (idle_helper->pending == 1) { + delete idle_helper; + } else { + idle_helper->pending--; + } + + return FALSE; + } + + CropHandler* ch = idle_helper->cropHandler; + + ch->cimg.lock (); + ch->cropPixbuf.clear (); + + if (!ch->enabled) { + delete [] ch->cropimg; + ch->cropimg = nullptr; + delete [] ch->cropimgtrue; + ch->cropimgtrue = nullptr; + ch->cimg.unlock (); + return FALSE; + } + + if (ch->cropimg) { + if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) { + // calculate final image size + int czoom = ch->zoom < 1000 ? 1000 : ch->zoom; + int imw = ch->cropimg_width * czoom / 1000; + int imh = ch->cropimg_height * czoom / 1000; + + if (imw > ch->ww) { + imw = ch->ww; + } + + if (imh > ch->wh) { + imh = ch->wh; + } + + Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); + ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); + tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); + tmpPixbuf.clear (); + + Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); + ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); + tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); + tmpPixbuftrue.clear (); + } + + delete [] ch->cropimg; + ch->cropimg = nullptr; + delete [] ch->cropimgtrue; + ch->cropimgtrue = nullptr; + } + + ch->cimg.unlock (); + + if (ch->displayHandler) { + ch->displayHandler->cropImageUpdated (); + + if (ch->initial) { + ch->displayHandler->initialImageArrived (); + ch->initial = false; + } + } + + idle_helper->pending--; + + return FALSE; + }; + + idle_register.add(func, idle_helper); } cimg.unlock (); diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 3bf7e58da4..0492aea2a9 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -36,56 +36,15 @@ class CropDisplayHandler virtual void setDisplayPosition (int x, int y) {} }; -class CropHandler; -struct CropHandlerIdleHelper { - CropHandler* cropHandler; - bool destroyed; - int pending; -}; - /** * This class handle the displayed part of the image, ask for the initial data and process it so it can display it. * Its position on the preview is handled not set by this class but by the CropHandlerListener (i.e. CropWindow) with which it works closely. */ -class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener +class CropHandler final : + public rtengine::DetailedCropListener, + public rtengine::SizeListener { - - friend int createpixbufs (void* data); - -protected: - int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) - int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller - int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters - int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image - int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size - int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds - bool enabled; - unsigned char* cropimg; - unsigned char* cropimgtrue; - int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; - bool initial; - bool isLowUpdatePriority; - - rtengine::StagedImageProcessor* ipc; - rtengine::DetailedCrop* crop; - - CropDisplayHandler* displayHandler; - CropHandlerIdleHelper* chi; - - void compDim (); - public: - - void update (); - - - rtengine::procparams::CropParams cropParams; - rtengine::procparams::ColorManagementParams colorParams; - Glib::RefPtr cropPixbuf; - Glib::RefPtr cropPixbuftrue; - - MyMutex cimg; - CropHandler (); ~CropHandler (); @@ -127,6 +86,46 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); // SizeListener interface void sizeChanged (int w, int h, int ow, int oh); + + void update (); + + + rtengine::procparams::CropParams cropParams; + rtengine::procparams::ColorManagementParams colorParams; + Glib::RefPtr cropPixbuf; + Glib::RefPtr cropPixbuftrue; + + MyMutex cimg; + +private: + struct IdleHelper { + CropHandler* cropHandler; + bool destroyed; + int pending; + }; + + void compDim (); + + int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) + int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller + int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters + int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image + int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size + int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds + bool enabled; + unsigned char* cropimg; + unsigned char* cropimgtrue; + int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; + bool initial; + bool isLowUpdatePriority; + + rtengine::StagedImageProcessor* ipc; + rtengine::DetailedCrop* crop; + + CropDisplayHandler* displayHandler; + IdleHelper* idle_helper; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index eafaa477a3..7b5adade2e 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -18,6 +18,7 @@ */ #include "dirbrowser.h" +#include #include #ifdef WIN32 diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index a5611cc455..bd673e5c3f 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -327,22 +327,24 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP DirPyrDenoise::~DirPyrDenoise () { + idle_register.destroy(); + delete NoiscurveEditorG; delete CCcurveEditorG; - -} -int chromaChangedUI (void* data) -{ - (static_cast(data))->chromaComputed_ (); - return 0; } + void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue) { nextchroma = autchroma; -// printf("CHROM=%f\n",nextchroma); nextred = autred; nextblue = autblue; - add_idle(chromaChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->chromaComputed_(); + return false; + }; + + idle_register.add(func, this); } bool DirPyrDenoise::chromaComputed_ () @@ -356,12 +358,6 @@ bool DirPyrDenoise::chromaComputed_ () updateNoiseLabel (); return false; } -int TilePrevChangedUI (void* data) -{ - (static_cast(data))->TilePrevComputed_ (); - return 0; -} - void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) { @@ -372,10 +368,14 @@ void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, i nextsizeT = sizeT; nextsizeP = sizeP; - add_idle(TilePrevChangedUI, this); - + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->TilePrevComputed_(); + return false; + }; + idle_register.add(func, this); } + bool DirPyrDenoise::TilePrevComputed_ () { @@ -385,6 +385,7 @@ bool DirPyrDenoise::TilePrevComputed_ () updatePrevLabel (); return false; } + void DirPyrDenoise::updateTileLabel () { if (!batchMode) { @@ -422,19 +423,17 @@ void DirPyrDenoise::updatePrevLabel () } } - -int noiseChangedUI (void* data) -{ - (static_cast(data))->noiseComputed_ (); - return 0; -} - - void DirPyrDenoise::noiseChanged (double nresid, double highresid) { nextnresid = nresid; nexthighresid = highresid; - add_idle(noiseChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->noiseComputed_(); + return false; + }; + + idle_register.add(func, this); } bool DirPyrDenoise::noiseComputed_ () diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index e81bf263e4..9745b374b2 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -28,10 +28,58 @@ #include "guiutils.h" #include "options.h" -class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider +class DirPyrDenoise final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoChromaListener, + public CurveListener, + public ColorProvider { +public: + DirPyrDenoise (); + ~DirPyrDenoise (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void curveChanged (CurveEditor* ce); + void setEditProvider (EditDataProvider *provider); + void autoOpenCurve (); -protected: + void adjusterChanged (Adjuster* a, double newval); + void enabledChanged (); + void enhanceChanged (); + void medianChanged (); + void autochromaChanged (); + void chromaChanged (double autchroma, double autred, double autblue); + bool chromaComputed_ (); + void noiseChanged (double nresid, double highresid); + bool noiseComputed_ (); + void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); + bool TilePrevComputed_ (); + +// void perform_toggled (); + void updateNoiseLabel (); + void LmethodChanged (); + void CmethodChanged (); + void C2methodChanged (); + void updateTileLabel (); + void updatePrevLabel (); + + void dmethodChanged (); + void medmethodChanged (); + void methodmedChanged (); + void rgbmethodChanged (); + void smethodChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + + void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); + void trimValues (rtengine::procparams::ProcParams* pp); + Glib::ustring getSettingString (); + +private: CurveEditorGroup* NoiscurveEditorG; CurveEditorGroup* CCcurveEditorG; Adjuster* luma; @@ -92,50 +140,7 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol int nextsizeT; int nextsizeP; -public: - - DirPyrDenoise (); - ~DirPyrDenoise (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void curveChanged (CurveEditor* ce); - void setEditProvider (EditDataProvider *provider); - void autoOpenCurve (); - - void adjusterChanged (Adjuster* a, double newval); - void enabledChanged (); - void enhanceChanged (); - void medianChanged (); - void autochromaChanged (); - void chromaChanged (double autchroma, double autred, double autblue); - bool chromaComputed_ (); - void noiseChanged (double nresid, double highresid); - bool noiseComputed_ (); - void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); - bool TilePrevComputed_ (); - -// void perform_toggled (); - void updateNoiseLabel (); - void LmethodChanged (); - void CmethodChanged (); - void C2methodChanged (); - void updateTileLabel (); - void updatePrevLabel (); - - void dmethodChanged (); - void medmethodChanged (); - void methodmedChanged (); - void rgbmethodChanged (); - void smethodChanged (); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - - void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); - void trimValues (rtengine::procparams::ProcParams* pp); - Glib::ustring getSettingString (); - + IdleRegister idle_register; }; #endif diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 0783efe14c..8da176fc35 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -35,6 +35,44 @@ using namespace rtengine::procparams; +namespace +{ + +struct spparams { + double val; + Glib::ustring str; + MyProgressBar *pProgress; + Glib::RefPtr cssProvider; +}; + +int setprogressStrUI ( void *p ) +{ + spparams *s = static_cast (p); + + if ( ! s->str.empty() ) { + s->pProgress->set_text ( M (s->str) ); + } + + if ( s->val >= 0 ) { + s->pProgress->set_fraction ( s->val ); + + if (s->cssProvider) { + if ( s->val < 1.0 ) { + s->cssProvider->load_from_data ("ProgressBar { background-color: red }"); + } else { + s->cssProvider->load_from_data ("ProgressBar { background-color: grey }"); + } + + s->pProgress->get_style_context()->set_background (s->pProgress->get_window()); + } + } + + delete s; + return FALSE; +} + +} + class EditorPanel::ColorManagementToolbar { private: @@ -683,6 +721,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) EditorPanel::~EditorPanel () { + idle_register.destroy(); history->setHistoryBeforeLineListener (nullptr); // the order is important! @@ -1017,46 +1056,12 @@ void EditorPanel::setProgressState (bool inProcessing) g_idle_add (setProgressStateUIThread, p); } -struct spparams { - double val; - Glib::ustring str; - MyProgressBar *pProgress; - Glib::RefPtr cssProvider; - -}; - -int setprogressStrUI ( void *p ) -{ - spparams *s = static_cast (p); - - if ( ! s->str.empty() ) { - s->pProgress->set_text ( M (s->str) ); - } - - if ( s->val >= 0 ) { - s->pProgress->set_fraction ( s->val ); - - if (s->cssProvider) { - if ( s->val < 1.0 ) { - s->cssProvider->load_from_data ("ProgressBar { background-color: red }"); - } else { - s->cssProvider->load_from_data ("ProgressBar { background-color: grey }"); - } - - s->pProgress->get_style_context()->set_background (s->pProgress->get_window()); - } - } - - delete s; - return 0; -} - void EditorPanel::setProgress (double p) { spparams *s = new spparams; s->val = p; s->pProgress = progressLabel; - add_idle (setprogressStrUI, s); + idle_register.add(setprogressStrUI, s); } void EditorPanel::setProgressStr (Glib::ustring str) @@ -1065,7 +1070,7 @@ void EditorPanel::setProgressStr (Glib::ustring str) s->str = str; s->val = -1; s->pProgress = progressLabel; - add_idle (setprogressStrUI, s); + idle_register.add(setprogressStrUI, s); } // This is only called from the ThreadUI, so within the gtk thread diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index d87f12c231..609df52369 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -45,19 +45,104 @@ struct EditorPanelIdleHelper { }; class RTWindow; -class EditorPanel : public Gtk::VBox, +class EditorPanel final : + public Gtk::VBox, public PParamsChangeListener, public rtengine::ProgressListener, public ThumbnailListener, public HistoryBeforeLineListener, public rtengine::HistogramListener { +public: + explicit EditorPanel (FilePanel* filePanel = nullptr); + ~EditorPanel (); + + void open (Thumbnail* tmb, rtengine::InitialImage* isrc); + void setAspect (); + void on_realize (); + void leftPaneButtonReleased (GdkEventButton *event); + void rightPaneButtonReleased (GdkEventButton *event); + + void setParent (RTWindow* p) + { + parent = p; + } + void writeOptions(); + + void showTopPanel (bool show); + bool isRealized() + { + return realized; + } + // progresslistener interface + void setProgress (double p); + void setProgressStr (Glib::ustring str); + void setProgressState (bool inProcessing); + void error (Glib::ustring title, Glib::ustring descr); + void displayError (Glib::ustring title, Glib::ustring descr); // this is called by error in the gtk thread + void refreshProcessingState (bool inProcessing); // this is called by setProcessingState in the gtk thread + + // PParamsChangeListener interface + void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = nullptr); + + // thumbnaillistener interface + void procParamsChanged (Thumbnail* thm, int whoChangedIt); + + // HistoryBeforeLineListener + void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params); + + // HistogramListener + void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, + LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma, LUTu & histLRETI); + + // event handlers + void info_toggled (); + void hideHistoryActivated (); + void tbRightPanel_1_toggled (); + void tbTopPanel_1_toggled (); + void beforeAfterToggled (); + void tbBeforeLock_toggled(); + void saveAsPressed (); + void queueImgPressed (); + void sendToGimpPressed (); + void openNextEditorImage (); + void openPreviousEditorImage (); + void syncFileBrowser (); + + void tbTopPanel_1_visible (bool visible); + bool CheckSidePanelsVisibility(); + void tbShowHideSidePanels_managestate(); + void toggleSidePanels(); + void toggleSidePanelsZoomFit(); + + void saveProfile (); + Glib::ustring getShortName (); + Glib::ustring getFileName (); + bool handleShortcutKey (GdkEventKey* event); + + bool getIsProcessing() const + { + return isProcessing; + } + void updateProfiles(const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC); + void updateTPVScrollbar (bool hide); + void updateTabsUsesIcons (bool useIcons); + void updateHistogramPosition (int oldPosition, int newPosition); + + Gtk::Paned* catalogPane; + private: + void close (); + + BatchQueueEntry* createBatchQueueEntry (); + bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); + bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); + bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname); + bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); Glib::ustring lastSaveAsFileName; bool realized; -protected: MyProgressBar *progressLabel; Gtk::ToggleButton* info; Gtk::ToggleButton* hidehp; @@ -122,13 +207,6 @@ class EditorPanel : public Gtk::VBox, EditorPanelIdleHelper* epih; - void close (); - - BatchQueueEntry* createBatchQueueEntry (); - bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); - bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); - bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname); - bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); int err; time_t processingStartedTime; @@ -137,84 +215,7 @@ class EditorPanel : public Gtk::VBox, bool isProcessing; - -public: - explicit EditorPanel (FilePanel* filePanel = nullptr); - virtual ~EditorPanel (); - - void open (Thumbnail* tmb, rtengine::InitialImage* isrc); - void setAspect (); - void on_realize (); - void leftPaneButtonReleased (GdkEventButton *event); - void rightPaneButtonReleased (GdkEventButton *event); - - void setParent (RTWindow* p) - { - parent = p; - } - void writeOptions(); - - void showTopPanel (bool show); - bool isRealized() - { - return realized; - } - // progresslistener interface - void setProgress (double p); - void setProgressStr (Glib::ustring str); - void setProgressState (bool inProcessing); - void error (Glib::ustring title, Glib::ustring descr); - void displayError (Glib::ustring title, Glib::ustring descr); // this is called by error in the gtk thread - void refreshProcessingState (bool inProcessing); // this is called by setProcessingState in the gtk thread - - // PParamsChangeListener interface - void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = nullptr); - - // thumbnaillistener interface - void procParamsChanged (Thumbnail* thm, int whoChangedIt); - - // HistoryBeforeLineListener - void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params); - - // HistogramListener - void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, - LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma, LUTu & histLRETI); - - // event handlers - void info_toggled (); - void hideHistoryActivated (); - void tbRightPanel_1_toggled (); - void tbTopPanel_1_toggled (); - void beforeAfterToggled (); - void tbBeforeLock_toggled(); - void saveAsPressed (); - void queueImgPressed (); - void sendToGimpPressed (); - void openNextEditorImage (); - void openPreviousEditorImage (); - void syncFileBrowser (); - - void tbTopPanel_1_visible (bool visible); - bool CheckSidePanelsVisibility(); - void tbShowHideSidePanels_managestate(); - void toggleSidePanels(); - void toggleSidePanelsZoomFit(); - - void saveProfile (); - Glib::ustring getShortName (); - Glib::ustring getFileName (); - bool handleShortcutKey (GdkEventKey* event); - - bool getIsProcessing() const - { - return isProcessing; - } - void updateProfiles(const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC); - void updateTPVScrollbar (bool hide); - void updateTabsUsesIcons (bool useIcons); - void updateHistogramPosition (int oldPosition, int newPosition); - - Gtk::Paned *catalogPane; + IdleRegister idle_register; }; #endif diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 8c7bae0fa5..ed9b70e8dc 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -22,12 +22,6 @@ #include "inspector.h" #include "placesbrowser.h" -int FilePanelInitUI (void* data) -{ - (static_cast(data))->init (); - return 0; -} - FilePanel::FilePanel () : parent(nullptr) { @@ -143,13 +137,21 @@ FilePanel::FilePanel () : parent(nullptr) fileCatalog->setFileSelectionChangeListener (tpc); fileCatalog->setFileSelectionListener (this); - add_idle (FilePanelInitUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->init(); + return FALSE; + }; + + idle_register.add(func, this); show_all (); } FilePanel::~FilePanel () { + idle_register.destroy(); + rightNotebookSwitchConn.disconnect(); if (inspectorPanel) { diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index 68f021043b..d54f5f75a5 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -33,38 +33,12 @@ #include "progressconnector.h" class RTWindow; -class FilePanel : public Gtk::HPaned, + +class FilePanel final : + public Gtk::HPaned, public FileSelectionListener, public PParamsChangeListener { - -protected: - //DirBrowser* dirBrowser; - PlacesBrowser* placesBrowser; - RecentBrowser* recentBrowser; - // FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it - - Inspector* inspectorPanel; - Gtk::VPaned* tpcPaned; - BatchToolPanelCoordinator* tpc; - History* history; - //FilterPanel* filterPanel; - RTWindow* parent; - Gtk::Notebook* rightNotebook; - sigc::connection rightNotebookSwitchConn; - - struct pendingLoad { - bool complete; - ProgressConnector *pc; - Thumbnail *thm; - }; - MyMutex pendingLoadMutex; - std::vector pendingLoads; - - int error; - - void on_NB_switch_page(Gtk::Widget* page, guint page_num); - public: FilePanel (); ~FilePanel (); @@ -107,6 +81,32 @@ class FilePanel : public Gtk::HPaned, bool handleShortcutKey (GdkEventKey* event); void updateTPVScrollbar (bool hide); void updateTabsUsesIcons (bool useIcons); + +private: + void on_NB_switch_page(Gtk::Widget* page, guint page_num); + + PlacesBrowser* placesBrowser; + RecentBrowser* recentBrowser; + + Inspector* inspectorPanel; + Gtk::VPaned* tpcPaned; + BatchToolPanelCoordinator* tpc; + History* history; + RTWindow* parent; + Gtk::Notebook* rightNotebook; + sigc::connection rightNotebookSwitchConn; + + struct pendingLoad { + bool complete; + ProgressConnector *pc; + Thumbnail *thm; + }; + MyMutex pendingLoadMutex; + std::vector pendingLoads; + + int error; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 43bfc11b0c..e8310ff0ef 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -43,6 +43,53 @@ guint add_idle (GSourceFunc function, gpointer data) //gtk_main_iteration_do(false); } +IdleRegister::~IdleRegister() +{ + destroy(); +} + +void IdleRegister::add(GSourceFunc function, gpointer data) +{ + struct DataWrapper { + IdleRegister* const self; + GSourceFunc function; + gpointer data; + }; + + const auto dispatch = [](gpointer data) -> gboolean { + DataWrapper* const data_wrapper = static_cast(data); + + if (!data_wrapper->function(data_wrapper->data)) { + data_wrapper->self->mutex.lock(); + data_wrapper->self->ids.erase(data_wrapper); + data_wrapper->self->mutex.unlock(); + + delete data_wrapper; + return FALSE; + } + + return TRUE; + }; + + DataWrapper* const data_wrapper = new DataWrapper{ + this, + function, + data + }; + + mutex.lock(); + ids[data_wrapper] = add_idle(dispatch, data_wrapper); + mutex.unlock(); +} + +void IdleRegister::destroy() +{ + mutex.lock(); + for (const auto id : ids) { + g_source_remove(id.second); + } + mutex.unlock(); +} /* gboolean giveMeAGo(void* data) { diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index e5919c9e45..12370a571d 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -19,13 +19,17 @@ #ifndef __GUI_UTILS_ #define __GUI_UTILS_ +#include + #include + #include -#include "../rtengine/rtengine.h" + #include "../rtengine/coord.h" +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" + #include "rtimage.h" -#include -#include Glib::ustring escapeHtmlChars(const Glib::ustring &src); bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true); @@ -40,6 +44,20 @@ void setExpandAlignProperties(Gtk::Widget *widget, bool hExpand, bool vExpand, e guint add_idle (GSourceFunc function, gpointer data); +class IdleRegister final : + public rtengine::NonCopyable +{ +public: + ~IdleRegister(); + + void add(GSourceFunc function, gpointer data); + void destroy(); + +private: + std::map ids; + MyMutex mutex; +}; + // TODO: The documentation says gdk_threads_enter and gdk_threads_leave should be replaced // by g_main_context_invoke(), g_idle_add() and related functions, but this will require more extensive changes. // We silence those warnings until then so that we notice the others. diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 0504a39340..bf2d4ce675 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -118,7 +118,7 @@ Resize::Resize () : FoldableToolPanel(this, "resize", M("TP_RESIZE_LABEL"), fals Resize::~Resize () { - + idle_register.destroy(); delete scale; delete sizeBox; } @@ -352,68 +352,76 @@ void Resize::sizeChanged (int mw, int mh, int ow, int oh) void Resize::setDimensions () { + const auto func = [](gpointer data) -> gboolean { + Resize* const self = static_cast(data); - int refw, refh; + self->wconn.block(true); + self->hconn.block(true); + self->scale->block(true); - wconn.block (true); - hconn.block (true); - scale->block(true); + int refw, refh; - if (appliesTo->get_active_row_number() == 0 && cropw) { - // Applies to Cropped area - refw = cropw; - refh = croph; - } else { - // Applies to Full image or crop is disabled - refw = maxw; - refh = maxh; - } + if (self->appliesTo->get_active_row_number() == 0 && self->cropw) { + // Applies to Cropped area + refw = self->cropw; + refh = self->croph; + } else { + // Applies to Full image or crop is disabled + refw = self->maxw; + refh = self->maxh; + } - GThreadLock lock; - w->set_range (32, 4 * refw); - h->set_range (32, 4 * refh); + self->w->set_range(32, 4 * refw); + self->h->set_range(32, 4 * refh); - double tmpScale; + switch (self->spec->get_active_row_number()) { + case 0: { + // Scale mode + self->w->set_value(static_cast(static_cast(static_cast(refw) * self->scale->getValue() + 0.5))); + self->h->set_value(static_cast(static_cast(static_cast(refh) * self->scale->getValue() + 0.5))); + break; + } - switch (spec->get_active_row_number()) { - case (0): // Scale mode - w->set_value((double)((int)( (double)(refw) * scale->getValue() + 0.5) )); - h->set_value((double)((int)( (double)(refh) * scale->getValue() + 0.5) )); - break; + case 1: { + // Width mode + const double tmp_scale = self->w->get_value() / static_cast(refw); + self->scale->setValue(tmp_scale); + self->h->set_value(static_cast(static_cast(static_cast(refh) * tmp_scale + 0.5))); + break; + } - case (1): // Width mode - tmpScale = w->get_value() / (double)refw; - scale->setValue (tmpScale); - h->set_value((double)((int)( (double)(refh) * tmpScale + 0.5) )); - break; + case 2: { + // Height mode + const double tmp_scale = self->h->get_value() / static_cast(refh); + self->scale->setValue(tmp_scale); + self->w->set_value(static_cast(static_cast(static_cast(refw) * tmp_scale + 0.5))); + break; + } - case (2): // Height mode - tmpScale = h->get_value() / (double)refh; - scale->setValue (tmpScale); - w->set_value((double)((int)( (double)(refw) * tmpScale + 0.5) )); - break; + case 3: { + // Bounding box mode + const double tmp_scale = + self->w->get_value() / self->h->get_value() < static_cast(refw) / static_cast(refh) + ? self->w->get_value() / static_cast(refw) + : self->h->get_value() / static_cast(refh); - case (3): { // Bounding box mode - double wSliderValue = w->get_value(); - double hSliderValue = h->get_value(); + self->scale->setValue(tmp_scale); + break; + } - if ( (wSliderValue / hSliderValue) < ((double)refw / (double)refh)) { - tmpScale = wSliderValue / (double)refw; - } else { - tmpScale = hSliderValue / (double)refh; + default: { + break; + } } - scale->setValue (tmpScale); - break; - } + self->scale->block(false); + self->wconn.block(false); + self->hconn.block(false); - default: - break; - } + return FALSE; + }; - scale->block(false); - wconn.block (false); - hconn.block (false); + idle_register.add(func, this); } void Resize::fitBoxScale() diff --git a/rtgui/resize.h b/rtgui/resize.h index cf640c281d..acba5b4783 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -25,25 +25,13 @@ #include "toolpanel.h" #include "guiutils.h" -class Resize : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::SizeListener +class Resize final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::SizeListener { - -protected: - Adjuster* scale; - Gtk::VBox* sizeBox; - MyComboBoxText* appliesTo; - MyComboBoxText* method; - MyComboBoxText* spec; - MySpinButton* w; - MySpinButton* h; - int maxw, maxh; - int cropw, croph; - sigc::connection sconn, aconn, wconn, hconn; - bool wDirty, hDirty; - ToolParamBlock* packBox; - public: - Resize (); ~Resize (); @@ -75,6 +63,20 @@ class Resize : public ToolParamBlock, public AdjusterListener, public FoldableTo int getComputedHeight (); void notifyBBox (); void updateGUI (); + + Adjuster* scale; + Gtk::VBox* sizeBox; + MyComboBoxText* appliesTo; + MyComboBoxText* method; + MyComboBoxText* spec; + MySpinButton* w; + MySpinButton* h; + int maxw, maxh; + int cropw, croph; + sigc::connection sconn, aconn, wconn, hconn; + bool wDirty, hDirty; + ToolParamBlock* packBox; + IdleRegister idle_register; }; #endif