diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index f0a9608fa..0a267f6dd 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -36,7 +36,7 @@ #35 2015-11-24 updated by mkyral #36 2016-10-18 updated by mkyral #37 2017-01-10 updated by mkyral - +#38 2017-04-26 updated by mkyral ABOUT_TAB_BUILD;Verze ABOUT_TAB_CREDITS;Zásluhy ABOUT_TAB_LICENSE;Licence @@ -71,6 +71,15 @@ CURVEEDITOR_TOOLTIPPASTE;Vložit křivku ze schránky. CURVEEDITOR_TOOLTIPSAVE;Uložit současnou křivku. CURVEEDITOR_TYPE;Typ DIRBROWSER_FOLDERS;Složky +DYNPROFILEEDITOR_DELETE;Smazat +DYNPROFILEEDITOR_EDIT;Upravit +DYNPROFILEEDITOR_EDIT_RULE;Upravit pravidlo dynamického profilu +DYNPROFILEEDITOR_ENTRY_TOOLTIP;Porovnávání rozlišuje velikost písmen.\nPro vložení regulárního výrazu přidejte\nprefix "re:". +DYNPROFILEEDITOR_MOVE_DOWN;Posunout dolů +DYNPROFILEEDITOR_MOVE_UP;Posunout nahoru +DYNPROFILEEDITOR_NEW;Nový +DYNPROFILEEDITOR_NEW_RULE;Nové pravidlo dynamického profilu +DYNPROFILEEDITOR_PROFILE;Profil zpracování EDITWINDOW_TITLE;Editace obrázku EDIT_OBJECT_TOOLTIP;V náhledovém okně zobrazí widget umožňující přizpůsobení nástroje. EDIT_PIPETTE_TOOLTIP;Pro přidání bodu na křivku, podržte klávesu Ctrl a klikněte levým tlačítkem na vybraný bod v náhledu obrázku.\nPro úpravu bodu podržte klávesu Ctrl a klikněte levým tlačítkem na odpovídající oblast v náhledu, následně uvolněte klávesu Ctrl (pokud si přejete jemné změny) a za stálého držení levého tlačítka myši pohybujte myší nahoru a dolů což bude posouvat bod na křivce nahoru a dolů. @@ -97,6 +106,7 @@ EXIFPANEL_RESETALL;Obnovit vše EXIFPANEL_RESETALLHINT;Obnoví původní hodnoty u všech štítků. EXIFPANEL_RESETHINT;Obnoví původní hodnoty u vybraných štítků. EXIFPANEL_SUBDIRECTORY;Podadresář +EXPORT_BYPASS;Kroky zpracování pro přeskočení EXPORT_BYPASS_ALL;Vybrat / Zrušit výběr všeho EXPORT_BYPASS_DEFRINGE;Vynechat odstranění lemu EXPORT_BYPASS_DIRPYRDENOISE;Vynechat redukci šumu @@ -119,8 +129,12 @@ EXPORT_FASTEXPORTOPTIONS;Volby rychlého exportu EXPORT_INSTRUCTIONS;Volba rychlého exportu umožňuje potlačit vybrané nastavení procesu vyvolání a zkrátit tak čas a zdroje potřebné pro zpracování fronty tím, že se pro vyvolání použije nastavení rychlého exportu. Tato metoda je doporučována pro rychlejší vyvolání obrázků v nižším rozlišení v případě, že je důležitá rychlost, nebo pokud je požadováno vyvolání jednoho nebo více obrázků v nižším rozlišení bez změny uložených parametrů vyvolání. EXPORT_MAXHEIGHT;Maximální výška: EXPORT_MAXWIDTH;Maximální šířka: +EXPORT_PIPELINE;Fronta zpracování EXPORT_PUTTOQUEUEFAST; Vložit do fronty pro rychlý export EXPORT_RAW_DMETHOD;Metoda demozajkování +EXPORT_USE_FAST_PIPELINE;Vyhrazený (kompletní zpracování zmenšeného obrázku) +EXPORT_USE_FAST_PIPELINE_TIP;Použije vyhrazenou frontu zpracování v režimu rychlého exportu a vymění tak kvalitu za rychlost. Zmenšení obrázku se provede co nejdříve po zahájení zpracování, na rozdíl od standardního zpracování, kde se provádí až na závěr. Zrychlení může být velmi významné, ale připravte se na artefakty a celkové zhoršení kvality výstupu. +EXPORT_USE_NORMAL_PIPELINE;Standardní (přeskočí některé kroky, zmenší až na konci) EXTPROGTARGET_1;raw EXTPROGTARGET_2;Zpracování fronty FILEBROWSER_ADDDELTEMPLATE;Přidat/Smazat šablony... @@ -143,7 +157,6 @@ FILEBROWSER_DELETEDLGMSG;Jste si jisti, že chcete vymazat %1 vybraných FILEBROWSER_DELETEDLGMSGINCLPROC;Jste si jisti, že chcete vymazat %1 vybraných souborů včetně výstupů dávkového zpracování? FILEBROWSER_EMPTYTRASH;Vysypat koš FILEBROWSER_EMPTYTRASHHINT;Trvale smazat soubory z koše, -FILEBROWSER_EXEC_CPB;Vlastní generátor profilu FILEBROWSER_EXTPROGMENU;Otevřít pomocí FILEBROWSER_FLATFIELD;Flat Field FILEBROWSER_MOVETODARKFDIR;Přesunout do složky tmavých snímků @@ -193,6 +206,7 @@ FILEBROWSER_RANK3_TOOLTIP;Hodnocení 3 *\nZkratka: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Hodnocení 4 *\nZkratka: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Hodnocení 5 *\nZkratka: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Přejmenování souboru +FILEBROWSER_RESETDEFAULTPROFILE;Vrátit se k původnímu FILEBROWSER_SELECTDARKFRAME;Výběr tmavého snímku... FILEBROWSER_SELECTFLATFIELD;Výběr Flat Field... FILEBROWSER_SHOWCOLORLABEL1HINT;Ukázat obrázky s červeným štítkem.\nZkratka: Alt-1 @@ -710,6 +724,38 @@ HISTORY_MSG_440;Metoda KdDÚ HISTORY_MSG_441;Retinex - Přenos zisku HISTORY_MSG_442;Retinex - Měřítko HISTORY_MSG_443;Kompenzace výstupního černého bodu +HISTORY_MSG_444;VB - Zdůraznění teploty +HISTORY_MSG_445;Raw Dílčí snímek +HISTORY_MSG_446;EvPixelShiftMotion +HISTORY_MSG_447;EvPixelShiftMotionCorrection +HISTORY_MSG_448;EvPixelShiftStddevFactorGreen +HISTORY_MSG_449;PS přizpůsobení ISO +HISTORY_MSG_450;EvPixelShiftNreadIso +HISTORY_MSG_451;EvPixelShiftPrnu +HISTORY_MSG_452;PS Ukázat pohyb +HISTORY_MSG_453;PS Zobrazit jen masku +HISTORY_MSG_454;EvPixelShiftAutomatic +HISTORY_MSG_455;EvPixelShiftNonGreenHorizontal +HISTORY_MSG_456;EvPixelShiftNonGreenVertical +HISTORY_MSG_457;PS Kontrola červená/modrá +HISTORY_MSG_458;EvPixelShiftStddevFactorRed +HISTORY_MSG_459;EvPixelShiftStddevFactorBlue +HISTORY_MSG_460;EvPixelShiftGreenAmaze +HISTORY_MSG_461;EvPixelShiftNonGreenAmaze +HISTORY_MSG_462;PS Kontrola zelená +HISTORY_MSG_463;EvPixelShiftRedBlueWeight +HISTORY_MSG_464;PS Maska pohybové neostrosti +HISTORY_MSG_465;PS Poloměr rozostření +HISTORY_MSG_466;EvPixelShiftSum +HISTORY_MSG_467;EvPixelShiftExp0 +HISTORY_MSG_468;PS Vyplnit díry +HISTORY_MSG_469;PS Medián +HISTORY_MSG_470;EvPixelShiftMedian3 +HISTORY_MSG_471;PS korekce pohybu +HISTORY_MSG_472;PS plynulé přechody +HISTORY_MSG_473;PS Použít LMMSE +HISTORY_MSG_474;PS korekce +HISTORY_MSG_475;PS korekce kanálu HISTORY_NEWSNAPSHOT;Přidat HISTORY_NEWSNAPSHOT_TOOLTIP;Zkratka: Alt-s HISTORY_SNAPSHOT;Snímek @@ -766,7 +812,7 @@ MAIN_BUTTON_SAVE_TOOLTIP;Uložit současný obrázek.\nZkratka: Ctrl+s MAIN_BUTTON_SENDTOEDITOR;Upravit obrázek v externím editoru MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Editovat současný obrázek v externím editoru.\nZkratka: Ctrl+e MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP;Zobrazit/skrýt všechny postranní panely.\nZkratka: m -MAIN_BUTTON_UNFULLSCREEN;Ukončit mód celé obrazovky +MAIN_BUTTON_UNFULLSCREEN;Ukončit režim celé obrazovky MAIN_FRAME_BATCHQUEUE;Fronta MAIN_FRAME_BATCHQUEUE_TOOLTIP;Fronta zpracování.\nZkratka: Ctrl-F3 MAIN_FRAME_EDITOR;Editor @@ -890,8 +936,8 @@ PARTIALPASTE_PREPROCESS_HOTPIXFILT;Filtr vypálených pixelů PARTIALPASTE_PREPROCESS_LINEDENOISE;Filtrovat linkové rušení PARTIALPASTE_PRSHARPENING;Doostření po změně velikosti PARTIALPASTE_RAWCACORR_AUTO;Automatická korekce CA -PARTIALPASTE_RAWCACORR_CABLUE;CA modrá -PARTIALPASTE_RAWCACORR_CARED;CA červená +PARTIALPASTE_RAWCACORR_CAAUTOSTRENGTH;CA Síla automatická korekce +PARTIALPASTE_RAWCACORR_CAREDBLUE;CA červená a modrá PARTIALPASTE_RAWEXPOS_BLACK;Úrovně černé PARTIALPASTE_RAWEXPOS_LINEAR;Korekce bílého bodu PARTIALPASTE_RAWEXPOS_PRESER;Zachování světel @@ -900,7 +946,9 @@ PARTIALPASTE_RAW_DCBENHANCE;Vylepšení DCB PARTIALPASTE_RAW_DCBITERATIONS;Průchody DCB PARTIALPASTE_RAW_DMETHOD;Metoda demozajkování PARTIALPASTE_RAW_FALSECOLOR;Potlačení chybných barev +PARTIALPASTE_RAW_IMAGENUM;Dílčí snímek PARTIALPASTE_RAW_LMMSEITERATIONS;Kroky rozšíření LMMSE +PARTIALPASTE_RAW_PIXELSHIFT;PixelShift PARTIALPASTE_RESIZE;Změna velikosti PARTIALPASTE_RETINEX;Retinex PARTIALPASTE_RGBCURVES;RGB křivky @@ -979,9 +1027,11 @@ PREFERENCES_DIRSOFTWARE;Instalační složka PREFERENCES_EDITORCMDLINE;Jiný příkaz PREFERENCES_EDITORLAYOUT;Rozvržení editoru PREFERENCES_EXPAUT;Expert +PREFERENCES_EXTENDEDZOOMLEVELS;Použít jemné úrovně zvětšení v režimu "Přizpůsobení obrazovce" +PREFERENCES_EXTENDEDZOOMLEVELS_TOOLTIP;Dovolí lépe vyplnit okno editoru ve všech režimech "přizpůsobit obrazovce". Ovšem kvalita náhledu může být mírně zhoršená v závislosti na vypočteném faktoru zvětšení. PREFERENCES_EXTERNALEDITOR;Externí editor PREFERENCES_FBROWSEROPTS;Volby prohlížeče souborů / náhledů -PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Jednořádková lišta nástrojů v prohlížeči souborů (vypněte na nízkých rozlišeních) +PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Jednořádková lišta nástrojů v prohlížeči souborů\n(vypněte na nízkých rozlišeních) PREFERENCES_FILEFORMAT;Formát souboru PREFERENCES_FILMSIMULATION;Simulace filmu PREFERENCES_FLATFIELD;Flat Field @@ -1051,7 +1101,7 @@ PREFERENCES_OUTDIR;Výstupní složka PREFERENCES_OUTDIRFOLDER;Ulož do souboru PREFERENCES_OUTDIRFOLDERHINT;Uložit obrázky do vybrané složky. PREFERENCES_OUTDIRTEMPLATE;Použít šablonu -PREFERENCES_OUTDIRTEMPLATEHINT;Lze použít následující formátovací řetězce:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nTyto formátovací řetězce reprezentují různé části cesty k uložené fotografii, některé vlastnosti fotografie nebo pořadí v dávce.\n\nNapříklad pokud má zpracovávaná fotografie následující cestu:\n/home/tomas/fotky/2010-10-31/dsc0042.nef,\nmají jednotlivé formátovací řetězce tento význam:\n%d4 = home\n%d3 = tomas\n%d2 = fotky\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tomas/fotky/2010-10-31/\n%p2 = /home/tomas/fotky/\n%p3 = /home/tomas/\n%p4 = /home/\n\n%r bude nahrazeno hodnocením fotografie. Pokud není fotografie ohodnocena, bude %r nahrazeno '0'. Pokud je fotografie v koši, bude %r nahrazeno 'x'.\n\n%s1, %s2, atd. bude nahrazeno pořadím v dávce doplněném na 1 až 9 číslic. Každé spuštění zpracování fronty jej vždy nastaví na jedna a po každé zpracované fotografii se o jedna zvýší .\n\nPokud si přejete uložit výstupní obrázek vedle originálu, napište:\n%p1/%f\n\nPokud si jej ale přejete uložit do adresáře "zpracovano" ve stejném adresáři jako otevřený obrázek, napište:\n%p1/zpracovano/%f\n\nPro uložení výstupního obrázku do adresáře "/home/tom/fotky/zpracovano/2010-10-31", napište:\n%p2/zpracovano/%d1/%f +PREFERENCES_OUTDIRTEMPLATEHINT;Lze použít následující formátovací řetězce:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nTyto formátovací řetězce reprezentují různé části cesty k uložené fotografii, některé vlastnosti fotografie nebo pořadí v dávce.\n\nNapříklad pokud má zpracovávaná fotografie následující cestu:\n/home/tomas/fotky/2010-10-31/dsc0042.nef,\nmají jednotlivé formátovací řetězce tento význam:\n%d4 = home\n%d3 = tomas\n%d2 = fotky\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tomas/fotky/2010-10-31/\n%p2 = /home/tomas/fotky/\n%p3 = /home/tomas/\n%p4 = /home/\n\n%r bude nahrazeno hodnocením fotografie. Pokud není fotografie ohodnocena, bude %r nahrazeno '0'. Pokud je fotografie v koši, bude %r nahrazeno 'x'.\n\n%s1, %s2, atd. bude nahrazeno pořadím v dávce doplněném na 1 až 9 číslic. Každé spuštění zpracování fronty jej vždy nastaví na jedna a po každé zpracované fotografii se o jedna zvýší .\n\nPokud si přejete uložit výstupní obrázek vedle originálu, napište:\n%p1/%f\n\nPokud si jej ale přejete uložit do adresáře "zpracovano" ve stejném adresáři jako otevřený obrázek, napište:\n%p1/zpracovano/%f\n\nPro uložení výstupního obrázku do adresáře\n"/home/tom/fotky/zpracovano/2010-10-31", napište:\n%p2/zpracovano/%d1/%f PREFERENCES_OVERLAY_FILENAMES;Překrýt jména souborů na náhledech v prohlížeči souborů PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Překrýt jména souborů na náhledech v editoru PREFERENCES_OVERWRITEOUTPUTFILE;Přepsat existující soubory @@ -1070,9 +1120,11 @@ PREFERENCES_PRINTER;Tiskárna (obtah) PREFERENCES_PROFILEHANDLING;Řízení profilů zpracování PREFERENCES_PROFILELOADPR;Priorita nahrávání profilů zpracování PREFERENCES_PROFILEPRCACHE;Profil v mezipaměti -PREFERENCES_PROFILEPRFILE;Profil uložený se zdrojovým souborem -PREFERENCES_PROFILESAVECACHE;Ukládat parametry zpracování do mezipaměti -PREFERENCES_PROFILESAVEINPUT;Ukládat parametry zpracování spolu se zdrojovým souborem +PREFERENCES_PROFILEPRFILE;Profil uložený se vstupním souborem +PREFERENCES_PROFILESAVEBOTH;Ukládat profil zpracování do mezipaměti a zároveň i se vstupním souborem +PREFERENCES_PROFILESAVECACHE;Ukládat profil zpracování do mezipaměti +PREFERENCES_PROFILESAVEINPUT;Ukládat profil zpracování spolu se vstupním souborem +PREFERENCES_PROFILESAVELOCATION;Místo uložení profilů zpracování PREFERENCES_PROFILE_NONE;Nic PREFERENCES_PROPERTY;Vlastnost PREFERENCES_PRTINTENT;Reprodukční záměr @@ -1082,7 +1134,7 @@ PREFERENCES_REMEMBERZOOMPAN;Zapamatovat si procento přiblížení a posun obrá PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Zapamatovat si procento přiblížení a posun aktuálního obrázku a použít tyto hodnoty při otevírání nového obrázku.\n\nTato volba funguje pouze v režimu "Mód jedné karty editoru" a volba "Metoda demozajkování pro náhled při přiblížení menším než 100%" je nastavena na "Stejně jako v PP3". PREFERENCES_RGBDTL_LABEL;Maximální počet vláken pro redukci šumu a úrovně vlnky PREFERENCES_RGBDTL_TOOLTIP;Pro automatické nastavení maximálního možného počtu vláken ponechte nastaveno na "0". Čím více vláken běží paralelně, tím rychlejší je výpočet. Paměťové nároky najdete na RawPedii. -PREFERENCES_SELECTFONT;Vyberte globální písmo +PREFERENCES_SELECTFONT;Vyberte hlavní písmo PREFERENCES_SELECTFONT_COLPICKER;Vybrat písmo pro Průzkumníka barev PREFERENCES_SELECTLANG;Volba jazyka PREFERENCES_SELECTTHEME;Zvolit vzhled @@ -1108,6 +1160,7 @@ PREFERENCES_STARTUPIMDIR;Složka obrázků při spuštění PREFERENCES_STDAUT;Běžný PREFERENCES_TAB_BROWSER;Prohlížeč souborů PREFERENCES_TAB_COLORMGR;Správa barev +PREFERENCES_TAB_DYNAMICPROFILE;Pravidla dynamických profilů PREFERENCES_TAB_GENERAL;Obecné PREFERENCES_TAB_IMPROC;Zpracování obrázku PREFERENCES_TAB_PERFORMANCE;Výkon a kvalita @@ -1136,6 +1189,7 @@ PROFILEPANEL_MODE_TIP;Režim uplatnění profilu zpracování.\n\nTlačítko je PROFILEPANEL_MYPROFILES;Mé profily PROFILEPANEL_PASTEPPASTE;Parametry pro vložení PROFILEPANEL_PCUSTOM;Vlastní +PROFILEPANEL_PDYNAMIC;Dynamiký PROFILEPANEL_PFILE;Ze souboru PROFILEPANEL_PINTERNAL;Neutrální PROFILEPANEL_PLASTSAVED;Poslední uschovaný @@ -1328,7 +1382,7 @@ TP_COLORAPP_SURROUND_DIM;Tlumené TP_COLORAPP_SURROUND_EXDARK;Velmi tmavé TP_COLORAPP_SURROUND_TOOLTIP;Změní tóny a barvy dle podmínek prohlížení na výstupním zařízení\n\nPrůměrné: Průměrné osvětlení prostředí (standardní). Obrázek nebude změněn.\n\nTlumené: Tlumené prostředí (TV). Obrázek bude mírně ztmaven.\n\nTmavé: Tmavé prostředí (projektor). Obrázek bude více tmavý.\n\nVelmi tmavé: Velmi tmavé prostředí (cutsheet). Obrázek bude velmi tmavý. TP_COLORAPP_SURSOURCE;Tmavé okolí -TP_COLORAPP_SURSOURCE_TOOLTIP;Může být použito pokud má zdrojový obrázek tmavý okraj. +TP_COLORAPP_SURSOURCE_TOOLTIP;Může být použito, pokud má vstupní obrázek tmavý okraj. TP_COLORAPP_TCMODE_BRIGHTNESS;Jas TP_COLORAPP_TCMODE_CHROMA;Barevnost TP_COLORAPP_TCMODE_COLORF;Pestrobarevnost @@ -1678,21 +1732,84 @@ TP_RAWEXPOS_LINEAR;Korekce bílého bodu TP_RAWEXPOS_PRESER;Zachování světel TP_RAWEXPOS_RGB;Červená, telená, modrá TP_RAWEXPOS_TWOGREEN;Spojit zelené +TP_RAW_1PASSMEDIUM;Jeden průchod (střední) +TP_RAW_3PASSBEST;Tři průchody (nejlepší) +TP_RAW_AHD;AHD +TP_RAW_AMAZE;AMaZE +TP_RAW_DCB;DCB TP_RAW_DCBENHANCE;Vylepšení DCB TP_RAW_DCBITERATIONS;Počet průchodů DCB TP_RAW_DMETHOD;Metoda TP_RAW_DMETHOD_PROGRESSBAR;%1 demozajkování... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Vylepšení demozajkování... -TP_RAW_DMETHOD_TOOLTIP;Poznámka: IGV a LMMSE jsou určeny pro obrázky s vysokým ISO, kde pomáhají redukci šumu minimalizovat posterizaci a vyžehlený vzhled. +TP_RAW_DMETHOD_TOOLTIP;Poznámka: IGV a LMMSE jsou určeny pro obrázky s vysokým ISO, kde pomáhají redukci šumu minimalizovat posterizaci a vyžehlený vzhled.\n\nPixel Shift je určen pro soubory Pentax Pixel Shift.\nPro soubory neobsahující Pixel Shift data je použita metoda AMaZE. +TP_RAW_EAHD;EAHD TP_RAW_FALSECOLOR;Počet kroků potlačování chybných barev +TP_RAW_FAST;Rychlá TP_RAW_HD;Práh TP_RAW_HD_TOOLTIP;Nižší hodnoty učiní detekci vypálených/mrtvých bodů agresivnější, ale falešná hlášení mohou vést k artefaktům. Pokud po povolení filtru vypálených/mrtvých bodů zpozorujete výskyt artefaktů, postupně snižujte prahovou hodnotu až do jejich vymizení. +TP_RAW_HPHD;HPHD +TP_RAW_IGV;IGV +TP_RAW_IMAGENUM;Dílčí snímek +TP_RAW_IMAGENUM_TOOLTIP;Některé Raw soubory mohou obsahovat několik dílčích snímků (HDR, Pixel Shift, Dual Pixel, Dual Sensitivity). Tímto tlačítkem vyberete konkrétní dílčí snímek. TP_RAW_LABEL;Demozajkování +TP_RAW_LMMSE;LMMSE TP_RAW_LMMSEITERATIONS;Kroky rozšíření LMMSE TP_RAW_LMMSE_TOOLTIP;Přidá gamu (krok 1) - přidá mediány (kroky 2, až 4) a následně přidá (kroky 5 a 6) vyčištění artefaktů a vylepšení poměru signálu a šumu. +TP_RAW_MONO;Mono +TP_RAW_NONE;Žádná (zobrazí strukturu senzoru) +TP_RAW_PIXELSHIFT;Pixel Shift +TP_RAW_PIXELSHIFTADAPTIVE;Přizpůsobivá detekce +TP_RAW_PIXELSHIFTBLUR;Maska pohybové neostrosti +TP_RAW_PIXELSHIFTBLUR_TOOLTIP;Maska pohybové neostrosti +TP_RAW_PIXELSHIFTEPERISO;Přizpůsobení ISO +TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;Výchozí hodnota (0,0) by měla dostačovat pro základní hodnoty ISO.\nDetekci pohybu na vyšších hodnotách ISO vylepšíte navýšením této hodnoty.\nZvyšujte po malých krocích a sledujte přitom masku pohybu. +TP_RAW_PIXELSHIFTEQUALBRIGHT;Vyrovnat jas snímků +TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL;Korekce po kanálech +TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL_TOOLTIP;Zapnuto: Nezávislá korekce jednotlivých RGB kanálů.\nVypnuto: Použije se stejná hodnota pro všechny kanály. +TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP;Vyrovná jas ostatních snímků podle jasu vybraného snímku.\nPokud jsou ve snímku přeexponované oblasti, vyberte jasnější snímek abyste zamezili výskytu purpurové barvy v přeexponovaných oblastech nebo povolte korekci pohybu. +TP_RAW_PIXELSHIFTEXP0;Testovací +TP_RAW_PIXELSHIFTGREEN;Kontrolovat zelený kanál na pohyb +TP_RAW_PIXELSHIFTHOLEFILL;Vyplnit díry v masce pohybu +TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Vyplnit díry v masce pohybu +TP_RAW_PIXELSHIFTLMMSE;Použít LMMSE pro části s pohybem +TP_RAW_PIXELSHIFTLMMSE_TOOLTIP;Pro oblasti s pohybem použít LMMSE namísto AMaZE.\nUžitečné pro fotografie s vysokým ISO. +TP_RAW_PIXELSHIFTMASKTHRESHOLD;3x3 nový práh +TP_RAW_PIXELSHIFTMEDIAN;Medián +TP_RAW_PIXELSHIFTMEDIAN3;Vyjmout vybraný snímek z mediánu +TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP;Vyjme vybraný snímek z mediánu.\nUžitečné, pokud se pohybující se objekty překrývají jen ve druhém a třetím. +TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Pro oblasti s pohybem použijte medián všech snímků namísto vybraného.\nOdstraní objekty, které jsou na všech snímcích na různých místech.\nVytvoří efekt pohybu pro pomalu se pohybující (překrývající se) objekty. +TP_RAW_PIXELSHIFTMM_AUTO;Automatická +TP_RAW_PIXELSHIFTMM_CUSTOM;Vlastní +TP_RAW_PIXELSHIFTMM_OFF;Vypnuto +TP_RAW_PIXELSHIFTMOTION;Úroveň kontroly pohybu (zastaralé) +TP_RAW_PIXELSHIFTMOTIONCORRECTION;Míra korekce pohybu v zelené +TP_RAW_PIXELSHIFTMOTIONCORRECTION_TOOLTIP;1 = 2 pixely\n3 = mřížka 3x3\n5 = mřížka 5x5 +TP_RAW_PIXELSHIFTMOTIONMETHOD;Korekce pohybu +TP_RAW_PIXELSHIFTMOTION_TOOLTIP;0 znamená bez detekce pohybu\n1 - 99 znamená, že pohybu bude detekován dle této hodnoty. Pro zvýšení míry detekce použijte vyšší hodnotu\n100 znamená, že bude použito AMaZE demozajkování snímku +TP_RAW_PIXELSHIFTNONGREENAMAZE;Kontrolovat červené/modré AMaZE +TP_RAW_PIXELSHIFTNONGREENCROSS;Kontrolovat pohyb v červeném a modrém kanálu +TP_RAW_PIXELSHIFTNONGREENCROSS2;Kontrolovat zelené amaze +TP_RAW_PIXELSHIFTNONGREENHORIZONTAL;Kontrolovat červenou/modrou vodorovně +TP_RAW_PIXELSHIFTNONGREENVERTICAL;Kontrolovat červenou/modrou svisle +TP_RAW_PIXELSHIFTNREADISO;nRead +TP_RAW_PIXELSHIFTPRNU;PRNU (%) +TP_RAW_PIXELSHIFTREDBLUEWEIGHT;Váha červené a modré +TP_RAW_PIXELSHIFTSHOWMOTION;Ukázat pohyb +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Zobrazit pouze masku +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Ukázat masku pohybu bez obrázku +TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Překryje obrázek maskou, která ukazuje oblasti s pohybem +TP_RAW_PIXELSHIFTSIGMA;Poloměr rozostření +TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;Výchozí poloměr 1,0 většinou dobře funguje pro základní ISO. U snímků s vyšším ISO poloměr zvětšete.\nHodnota 5,0 je dobrým výchozím bodem pro snímky pořízené na vysoké ISO.\nBěhem změny hodnoty poloměru sledujte masku pohybu. +TP_RAW_PIXELSHIFTSMOOTH;Hladké přechody +TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Plynulé přechody mezi místy s pohybem a bez něj.\nNastavte 0 pro zakázání plynulých přechodů\nNastavte 1 pro použití AMaZE/LMMSE nebo Median +TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE;StdDev faktor modrý +TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN;StdDev faktor zelený +TP_RAW_PIXELSHIFTSTDDEVFACTORRED;StdDev faktor červený TP_RAW_SENSOR_BAYER_LABEL;Snímač s Bayerovou maskou TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;Tří průchodová dává lepší výsledky (doporučeno pro fotky s nízkým ISO).\nJednoprůchodová je téměř k nerozeznání od tří průchodové pro vysoké ISO a je rychlejší. TP_RAW_SENSOR_XTRANS_LABEL;Senzory s X-Trans maticí +TP_RAW_VNG4;VNG4 TP_RESIZE_APPLIESTO;Aplikovat na: TP_RESIZE_CROPPEDAREA;Oblast ořezu TP_RESIZE_FITBOX;Výřez @@ -2057,6 +2174,8 @@ TP_WBALANCE_SOLUX41;Solux 4100K TP_WBALANCE_SOLUX47;Solux 4700K (vendor) TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) TP_WBALANCE_SPOTWB;Bodové vyvážení +TP_WBALANCE_TEMPBIAS;AVB - Zdůraznění teploty +TP_WBALANCE_TEMPBIAS_TOOLTIP;Dovolí ovlivnit výpočet "automatického vyvážení bílé"\nzdůrazněním teplejší nebo chladnější teploty. Toto zdůraznění\nje vyjádřeno v procentech vypočtené teploty a výsledek\nlze vyjádřit vzorcem "vypočtenáTeplota + vypočtenáTeplota * zdůraznění". TP_WBALANCE_TEMPERATURE;Teplota TP_WBALANCE_TUNGSTEN;Wolfram TP_WBALANCE_WATER1;Pod vodou 1 @@ -2069,130 +2188,3 @@ ZOOMPANEL_ZOOMFITCROPSCREEN;Přizpůsobit obrazovce\nZkratka: Alt-ff ZOOMPANEL_ZOOMIN;Přiblížit\nZkratka: + ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - - -!!!!!!!!!!!!!!!!!!!!!!!!! -! Untranslated keys follow; remove the ! prefix after an entry is translated. -!!!!!!!!!!!!!!!!!!!!!!!!! - -!DYNPROFILEEDITOR_DELETE;Delete -!DYNPROFILEEDITOR_EDIT;Edit -!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule -!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. -!DYNPROFILEEDITOR_MOVE_DOWN;Move Down -!DYNPROFILEEDITOR_MOVE_UP;Move Up -!DYNPROFILEEDITOR_NEW;New -!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule -!DYNPROFILEEDITOR_PROFILE;Processing Profile -!EXPORT_BYPASS;Processing steps to bypass -!EXPORT_PIPELINE;Processing pipeline -!EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image) -!EXPORT_USE_FAST_PIPELINE_TIP;Use a dedicated processing pipeline for images in Fast Export mode, that trades speed for quality. Resizing of the image is done as early as possible, instead of doing it at the end like in the normal pipeline. The speedup can be significant, but be prepared to see artifacts and a general degradation of output quality. -!EXPORT_USE_NORMAL_PIPELINE;Standard (bypass some steps, resize at the end) -!FILEBROWSER_RESETDEFAULTPROFILE;Reset to default -!HISTORY_MSG_444;WB - Temp bias -!HISTORY_MSG_445;Raw Sub-Image -!HISTORY_MSG_446;EvPixelShiftMotion -!HISTORY_MSG_447;EvPixelShiftMotionCorrection -!HISTORY_MSG_448;EvPixelShiftStddevFactorGreen -!HISTORY_MSG_449;PS ISO adaption -!HISTORY_MSG_450;EvPixelShiftNreadIso -!HISTORY_MSG_451;EvPixelShiftPrnu -!HISTORY_MSG_452;PS Show motion -!HISTORY_MSG_453;PS Show mask only -!HISTORY_MSG_454;EvPixelShiftAutomatic -!HISTORY_MSG_455;EvPixelShiftNonGreenHorizontal -!HISTORY_MSG_456;EvPixelShiftNonGreenVertical -!HISTORY_MSG_457;PS Check red/blue -!HISTORY_MSG_458;EvPixelShiftStddevFactorRed -!HISTORY_MSG_459;EvPixelShiftStddevFactorBlue -!HISTORY_MSG_460;EvPixelShiftGreenAmaze -!HISTORY_MSG_461;EvPixelShiftNonGreenAmaze -!HISTORY_MSG_462;PS Check green -!HISTORY_MSG_463;EvPixelShiftRedBlueWeight -!HISTORY_MSG_464;PS Blur motion mask -!HISTORY_MSG_465;PS Blur radius -!HISTORY_MSG_466;EvPixelShiftSum -!HISTORY_MSG_467;EvPixelShiftExp0 -!HISTORY_MSG_468;PS Fill holes -!HISTORY_MSG_469;PS Median -!HISTORY_MSG_470;EvPixelShiftMedian3 -!HISTORY_MSG_471;PS Motion correction -!HISTORY_MSG_472;PS Smooth transitions -!HISTORY_MSG_473;PS Use lmmse -!HISTORY_MSG_474;PS Equalize -!HISTORY_MSG_475;PS Equalize channel -!PARTIALPASTE_RAWCACORR_CAAUTOSTRENGTH;CA auto-correction strength -!PARTIALPASTE_RAWCACORR_CAREDBLUE;CA red & blue -!PARTIALPASTE_RAW_IMAGENUM;Sub-image -!PARTIALPASTE_RAW_PIXELSHIFT;PixelShift -!PREFERENCES_EXTENDEDZOOMLEVELS;Use finer-grained zoom levels for "fit to screen" zooming -!PREFERENCES_EXTENDEDZOOMLEVELS_TOOLTIP;This allows to better fill the editor window when using one of the "fit to screen" zoom modes. However, the preview quality might be slightly degraded, depending on the actual zoom factor computed. -!PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next to the input file -!PREFERENCES_PROFILESAVELOCATION;Processing profile saving location -!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules -!PROFILEPANEL_PDYNAMIC;Dynamic -!TP_RAW_1PASSMEDIUM;1-Pass (Medium) -!TP_RAW_3PASSBEST;3-Pass (Best) -!TP_RAW_AHD;AHD -!TP_RAW_AMAZE;AMaZE -!TP_RAW_DCB;DCB -!TP_RAW_EAHD;EAHD -!TP_RAW_FAST;Fast -!TP_RAW_HPHD;HPHD -!TP_RAW_IGV;IGV -!TP_RAW_IMAGENUM;Sub-image -!TP_RAW_IMAGENUM_TOOLTIP;Some raw files might embed several sub-images (HDR, Pixel Shift, Dual Pixel, Dual Sensitivity). Use this button to select the sub-image. -!TP_RAW_LMMSE;LMMSE -!TP_RAW_MONO;Mono -!TP_RAW_NONE;None (Shows sensor pattern) -!TP_RAW_PIXELSHIFT;Pixel Shift -!TP_RAW_PIXELSHIFTADAPTIVE;Adaptive detection -!TP_RAW_PIXELSHIFTBLUR;Blur motion mask -!TP_RAW_PIXELSHIFTBLUR_TOOLTIP;Blur motion mask -!TP_RAW_PIXELSHIFTEPERISO;ISO adaption -!TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value (0.0) should work fine for base ISO.\nIncrease the value to improve motion detection for higher ISO.\nIncrease in small steps and watch the motion mask while increasing. -!TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames -!TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL;Equalize per channel -!TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL_TOOLTIP;Enabled: Equalize the channels (RGB) individually.\nDisabled: Use same equalization factor for all channels. -!TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP;Equalize the brightness of the frames to the brightness of the selected frame.\nIf there are overexposed areas in the frames select the brightest frame to avoid magenta colour cast in overexposed areas or enable motion correction. -!TP_RAW_PIXELSHIFTEXP0;Experimental -!TP_RAW_PIXELSHIFTGREEN;Check green channel for motion -!TP_RAW_PIXELSHIFTHOLEFILL;Fill holes in motion mask -!TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Fill holes in motion mask -!TP_RAW_PIXELSHIFTLMMSE;Use lmmse for motion parts -!TP_RAW_PIXELSHIFTLMMSE_TOOLTIP;Use lmmse instead of amaze for motion areas.\nUseful for High ISO images. -!TP_RAW_PIXELSHIFTMASKTHRESHOLD;3x3 new threshold -!TP_RAW_PIXELSHIFTMEDIAN;Median -!TP_RAW_PIXELSHIFTMEDIAN3;Exclude selected frame from median -!TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP;Excludes selected frame from median.\nUseful if moving objects overlap in frame 2 and 3 -!TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Use median of all frames instead of selected frame for regions with motion.\nRemoves objects which are at different places in all frames.\nGives motion effect on slow moving (overlapping) objects. -!TP_RAW_PIXELSHIFTMM_AUTO;Automatic -!TP_RAW_PIXELSHIFTMM_CUSTOM;Custom -!TP_RAW_PIXELSHIFTMM_OFF;Off -!TP_RAW_PIXELSHIFTMOTION;Motion detection level (deprecated) -!TP_RAW_PIXELSHIFTMOTIONCORRECTION;Green motion correction size -!TP_RAW_PIXELSHIFTMOTIONCORRECTION_TOOLTIP;1 = 2 pixels\n3 = 3x3 grid\n5 = 5x5 grid -!TP_RAW_PIXELSHIFTMOTIONMETHOD;Motion Correction -!TP_RAW_PIXELSHIFTMOTION_TOOLTIP;0 means no motion detection\n1 - 99 means motion will be detected according to this value. Increase value to increase detection rate\n100 means the Amaze demosaiced frame will be used -!TP_RAW_PIXELSHIFTNONGREENAMAZE;Check red/blue amaze -!TP_RAW_PIXELSHIFTNONGREENCROSS;Check red/blue channels for motion -!TP_RAW_PIXELSHIFTNONGREENCROSS2;Check green amaze -!TP_RAW_PIXELSHIFTNONGREENHORIZONTAL;Check red/blue horizontal -!TP_RAW_PIXELSHIFTNONGREENVERTICAL;Check red/blue vertical -!TP_RAW_PIXELSHIFTNREADISO;nRead -!TP_RAW_PIXELSHIFTPRNU;PRNU (%) -!TP_RAW_PIXELSHIFTREDBLUEWEIGHT;Red&Blue weight -!TP_RAW_PIXELSHIFTSHOWMOTION;Show motion -!TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Show mask only -!TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Shows the motion mask without the image -!TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Overlays the image with a mask showing the regions with motion -!TP_RAW_PIXELSHIFTSIGMA;Blur radius -!TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;Default radius of 1.0 usually fits good for base ISO. Increase value for high ISO shots,\n5.0 is a good starting point for high ISO shots.\nWatch motion mask while changing the value. -!TP_RAW_PIXELSHIFTSMOOTH;Smooth transitions -!TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions between areas with and without motion.\nSet to 0 to disable smooth transitions\nSet to 1 to get Amaze/lmmse or Median -!TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE;StdDev factor Blue -!TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN;StdDev factor Green -!TP_RAW_PIXELSHIFTSTDDEVFACTORRED;StdDev factor Red -!TP_RAW_VNG4;VNG4 -!TP_WBALANCE_TEMPBIAS;AWB temperature bias -!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 273abb65f..c9a2b395b 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -50,6 +50,7 @@ set(RTENGINESOURCEFILES dfmanager.cc diagonalcurves.cc dirpyr_equalizer.cc + dynamicprofile.cc expo_before_b.cc fast_demo.cc ffmanager.cc @@ -98,6 +99,7 @@ set(RTENGINESOURCEFILES previewimage.cc processingjob.cc procparams.cc + profilestore.cc rawimage.cc rawimagesource.cc refreshmap.cc diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc new file mode 100644 index 000000000..5ac408da5 --- /dev/null +++ b/rtengine/dynamicprofile.cc @@ -0,0 +1,261 @@ +/* -*- C++ -*- + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "../rtengine/dynamicprofile.h" + +#include +#include + +using namespace rtengine; +using namespace rtengine::procparams; + +namespace +{ + +const int ISO_MAX = 512000; +const double FNUMBER_MAX = 100.0; +const double FOCALLEN_MAX = 10000.0; +const double SHUTTERSPEED_MAX = 1000.0; +const double EXPCOMP_MIN = -20.0; +const double EXPCOMP_MAX = 20.0; + +} // namespace + +DynamicProfileRules dynamicProfileRules; + +bool DynamicProfileRule::Optional::operator() (const Glib::ustring &val) const +{ + if (!enabled) { + return true; + } + + if (value.find ("re:") == 0) { + // this is a regexp + return Glib::Regex::match_simple (value.substr (3), val, Glib::REGEX_CASELESS); + } else { + // normal string comparison + return value.casefold() == val.casefold(); + } +} + + +DynamicProfileRule::DynamicProfileRule(): + serial_number (0), + iso (0, ISO_MAX), + fnumber (0, FNUMBER_MAX), + focallen (0, FOCALLEN_MAX), + shutterspeed (0, SHUTTERSPEED_MAX), + expcomp (EXPCOMP_MIN, EXPCOMP_MAX) +{ +} + + +bool DynamicProfileRule::operator< (const DynamicProfileRule &other) const +{ + return serial_number < other.serial_number; +} + + +bool DynamicProfileRule::matches (const rtengine::ImageMetaData *im) const +{ + return (iso (im->getISOSpeed()) + && fnumber (im->getFNumber()) + && focallen (im->getFocalLen()) + && shutterspeed (im->getShutterSpeed()) + && expcomp (im->getExpComp()) + && camera (im->getCamera()) + && lens (im->getLens())); +} + +namespace +{ + +void get_int_range (DynamicProfileRule::Range &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + int min = kf.get_integer (group, key + "_min"); + int max = kf.get_integer (group, key + "_max"); + + if (min <= max) { + dest.min = min; + dest.max = max; + } + } catch (Glib::KeyFileError &e) { + } +} + + +void get_double_range (DynamicProfileRule::Range &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + double min = kf.get_double (group, key + "_min"); + double max = kf.get_double (group, key + "_max"); + + if (min <= max) { + dest.min = min; + dest.max = max; + } + } catch (Glib::KeyFileError &e) { + } +} + + +void get_optional (DynamicProfileRule::Optional &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + bool e = kf.get_boolean (group, key + "_enabled"); + + if (e) { + Glib::ustring s = kf.get_string (group, key + "_value"); + dest.enabled = e; + dest.value = s; + } + } catch (Glib::KeyFileError &) { + } +} + +void set_int_range (Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Range &val) +{ + kf.set_integer (group, key + "_min", val.min); + kf.set_integer (group, key + "_max", val.max); +} + +void set_double_range (Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Range &val) +{ + kf.set_double (group, key + "_min", val.min); + kf.set_double (group, key + "_max", val.max); +} + +void set_optional (Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Optional &val) +{ + kf.set_boolean (group, key + "_enabled", val.enabled); + kf.set_string (group, key + "_value", val.value); +} + +} // namespace + +bool DynamicProfileRules::loadRules() +{ + dynamicRules.clear(); + Glib::KeyFile kf; + + try { + if (!kf.load_from_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg"))) { + return false; + } + } catch (Glib::Error &e) { + return false; + } + + if (options.rtSettings.verbose) { + printf ("loading dynamic profiles...\n"); + } + + auto groups = kf.get_groups(); + + for (auto group : groups) { + // groups are of the form "rule N", where N is a positive integer + if (group.find ("rule ") != 0) { + return false; + } + + std::istringstream buf (group.c_str() + 5); + int serial = 0; + + if (! (buf >> serial) || !buf.eof()) { + return false; + } + + if (options.rtSettings.verbose) { + printf (" loading rule %d\n", serial); + } + + dynamicRules.emplace_back (DynamicProfileRule()); + DynamicProfileRule &rule = dynamicRules.back(); + rule.serial_number = serial; + get_int_range (rule.iso, kf, group, "iso"); + get_double_range (rule.fnumber, kf, group, "fnumber"); + get_double_range (rule.focallen, kf, group, "focallen"); + get_double_range (rule.shutterspeed, kf, group, "shutterspeed"); + get_double_range (rule.expcomp, kf, group, "expcomp"); + get_optional (rule.camera, kf, group, "camera"); + get_optional (rule.lens, kf, group, "lens"); + + try { + rule.profilepath = kf.get_string (group, "profilepath"); + } catch (Glib::KeyFileError &) { + dynamicRules.pop_back(); + } + } + + std::sort (dynamicRules.begin(), dynamicRules.end()); + rulesLoaded = true; + return true; +} + +bool DynamicProfileRules::storeRules() +{ + if (options.rtSettings.verbose) { + printf ("saving dynamic profiles...\n"); + } + + Glib::KeyFile kf; + + for (auto &rule : dynamicRules) { + std::ostringstream buf; + buf << "rule " << rule.serial_number; + Glib::ustring group = buf.str(); + set_int_range (kf, group, "iso", rule.iso); + set_double_range (kf, group, "fnumber", rule.fnumber); + set_double_range (kf, group, "focallen", rule.focallen); + set_double_range (kf, group, "shutterspeed", rule.shutterspeed); + set_double_range (kf, group, "expcomp", rule.expcomp); + set_optional (kf, group, "camera", rule.camera); + set_optional (kf, group, "lens", rule.lens); + kf.set_string (group, "profilepath", rule.profilepath); + } + + return kf.save_to_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg")); +} + +const std::vector &DynamicProfileRules::getRules() +{ + if (!rulesLoaded) { + loadRules(); + } + + return dynamicRules; +} + +void DynamicProfileRules::setRules (const std::vector &r) +{ + dynamicRules = r; +} diff --git a/rtgui/dynamicprofile.h b/rtengine/dynamicprofile.h similarity index 63% rename from rtgui/dynamicprofile.h rename to rtengine/dynamicprofile.h index 4c5e552e4..cfe46d9ba 100644 --- a/rtgui/dynamicprofile.h +++ b/rtengine/dynamicprofile.h @@ -21,18 +21,18 @@ #include #include -#include "options.h" +#include "../rtgui/options.h" - -class DynamicProfileRule { +class DynamicProfileRule +{ public: template struct Range { T min; T max; - explicit Range(T l=T(), T u=T()): min(l), max(u) {} + explicit Range (T l = T(), T u = T()): min (l), max (u) {} - bool operator()(T val) const + bool operator() (T val) const { return val >= min && val <= max; } @@ -41,15 +41,15 @@ public: struct Optional { Glib::ustring value; bool enabled; - explicit Optional(const Glib::ustring v="", bool e=false): - value(v), enabled(e) {} + explicit Optional (const Glib::ustring v = "", bool e = false): + value (v), enabled (e) {} - bool operator()(const Glib::ustring &val) const; + bool operator() (const Glib::ustring &val) const; }; - + DynamicProfileRule(); - bool matches(const rtengine::ImageMetaData *im) const; - bool operator<(const DynamicProfileRule &other) const; + bool matches (const rtengine::ImageMetaData *im) const; + bool operator< (const DynamicProfileRule &other) const; int serial_number; Range iso; @@ -62,13 +62,18 @@ public: Glib::ustring profilepath; }; +class DynamicProfileRules +{ +protected: + /** cache for dynamic profile rules */ + std::vector dynamicRules; + bool rulesLoaded; -bool loadDynamicProfileRules(std::vector &out); -bool storeDynamicProfileRules( - const std::vector &rules); - -rtengine::procparams::PartialProfile *loadDynamicProfile( - const rtengine::ImageMetaData *im); - +public: + bool loadRules(); + bool storeRules(); + const std::vector &getRules(); + void setRules (const std::vector &r); +}; #endif // _DYNAMICPROFILE_H_ diff --git a/rtengine/init.cc b/rtengine/init.cc index 4c66cea68..2d157c762 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "../rtgui/profilestorecombobox.h" #include "rtengine.h" #include "iccstore.h" #include "dcp.h" @@ -27,7 +28,7 @@ #include "dfmanager.h" #include "ffmanager.h" #include "rtthumbnail.h" -#include "../rtgui/profilestore.h" +#include "profilestore.h" #include "../rtgui/threadutils.h" namespace rtengine @@ -40,6 +41,7 @@ MyMutex* lcmsMutex = nullptr; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; + ProfileStore::getInstance()->init (loadAll); ICCStore::getInstance()->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll); diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc new file mode 100644 index 000000000..984ab9423 --- /dev/null +++ b/rtengine/profilestore.cc @@ -0,0 +1,535 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "profilestore.h" + +#include "dynamicprofile.h" +#include "../rtgui/options.h" +#include "../rtgui/multilangmgr.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +ProfileStore::ProfileStore () : storeState (STORESTATE_NOTINITIALIZED), internalDefaultProfile (nullptr), internalDefaultEntry (nullptr), internalDynamicEntry (nullptr), loadAll (true) +{ + internalDefaultProfile = new AutoPartialProfile(); + internalDefaultProfile->set (true); +} + +ProfileStore* ProfileStore::getInstance() +{ + static ProfileStore instance; + return &instance; +} + + +bool ProfileStore::init (bool loadAll) +{ + if (storeState == STORESTATE_DELETED) { + return false; + } + + this->loadAll = loadAll; + + if (storeState == STORESTATE_NOTINITIALIZED && loadAll) { + storeState = STORESTATE_BEINGINITIALIZED; + _parseProfiles (); + storeState = STORESTATE_INITIALIZED; + } + + return storeState == STORESTATE_INITIALIZED; +} + +ProfileStore::~ProfileStore () +{ + if (storeState == STORESTATE_NOTINITIALIZED) { + return; + } + + // This lock prevent object's suppression while scanning the directories + storeState = STORESTATE_DELETED; + + { + MyMutex::MyLock lock (parseMutex); + + clearProfileList (); + partProfiles.clear (); + clearFileList(); + delete internalDefaultProfile; + delete internalDefaultEntry; + delete internalDynamicEntry; + } +} + +/* + * Public method to parse the profiles' directories + * Since there's a race condition in the multithreaded environment on this object, + * parseProfiles may need to ask for initialization of this object, and then will + * ask a mutex lock on it, has it been initialized by this call or not + * + * This method will scan the directory tree again and update the profile list. When finished, + * the listeners will be called in order to update with the new list + */ +void ProfileStore::parseProfiles () +{ + + for (auto listener : listeners) { + listener->storeCurrentValue(); + } + + init (true); // safe even if already initialized + + for (auto listener : listeners) { + listener->updateProfileList(); + listener->restoreValue(); + } +} + +void ProfileStore::_parseProfiles () +{ + // clear loaded profiles + folders.clear(); + clearFileList(); + clearProfileList (); + + folders.push_back ("<<< ROOT >>>"); // Fake path, so parentFolderId == 0 will be used to attach a ProfileStoreEntry to the root container, not sub-menu + + Glib::ustring p1 = options.getUserProfilePath(); + Glib::ustring p2 = options.getGlobalProfilePath(); + bool displayLevel0 = options.useBundledProfiles && !p1.empty() && !p2.empty() && p1 != p2; + + Glib::ustring virtualPath ("${U}"); + Glib::ustring currDir ("${U}"); + parseDir (p1, virtualPath, currDir, 0, 0, displayLevel0); + + if (displayLevel0) { + virtualPath = "${G}"; + currDir = "${G}"; + parseDir (p2, virtualPath, currDir, 0, 0, displayLevel0); + } + + // sort profiles + std::sort (entries.begin(), entries.end(), SortProfiles() ); + + // entries and partProfiles are empty, but the entry and profiles already exist (they have survived to clearFileList and clearProfileList) + if (!internalDefaultEntry) { + internalDefaultEntry = new ProfileStoreEntry (Glib::ustring ("(") + M ("PROFILEPANEL_PINTERNAL") + Glib::ustring (")"), PSET_FILE, 0, 0); + } + + entries.push_back (internalDefaultEntry); + partProfiles[internalDefaultEntry] = internalDefaultProfile; + + if (!internalDynamicEntry) { + internalDynamicEntry = new ProfileStoreEntry (Glib::ustring ("(") + M ("PROFILEPANEL_PDYNAMIC") + Glib::ustring (")"), PSET_FILE, 0, 0); + // do not add it to the entries. This is here only for the preferences dialog + } + + // Check if the default profiles has been found. + if (findEntryFromFullPathU (options.defProfRaw) == nullptr) { + options.setDefProfRawMissing (true); + + if (options.rtSettings.verbose) { + printf ("WARNING: Default profile \"%s\" for raw images not found!\n", options.defProfRaw.c_str()); + } + } + + if (findEntryFromFullPathU (options.defProfImg) == nullptr) { + options.setDefProfImgMissing (true); + + if (options.rtSettings.verbose) { + printf ("WARNING: Default profile \"%s\" for standard images not found!\n", options.defProfImg.c_str()); + } + } +} + +/// @return Returns true if some files has been found (directories are ignored) +bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0) +{ + bool fileFound = false; + + // reload the available profiles from the profile dir + if (!realPath.empty() && Glib::file_test (realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) { + unsigned int folder = 0; // folder's own Id + + // add this entry to the folder list + folders.push_back (virtualPath); + folder = (unsigned int) (folders.size()) - 1; + + if (level > 0 || displayLevel0) { + // replace the virtual folder name by a localized text + if (currDir == "${U}") { + currDir = M ("PROFILEPANEL_MYPROFILES"); + } else if (currDir == "${G}") { + currDir = M ("PROFILEPANEL_GLOBALPROFILES"); + } + + // add this localized text to the file list + entries.push_back ( new ProfileStoreEntry (currDir, PSET_FOLDER, parentId, folder) ); + } + + // walking through the directory + Glib::Dir* dir = nullptr; + dir = new Glib::Dir (realPath); + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { + currDir = *i; + + if (currDir == "." || currDir == "..") { + continue; + } + + Glib::ustring fname = Glib::build_filename (realPath, currDir); + + if (Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { + Glib::ustring vp (Glib::build_filename (virtualPath, currDir)); + Glib::ustring rp (Glib::build_filename (realPath, currDir)); + fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0); + } else { + size_t lastdot = currDir.find_last_of ('.'); + + if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr (lastdot).casefold() == paramFileExtension) { + // file found + if ( options.rtSettings.verbose ) { + printf ("Processing file %s...", fname.c_str()); + } + + Glib::ustring name = currDir.substr (0, lastdot); + + // create the partial profile + AutoPartialProfile *pProf = new AutoPartialProfile(); + int res = pProf->load (fname); + + if (!res && pProf->pparams->ppVersion >= 220) { + fileFound = true; + + if ( options.rtSettings.verbose ) { + printf ("OK\n"); + } + + // adding this file to the list + ProfileStoreEntry* filePSE = new ProfileStoreEntry (name, PSET_FILE, folder, 0); + entries.push_back (filePSE); + + // map the partial profile + partProfiles[filePSE] = pProf; + //partProfiles.insert( std::pair (filePSE, pProf) ); + } else if ( options.rtSettings.verbose ) { + printf ("failed!\n"); + } + } + } + } + + delete dir; + } + + if (!fileFound && (level > 0 || displayLevel0)) { + // no files found in this level, we delete the subdirectory entry + folders.pop_back(); + entries.pop_back(); + } + + return fileFound; +} + +int ProfileStore::findFolderId (const Glib::ustring &path) +{ + // initialization must have been done when calling this + for (std::vector::iterator i = folders.begin(); i != folders.end(); ++i) { + if (*i == path) { + return i - folders.begin(); + } + } + + return -1; +} + +/** @brief Return the ProfileStoreEntry object that match the given file and path + * + * @param fullPath Path of the file; the filename may end by the standard extension, + * but have to begin with a virtual location ( ${G} or ${U} ) + * Will return null on invalid path or if the entry can't be found + */ +const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU (Glib::ustring path) +{ + if (path.empty()) { + return nullptr; + } + + if (storeState == STORESTATE_NOTINITIALIZED) { + parseProfiles(); + } + + if (path == DEFPROFILE_INTERNAL || path == DEFPROFILE_DYNAMIC) { + return internalDefaultEntry; + } + + // consistently apply casefold() to make sure dot position is correct + const Glib::ustring casefolded_path = path.casefold(); + const Glib::ustring::size_type lastdot_pos = casefolded_path.find_last_of ('.'); + + if ( + lastdot_pos != Glib::ustring::npos + && lastdot_pos <= casefolded_path.size() - 4 + && !casefolded_path.compare (lastdot_pos, 4, paramFileExtension) + ) { + // removing the extension + // now use dot position without casefold() + path = path.substr (0, path.find_last_of ('.')); + } + + // dir separator may come from options file and may be \ or /, we convert them to G_DIR_SEPARATOR_S + if (path.size() > 4 && (path[4] == '/' || path[4] == '\\')) { + path = path.substr (0, 4) + G_DIR_SEPARATOR_S + path.substr (5); + } + + // removing the filename + Glib::ustring fName = Glib::path_get_basename (path); + + if (!fName.empty()) { + path = path.substr (0, path.length() - fName.length()); + } else { + // path is malformed, returning NULL; + return nullptr; + } + + path = Glib::path_get_dirname (path); + + // 1. find the path in the folder list + int parentFolderId = findFolderId (path); + + if (parentFolderId == -1) { + return nullptr; + } + + // 2. find the entry that match the given filename and parentFolderId + if (parentFolderId >= 0) { + for (auto entry : entries) { + if (entry->parentFolderId == parentFolderId && entry->label == fName) { + return entry; + } + } + } + + return nullptr; +} + +/** Protected version of findEntryFromFullPathU */ +const ProfileStoreEntry* ProfileStore::findEntryFromFullPath (Glib::ustring path) +{ + MyMutex::MyLock lock (parseMutex); + return findEntryFromFullPathU (path); +} + +const PartialProfile* ProfileStore::getProfile (Glib::ustring path) +{ + + if (storeState == STORESTATE_NOTINITIALIZED) { + parseProfiles(); + } + + const ProfileStoreEntry *pse = findEntryFromFullPath (path); + + if (!pse) { + return nullptr; + } + + return getProfile (pse); +} + +const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) +{ + + if (storeState == STORESTATE_NOTINITIALIZED) { + parseProfiles(); + } + + MyMutex::MyLock lock (parseMutex); + + if (entry == internalDefaultEntry) { + return internalDefaultProfile; + } + + std::map::iterator iter = partProfiles.find (entry); + + if (iter != partProfiles.end()) { + return iter->second; + } else { + // This shouldn't happen! +#ifndef NDEBUG + printf ("WARNING! Profile not found!\n"); +#endif + return nullptr; + } +} + +/** @brief Get a pointer to the profile's vector list + * + * This method grants you unique access to the vector list through Mutex locking. + * When you're done with the file list, you MUST call the releaseFileList method to release the lock. + */ +const std::vector* ProfileStore::getFileList () +{ + + if (storeState == STORESTATE_NOTINITIALIZED) { + parseProfiles(); + } + + parseMutex.lock(); + + return &entries; +} + +void ProfileStore::releaseFileList() +{ + parseMutex.unlock(); +} + +/* + * Send back a pointer to the default procparams for raw or standard images. + * If the profile doesn't already exist in the profile list, + * it will add it with default internal values, so this method never fails + */ +const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) +{ + + //Note: the mutex is locked in getProfile, called below + // eventual initialization is done there too + + const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); + + if (!pProf) { + pProf = internalDefaultProfile; + } + + return pProf->pparams; +} + +/* + * Send back a pointer to the default partial profile for raw or standard images. + * If it doesn't already exist in the profile list, it will add it with default internal values, + * so this method will never fails + */ +const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) +{ + + //Note: the mutex is locked in getProfile, called below + // eventual initialization is done there too + + const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); + + if (!pProf) { + pProf = internalDefaultProfile; + } + + return pProf; +} + +const Glib::ustring ProfileStore::getPathFromId (int folderId) +{ + // initialization must have been done when calling this + return folders.at (folderId); +} + + +void ProfileStore::clearFileList() +{ + for (auto entry : entries) { + if (entry != internalDefaultEntry) { + delete entry; + } + } + + entries.clear(); +} + +void ProfileStore::clearProfileList() +{ + for (auto partProfile : partProfiles) { + if (partProfile.second != internalDefaultProfile) { + delete partProfile.second; + } + } + + partProfiles.clear(); +} + +void ProfileStore::addListener (ProfileStoreListener *listener) +{ + listeners.push_back (listener); +} + +void ProfileStore::removeListener (ProfileStoreListener *listener) +{ + listeners.remove (listener); +} + +void ProfileStore::dumpFolderList() +{ + printf ("Folder list:\n------------\n"); + + for (unsigned int i = 0; i < folders.size(); i++) { + printf (" #%3ud - %s\n", i, folders.at (i).c_str()); + } + + printf ("\n"); +} + +PartialProfile *ProfileStore::loadDynamicProfile (const ImageMetaData *im) +{ + if (storeState == STORESTATE_NOTINITIALIZED) { + parseProfiles(); + } + + PartialProfile *ret = new PartialProfile (true, true); + + if (!rulesLoaded) { + loadRules(); + } + + for (auto rule : dynamicRules) { + if (rule.matches (im)) { + if (options.rtSettings.verbose) { + printf ("found matching profile %s\n", rule.profilepath.c_str()); + } + + const PartialProfile *p = getProfile (rule.profilepath); + + if (p != nullptr) { + p->applyTo (ret->pparams); + } else { + printf ("ERROR loading matching profile from: %s\n", rule.profilepath.c_str()); + } + } + } + + return ret; +} + +ProfileStoreEntry::ProfileStoreEntry() : label (""), type (PSET_FOLDER), parentFolderId (0), folderId (0) {} + +ProfileStoreEntry::ProfileStoreEntry (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) : label (label), type (type), parentFolderId (parentFolder), folderId (folder) {} + +void ProfileStoreEntry::setValues (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) +{ + this->label = label; + this->type = type; + parentFolderId = parentFolder; + folderId = folder; +} + diff --git a/rtgui/profilestore.h b/rtengine/profilestore.h similarity index 67% rename from rtgui/profilestore.h rename to rtengine/profilestore.h index ad569c180..c6627b4c8 100644 --- a/rtgui/profilestore.h +++ b/rtengine/profilestore.h @@ -23,16 +23,14 @@ #include #include -#include "../rtengine/rtengine.h" -#include "../rtengine/noncopyable.h" - -#include "threadutils.h" -#include "paramsedited.h" -#include "guiutils.h" +#include "rtengine.h" +#include "noncopyable.h" +#include "dynamicprofile.h" // forward decl class DynamicProfileRule; +class DynamicProfileRules; /** @brief This will implement callback functions for the ProfileStore * @@ -83,7 +81,7 @@ public: * @param parentFolder index of the elements's path in the folder list * @param folder index of the folder's own path in the folder list */ - ProfileStoreEntry(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); + ProfileStoreEntry (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); /** @brief Set the values of the object after its instantiation * @param label Label to be used in menu or combobox; also used as profile's filename @@ -91,31 +89,7 @@ public: * @param parentFolder index of the elements's path in the folder list * @param folder index of the folder's own path in the folder list */ - void setValues(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); -}; - - -/** - * @brief subclass of Gtk::Label with extra fields for Combobox and Menu, to link with a ProfileStoreEntry - */ -class ProfileStoreLabel : public Gtk::Label -{ - -public: - const ProfileStoreEntry *entry; - -#ifndef NDEBUG - ProfileStoreLabel() : Gtk::Label("*** error ***"), entry(nullptr) {} -#else - ProfileStoreLabel() : Gtk::Label(""), entry(NULL) {} -#endif - - /** @brief Create a new ProfileStoreLabel - * - * @param entry Pointer to the ProfileStoreEntry object, be it a directory or a file - */ - explicit ProfileStoreLabel(const ProfileStoreEntry *entry); - ProfileStoreLabel (const ProfileStoreLabel &other); + void setValues (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); }; @@ -124,12 +98,12 @@ public: * This store can be queried by the GUI to display a Tree of the profiles available * in the user's and system's profile directory and subdirectories. */ -class ProfileStore : - public rtengine::NonCopyable +class ProfileStore : public rtengine::NonCopyable, public DynamicProfileRules { typedef enum { STORESTATE_NOTINITIALIZED, + STORESTATE_LIGHTWEIGHT, STORESTATE_BEINGINITIALIZED, STORESTATE_INITIALIZED, STORESTATE_DELETED @@ -137,13 +111,13 @@ class ProfileStore : private: struct SortProfiles { - bool operator ()(const ProfileStoreEntry* const a1, const ProfileStoreEntry* const a2) + bool operator () (const ProfileStoreEntry* const a1, const ProfileStoreEntry* const a2) { return a1->parentFolderId == a2->parentFolderId ? a1->label < a2->label : a1->parentFolderId < a2->parentFolderId; } }; - MyMutex *parseMutex; + MyMutex parseMutex; StoreState storeState; rtengine::procparams::AutoPartialProfile *internalDefaultProfile; ProfileStoreEntry *internalDefaultEntry; @@ -164,8 +138,8 @@ private: /** List of the client of this store */ std::list listeners; - /** cache for dynamic profile rules */ - std::unique_ptr> dynamicRules; + /** whereas we have to load all profile at init time or one by one upon request */ + bool loadAll; /** @brief Method to recursively parse a profile folder with a level depth arbitrarily limited to 3 * @@ -182,24 +156,26 @@ private: void _parseProfiles (); void clearFileList (); void clearProfileList (); - const ProfileStoreEntry* findEntryFromFullPathU(Glib::ustring path); + const ProfileStoreEntry* findEntryFromFullPathU (Glib::ustring path); public: ProfileStore(); ~ProfileStore(); - bool init (); + static ProfileStore* getInstance(); + + bool init (bool loadAll = true); void parseProfiles (); - int findFolderId(const Glib::ustring &path); - const ProfileStoreEntry* findEntryFromFullPath(Glib::ustring path); + int findFolderId (const Glib::ustring &path); + const ProfileStoreEntry* findEntryFromFullPath (Glib::ustring path); const rtengine::procparams::PartialProfile* getProfile (Glib::ustring path); const rtengine::procparams::PartialProfile* getProfile (const ProfileStoreEntry* entry); const std::vector* getFileList (); void releaseFileList (); const rtengine::procparams::ProcParams* getDefaultProcParams (bool isRaw); const rtengine::procparams::PartialProfile* getDefaultPartialProfile (bool isRaw); - const Glib::ustring getPathFromId(int folderId); + const Glib::ustring getPathFromId (int folderId); const ProfileStoreEntry* getInternalDefaultPSE() { return internalDefaultEntry; @@ -210,53 +186,12 @@ public: return internalDynamicEntry; } - const std::vector &getDynamicProfileRules() const; - void setDynamicProfileRules(const std::vector &r); + void addListener (ProfileStoreListener *listener); + void removeListener (ProfileStoreListener *listener); - void addListener(ProfileStoreListener *listener); - void removeListener(ProfileStoreListener *listener); + rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::ImageMetaData *im); void dumpFolderList(); - }; -class ProfileStoreComboBox : public MyComboBox -{ - -protected: - class MethodColumns : public Gtk::TreeModel::ColumnRecord - { - public: - Gtk::TreeModelColumn label; - Gtk::TreeModelColumn profileStoreEntry; - MethodColumns() - { - add(label); - add(profileStoreEntry); - } - }; - - Glib::RefPtr refTreeModel; - MethodColumns methodColumns; - void refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList); - Gtk::TreeIter findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse); - Gtk::TreeIter findRowFromFullPath_(Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name); - -public: - ProfileStoreComboBox(); - void updateProfileList(); - Glib::ustring getCurrentLabel(); - const ProfileStoreEntry* getSelectedEntry(); - Gtk::TreeIter findRowFromEntry (const ProfileStoreEntry *pse); - Gtk::TreeIter findRowFromFullPath (Glib::ustring path); - Glib::ustring getFullPathFromActiveRow (); - bool setActiveRowFromFullPath (Glib::ustring oldPath); - bool setActiveRowFromEntry (const ProfileStoreEntry *pse); - bool setInternalEntry (); - Gtk::TreeIter getRowFromLabel(Glib::ustring name); - Gtk::TreeIter addRow(const ProfileStoreEntry *profileStoreEntry); -}; - -extern ProfileStore profileStore; - #endif diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index e7a71c81e..efbba78d1 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1416,11 +1416,12 @@ private: } params.wavelet.strength *= scale_factor; params.dirpyrDenoise.luma *= scale_factor; - params.dirpyrDenoise.Ldetail += (100 - params.dirpyrDenoise.Ldetail) * scale_factor; - //params.dirpyrDenoise.smethod = "shal"; - for (auto &p : params.dirpyrDenoise.lcurve) { - p *= scale_factor; + //params.dirpyrDenoise.Ldetail += (100 - params.dirpyrDenoise.Ldetail) * scale_factor; + auto &lcurve = params.dirpyrDenoise.lcurve; + for (size_t i = 2; i < lcurve.size(); i += 4) { + lcurve[i] *= min(scale_factor * 2, 1.0); } + noiseLCurve.Set(lcurve); const char *medmethods[] = { "soft", "33", "55soft", "55", "77", "99" }; if (params.dirpyrDenoise.median) { auto &key = params.dirpyrDenoise.methodmed == "RGB" ? params.dirpyrDenoise.rgbmethod : params.dirpyrDenoise.medmethod; diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 300491e85..c317f8525 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -46,7 +46,6 @@ set(NONCLISOURCEFILES dirpyrdenoise.cc dirpyrequalizer.cc distortion.cc - dynamicprofile.cc dynamicprofilepanel.cc edit.cc editorpanel.cc @@ -107,7 +106,7 @@ set(NONCLISOURCEFILES previewmodepanel.cc previewwindow.cc profilepanel.cc - profilestore.cc + profilestorecombobox.cc prsharpening.cc rawcacorrection.cc rawexposure.cc @@ -219,15 +218,15 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY # Create new executables targets add_executable(rth ${EXTRA_SRC_NONCLI} ${NONCLISOURCEFILES}) -#add_executable(rth-cli ${EXTRA_SRC_CLI} ${CLISOURCEFILES}) +add_executable(rth-cli ${EXTRA_SRC_CLI} ${CLISOURCEFILES}) # Add dependencies to executables targets add_dependencies(rth UpdateInfo) -#add_dependencies(rth-cli UpdateInfo) +add_dependencies(rth-cli UpdateInfo) # Set executables targets properties, i.e. output filename and compile flags set_target_properties(rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee) -#set_target_properties(rth-cli PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee-cli) +set_target_properties(rth-cli PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee-cli) # Add linked libraries dependencies to executables targets target_link_libraries(rth rtengine @@ -251,25 +250,25 @@ target_link_libraries(rth rtengine ${ZLIB_LIBRARIES} ) -#target_link_libraries(rth-cli rtengine -# ${CAIROMM_LIBRARIES} -# ${EXPAT_LIBRARIES} -# ${EXTRA_LIB_RTGUI} -# ${FFTW3F_LIBRARIES} -# ${GIOMM_LIBRARIES} -# ${GIO_LIBRARIES} -# ${GLIB2_LIBRARIES} -# ${GLIBMM_LIBRARIES} -# ${GOBJECT_LIBRARIES} -# ${GTHREAD_LIBRARIES} -# ${IPTCDATA_LIBRARIES} -# ${JPEG_LIBRARIES} -# ${LCMS_LIBRARIES} -# ${PNG_LIBRARIES} -# ${TIFF_LIBRARIES} -# ${ZLIB_LIBRARIES} -# ) +target_link_libraries(rth-cli rtengine + ${CAIROMM_LIBRARIES} + ${EXPAT_LIBRARIES} + ${EXTRA_LIB_RTGUI} + ${FFTW3F_LIBRARIES} + ${GIOMM_LIBRARIES} + ${GIO_LIBRARIES} + ${GLIB2_LIBRARIES} + ${GLIBMM_LIBRARIES} + ${GOBJECT_LIBRARIES} + ${GTHREAD_LIBRARIES} + ${IPTCDATA_LIBRARIES} + ${JPEG_LIBRARIES} + ${LCMS_LIBRARIES} + ${PNG_LIBRARIES} + ${TIFF_LIBRARIES} + ${ZLIB_LIBRARIES} + ) # Install executables install(TARGETS rth DESTINATION ${BINDIR}) -#install(TARGETS rth-cli DESTINATION ${BINDIR}) +install(TARGETS rth-cli DESTINATION ${BINDIR}) diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index eee97c2ad..d5a728a97 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -945,21 +945,53 @@ void BayerProcess::pixelShiftMotionMethodChanged () void BayerProcess::FrameCountChanged(int n, int frameNum) { - GThreadLock lock; - imageNumber->block (true); + struct Data { + BayerProcess *me; + int n; + int frameNum; + }; + const auto func = [](gpointer data) -> gboolean { + Data *d = static_cast(data); + BayerProcess *me = d->me; + me->imageNumber->block (true); + int n = d->n; + int frameNum = d->frameNum; - imageNumber->remove_all(); - imageNumber->append("1"); - for(int i = 2; i <= std::min(n, 4); ++i) { - std::ostringstream entry; - entry << i; - imageNumber->append(entry.str()); - } - imageNumber->set_active(std::min(frameNum, n - 1)); - if(n == 1) { - imageNumberBox->hide(); - } else { - imageNumberBox->show(); - } - imageNumber->block (false); + me->imageNumber->remove_all(); + me->imageNumber->append("1"); + for(int i = 2; i <= std::min(n, 4); ++i) { + std::ostringstream entry; + entry << i; + me->imageNumber->append(entry.str()); + } + me->imageNumber->set_active(std::min(frameNum, n - 1)); + if(n == 1) { + me->imageNumberBox->hide(); + } else { + me->imageNumberBox->show(); + } + me->imageNumber->block (false); + delete d; + return FALSE; + }; + + idle_register.add(func, new Data { this, n, frameNum }); + + // GThreadLock lock; + // imageNumber->block (true); + + // imageNumber->remove_all(); + // imageNumber->append("1"); + // for(int i = 2; i <= std::min(n, 4); ++i) { + // std::ostringstream entry; + // entry << i; + // imageNumber->append(entry.str()); + // } + // imageNumber->set_active(std::min(frameNum, n - 1)); + // if(n == 1) { + // imageNumberBox->hide(); + // } else { + // imageNumberBox->show(); + // } + // imageNumber->block (false); } diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index 3d15802a5..6d9dd6062 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -74,6 +74,8 @@ protected: Adjuster* pixelShiftRedBlueWeight; #endif int oldMethod; + + IdleRegister idle_register; public: BayerProcess (); diff --git a/rtgui/dynamicprofile.cc b/rtgui/dynamicprofile.cc deleted file mode 100644 index 4439a1562..000000000 --- a/rtgui/dynamicprofile.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- C++ -*- - * This file is part of RawTherapee. - * - * Copyright (c) 2017 Alberto Griggio - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ - -#include "dynamicprofile.h" -#include "profilestore.h" -#include -#include - -using namespace rtengine; -using namespace rtengine::procparams; - -namespace { - -const int ISO_MAX = 512000; -const double FNUMBER_MAX = 100.0; -const double FOCALLEN_MAX = 10000.0; -const double SHUTTERSPEED_MAX = 1000.0; -const double EXPCOMP_MIN = -20.0; -const double EXPCOMP_MAX = 20.0; - -} // namespace - - -bool DynamicProfileRule::Optional::operator()(const Glib::ustring &val) const -{ - if (!enabled) { - return true; - } - if (value.find("re:") == 0) { - // this is a regexp - return Glib::Regex::match_simple(value.substr(3), val, - Glib::REGEX_CASELESS); - } else { - // normal string comparison - return value.casefold() == val.casefold(); - } -} - - -DynamicProfileRule::DynamicProfileRule(): - serial_number(0), - iso(0, ISO_MAX), - fnumber(0, FNUMBER_MAX), - focallen(0, FOCALLEN_MAX), - shutterspeed(0, SHUTTERSPEED_MAX), - expcomp(EXPCOMP_MIN, EXPCOMP_MAX) -{ -} - - -bool DynamicProfileRule::operator<(const DynamicProfileRule &other) const -{ - return serial_number < other.serial_number; -} - - -bool DynamicProfileRule::matches(const rtengine::ImageMetaData *im) const -{ - return (iso(im->getISOSpeed()) - && fnumber(im->getFNumber()) - && focallen(im->getFocalLen()) - && shutterspeed(im->getShutterSpeed()) - && expcomp(im->getExpComp()) - && camera(im->getCamera()) - && lens(im->getLens())); -} - -namespace { - -void get_int_range(DynamicProfileRule::Range &dest, - const Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key) -{ - try { - int min = kf.get_integer(group, key + "_min"); - int max = kf.get_integer(group, key + "_max"); - if (min <= max) { - dest.min = min; - dest.max = max; - } - } catch (Glib::KeyFileError &e) { - } -} - - -void get_double_range(DynamicProfileRule::Range &dest, - const Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key) -{ - try { - double min = kf.get_double(group, key + "_min"); - double max = kf.get_double(group, key + "_max"); - if (min <= max) { - dest.min = min; - dest.max = max; - } - } catch (Glib::KeyFileError &e) { - } -} - - -void get_optional(DynamicProfileRule::Optional &dest, - const Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key) -{ - try { - bool e = kf.get_boolean(group, key + "_enabled"); - if (e) { - Glib::ustring s = kf.get_string(group, key + "_value"); - dest.enabled = e; - dest.value = s; - } - } catch (Glib::KeyFileError &) { - } -} - -void set_int_range(Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key, - const DynamicProfileRule::Range &val) -{ - kf.set_integer(group, key + "_min", val.min); - kf.set_integer(group, key + "_max", val.max); -} - -void set_double_range(Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key, - const DynamicProfileRule::Range &val) -{ - kf.set_double(group, key + "_min", val.min); - kf.set_double(group, key + "_max", val.max); -} - -void set_optional(Glib::KeyFile &kf, const Glib::ustring &group, - const Glib::ustring &key, - const DynamicProfileRule::Optional &val) -{ - kf.set_boolean(group, key + "_enabled", val.enabled); - kf.set_string(group, key + "_value", val.value); -} - -} // namespace - - -bool loadDynamicProfileRules(std::vector &out) -{ - out.clear(); - Glib::KeyFile kf; - try { - if (!kf.load_from_file( - Glib::build_filename(Options::rtdir, "dynamicprofile.cfg"))) { - return false; - } - } catch (Glib::Error &e) { - return false; - } - if (options.rtSettings.verbose) { - printf("loading dynamic profiles...\n"); - } - auto groups = kf.get_groups(); - for (auto group : groups) { - // groups are of the form "rule N", where N is a positive integer - if (group.find("rule ") != 0) { - return false; - } - std::istringstream buf(group.c_str() + 5); - int serial = 0; - if (!(buf >> serial) || !buf.eof()) { - return false; - } - if (options.rtSettings.verbose) { - printf(" loading rule %d\n", serial); - } - - out.emplace_back(DynamicProfileRule()); - DynamicProfileRule &rule = out.back(); - rule.serial_number = serial; - get_int_range(rule.iso, kf, group, "iso"); - get_double_range(rule.fnumber, kf, group, "fnumber"); - get_double_range(rule.focallen, kf, group, "focallen"); - get_double_range(rule.shutterspeed, kf, group, "shutterspeed"); - get_double_range(rule.expcomp, kf, group, "expcomp"); - get_optional(rule.camera, kf, group, "camera"); - get_optional(rule.lens, kf, group, "lens"); - try { - rule.profilepath = kf.get_string(group, "profilepath"); - } catch (Glib::KeyFileError &) { - out.pop_back(); - } - } - std::sort(out.begin(), out.end()); - return true; -} - - -bool storeDynamicProfileRules(const std::vector &rules) -{ - if (options.rtSettings.verbose) { - printf("saving dynamic profiles...\n"); - } - Glib::KeyFile kf; - for (auto &rule : rules) { - std::ostringstream buf; - buf << "rule " << rule.serial_number; - Glib::ustring group = buf.str(); - set_int_range(kf, group, "iso", rule.iso); - set_double_range(kf, group, "fnumber", rule.fnumber); - set_double_range(kf, group, "focallen", rule.focallen); - set_double_range(kf, group, "shutterspeed", rule.shutterspeed); - set_double_range(kf, group, "expcomp", rule.expcomp); - set_optional(kf, group, "camera", rule.camera); - set_optional(kf, group, "lens", rule.lens); - kf.set_string(group, "profilepath", rule.profilepath); - } - return kf.save_to_file( - Glib::build_filename(Options::rtdir, "dynamicprofile.cfg")); -} - - -PartialProfile *loadDynamicProfile(const ImageMetaData *im) -{ - PartialProfile *ret = new PartialProfile(true, true); - for (auto &rule : profileStore.getDynamicProfileRules()) { - if (rule.matches(im)) { - if (options.rtSettings.verbose) { - printf("found matching profile %s\n", - rule.profilepath.c_str()); - } - const PartialProfile *p = - profileStore.getProfile(rule.profilepath); - if (p != nullptr) { - p->applyTo(ret->pparams); - } else { - printf("ERROR loading matching profile from: %s\n", - rule.profilepath.c_str()); - } - } - } - return ret; -} diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index 172c06f47..db3a19ed0 100644 --- a/rtgui/dynamicprofilepanel.cc +++ b/rtgui/dynamicprofilepanel.cc @@ -19,8 +19,9 @@ #include "dynamicprofilepanel.h" #include "multilangmgr.h" -#include "profilestore.h" +#include "../rtengine/profilestore.h" #include "../rtengine/rtengine.h" +#include "../rtengine/dynamicprofile.h" #include #include @@ -29,65 +30,63 @@ // DynamicProfilePanel::EditDialog //----------------------------------------------------------------------------- -DynamicProfilePanel::EditDialog::EditDialog(const Glib::ustring &title, - Gtk::Window &parent): - Gtk::Dialog(title, parent) +DynamicProfilePanel::EditDialog::EditDialog (const Glib::ustring &title, Gtk::Window &parent): + Gtk::Dialog (title, parent) { - profilepath_ = Gtk::manage(new ProfileStoreComboBox()); - Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); - hb->pack_start(*Gtk::manage(new Gtk::Label(M("DYNPROFILEEDITOR_PROFILE"))), - false, false, 4); - hb->pack_start(*profilepath_, true, true, 2); - get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); + profilepath_ = Gtk::manage (new ProfileStoreComboBox()); + Gtk::HBox *hb = Gtk::manage (new Gtk::HBox()); + hb->pack_start (*Gtk::manage (new Gtk::Label (M ("DYNPROFILEEDITOR_PROFILE"))), false, false, 4); + hb->pack_start (*profilepath_, true, true, 2); + get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4); - add_optional(M("EXIFFILTER_CAMERA"), has_camera_, camera_); - add_optional(M("EXIFFILTER_LENS"), has_lens_, lens_); - - add_range(M("EXIFFILTER_ISO"), iso_min_, iso_max_); - add_range(M("EXIFFILTER_APERTURE"), fnumber_min_, fnumber_max_); - add_range(M("EXIFFILTER_FOCALLEN"), focallen_min_, focallen_max_); - add_range(M("EXIFFILTER_SHUTTER"), shutterspeed_min_, shutterspeed_max_); - add_range(M("EXIFFILTER_EXPOSURECOMPENSATION"), expcomp_min_, expcomp_max_); + add_optional (M ("EXIFFILTER_CAMERA"), has_camera_, camera_); + add_optional (M ("EXIFFILTER_LENS"), has_lens_, lens_); - add_button(M("GENERAL_OK"), 1); - add_button(M("GENERAL_CANCEL"), 2); + add_range (M ("EXIFFILTER_ISO"), iso_min_, iso_max_); + add_range (M ("EXIFFILTER_APERTURE"), fnumber_min_, fnumber_max_); + add_range (M ("EXIFFILTER_FOCALLEN"), focallen_min_, focallen_max_); + add_range (M ("EXIFFILTER_SHUTTER"), shutterspeed_min_, shutterspeed_max_); + add_range (M ("EXIFFILTER_EXPOSURECOMPENSATION"), expcomp_min_, expcomp_max_); + + add_button (M ("GENERAL_OK"), 1); + add_button (M ("GENERAL_CANCEL"), 2); set_ranges(); - + show_all_children(); } -void DynamicProfilePanel::EditDialog::set_rule( +void DynamicProfilePanel::EditDialog::set_rule ( const DynamicProfileRule &rule) { - iso_min_->set_value(rule.iso.min); - iso_max_->set_value(rule.iso.max); + iso_min_->set_value (rule.iso.min); + iso_max_->set_value (rule.iso.max); - fnumber_min_->set_value(rule.fnumber.min); - fnumber_max_->set_value(rule.fnumber.max); + fnumber_min_->set_value (rule.fnumber.min); + fnumber_max_->set_value (rule.fnumber.max); - focallen_min_->set_value(rule.focallen.min); - focallen_max_->set_value(rule.focallen.max); + focallen_min_->set_value (rule.focallen.min); + focallen_max_->set_value (rule.focallen.max); - shutterspeed_min_->set_value(rule.shutterspeed.min); - shutterspeed_max_->set_value(rule.shutterspeed.max); + shutterspeed_min_->set_value (rule.shutterspeed.min); + shutterspeed_max_->set_value (rule.shutterspeed.max); - expcomp_min_->set_value(rule.expcomp.min); - expcomp_max_->set_value(rule.expcomp.max); + expcomp_min_->set_value (rule.expcomp.min); + expcomp_max_->set_value (rule.expcomp.max); - has_camera_->set_active(rule.camera.enabled); - camera_->set_text(rule.camera.value); + has_camera_->set_active (rule.camera.enabled); + camera_->set_text (rule.camera.value); - has_lens_->set_active(rule.lens.enabled); - lens_->set_text(rule.lens.value); + has_lens_->set_active (rule.lens.enabled); + lens_->set_text (rule.lens.value); profilepath_->updateProfileList(); - if (!profilepath_->setActiveRowFromFullPath(rule.profilepath)) { + + if (!profilepath_->setActiveRowFromFullPath (rule.profilepath)) { profilepath_->setInternalEntry(); } } - DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() { @@ -97,7 +96,7 @@ DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() ret.fnumber.min = fnumber_min_->get_value(); ret.fnumber.max = fnumber_max_->get_value(); - + ret.focallen.min = focallen_min_->get_value(); ret.focallen.max = focallen_max_->get_value(); @@ -112,7 +111,7 @@ DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() ret.lens.enabled = has_lens_->get_active(); ret.lens.value = lens_->get_text(); - + ret.profilepath = profilepath_->getFullPathFromActiveRow(); return ret; @@ -121,20 +120,20 @@ DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() void DynamicProfilePanel::EditDialog::set_ranges() { DynamicProfileRule default_rule; - iso_min_->set_digits(0); - iso_max_->set_digits(0); - iso_min_->set_increments(1, 10); - iso_max_->set_increments(1, 10); - iso_min_->set_range(default_rule.iso.min, default_rule.iso.max); - iso_max_->set_range(default_rule.iso.min, default_rule.iso.max); - iso_min_->set_value(default_rule.iso.min); - iso_max_->set_value(default_rule.iso.max); + iso_min_->set_digits (0); + iso_max_->set_digits (0); + iso_min_->set_increments (1, 10); + iso_max_->set_increments (1, 10); + iso_min_->set_range (default_rule.iso.min, default_rule.iso.max); + iso_max_->set_range (default_rule.iso.min, default_rule.iso.max); + iso_min_->set_value (default_rule.iso.min); + iso_max_->set_value (default_rule.iso.max); -#define DOIT_(name) \ - name ## _min_->set_digits(1); \ - name ## _max_->set_digits(1); \ - name ## _min_->set_increments(0.1, 1); \ - name ## _max_->set_increments(0.1, 1); \ +#define DOIT_(name) \ + name ## _min_->set_digits(1); \ + name ## _max_->set_digits(1); \ + name ## _min_->set_increments(0.1, 1); \ + name ## _max_->set_increments(0.1, 1); \ name ## _min_->set_range(default_rule. name .min, \ default_rule. name .max); \ name ## _max_->set_range(default_rule. name .min, \ @@ -142,45 +141,42 @@ void DynamicProfilePanel::EditDialog::set_ranges() name ## _min_->set_value(default_rule. name .min); \ name ## _max_->set_value(default_rule. name .max) - DOIT_(fnumber); - DOIT_(focallen); - DOIT_(shutterspeed); - DOIT_(expcomp); + DOIT_ (fnumber); + DOIT_ (focallen); + DOIT_ (shutterspeed); + DOIT_ (expcomp); #undef DOIT_ - shutterspeed_min_->set_digits(4); - shutterspeed_max_->set_digits(4); + shutterspeed_min_->set_digits (4); + shutterspeed_max_->set_digits (4); profilepath_->setInternalEntry(); } -void DynamicProfilePanel::EditDialog::add_range(const Glib::ustring &name, +void DynamicProfilePanel::EditDialog::add_range (const Glib::ustring &name, Gtk::SpinButton *&from, Gtk::SpinButton *&to) { - Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); - hb->pack_start(*Gtk::manage(new Gtk::Label(name)), false, false, 4); - from = Gtk::manage(new Gtk::SpinButton()); - to = Gtk::manage(new Gtk::SpinButton()); - from->set_numeric(true); - to->set_numeric(true); - hb->pack_start(*from, true, true, 2); - hb->pack_start(*Gtk::manage(new Gtk::Label(" - ")), - false, false, 4); - hb->pack_start(*to, true, true, 2); - get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); + Gtk::HBox *hb = Gtk::manage (new Gtk::HBox()); + hb->pack_start (*Gtk::manage (new Gtk::Label (name)), false, false, 4); + from = Gtk::manage (new Gtk::SpinButton()); + to = Gtk::manage (new Gtk::SpinButton()); + from->set_numeric (true); + to->set_numeric (true); + hb->pack_start (*from, true, true, 2); + hb->pack_start (*Gtk::manage (new Gtk::Label (" - ")), false, false, 4); + hb->pack_start (*to, true, true, 2); + get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4); } - -void DynamicProfilePanel::EditDialog::add_optional(const Glib::ustring &name, - Gtk::CheckButton *&check, Gtk::Entry *&field) +void DynamicProfilePanel::EditDialog::add_optional (const Glib::ustring &name, Gtk::CheckButton *&check, Gtk::Entry *&field) { - check = Gtk::manage (new Gtk::CheckButton(name)); - Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); - hb->pack_start(*check, Gtk::PACK_SHRINK, 4); - field = Gtk::manage(new Gtk::Entry()); - hb->pack_start(*field, true, true, 2); - get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); - field->set_tooltip_text(M("DYNPROFILEEDITOR_ENTRY_TOOLTIP")); + check = Gtk::manage (new Gtk::CheckButton (name)); + Gtk::HBox *hb = Gtk::manage (new Gtk::HBox()); + hb->pack_start (*check, Gtk::PACK_SHRINK, 4); + field = Gtk::manage (new Gtk::Entry()); + hb->pack_start (*field, true, true, 2); + get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4); + field->set_tooltip_text (M ("DYNPROFILEEDITOR_ENTRY_TOOLTIP")); } @@ -189,121 +185,135 @@ void DynamicProfilePanel::EditDialog::add_optional(const Glib::ustring &name, //----------------------------------------------------------------------------- DynamicProfilePanel::DynamicProfilePanel(): - vbox_(Gtk::ORIENTATION_VERTICAL), - button_up_(M("DYNPROFILEEDITOR_MOVE_UP")), - button_down_(M("DYNPROFILEEDITOR_MOVE_DOWN")), - button_new_(M("DYNPROFILEEDITOR_NEW")), - button_edit_(M("DYNPROFILEEDITOR_EDIT")), - button_delete_(M("DYNPROFILEEDITOR_DELETE")) + vbox_ (Gtk::ORIENTATION_VERTICAL), + button_up_ (M ("DYNPROFILEEDITOR_MOVE_UP")), + button_down_ (M ("DYNPROFILEEDITOR_MOVE_DOWN")), + button_new_ (M ("DYNPROFILEEDITOR_NEW")), + button_edit_ (M ("DYNPROFILEEDITOR_EDIT")), + button_delete_ (M ("DYNPROFILEEDITOR_DELETE")) { - add(vbox_); + add (vbox_); - treeview_.set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_VERTICAL); - scrolledwindow_.add(treeview_); + treeview_.set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_VERTICAL); + scrolledwindow_.add (treeview_); - scrolledwindow_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + scrolledwindow_.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - vbox_.pack_start(scrolledwindow_); - vbox_.pack_start(buttonbox_, Gtk::PACK_SHRINK); + vbox_.pack_start (scrolledwindow_); + vbox_.pack_start (buttonbox_, Gtk::PACK_SHRINK); - buttonbox_.pack_start(button_new_, Gtk::PACK_SHRINK); - buttonbox_.pack_start(button_edit_, Gtk::PACK_SHRINK); - buttonbox_.pack_start(button_delete_, Gtk::PACK_SHRINK); - buttonbox_.pack_start(button_up_, Gtk::PACK_SHRINK); - buttonbox_.pack_start(button_down_, Gtk::PACK_SHRINK); - buttonbox_.set_border_width(5); - buttonbox_.set_layout(Gtk::BUTTONBOX_END); - button_up_.signal_clicked().connect( - sigc::mem_fun(*this, &DynamicProfilePanel::on_button_up)); - button_down_.signal_clicked().connect( - sigc::mem_fun(*this, &DynamicProfilePanel::on_button_down)); - button_new_.signal_clicked().connect( - sigc::mem_fun(*this, &DynamicProfilePanel::on_button_new)); - button_edit_.signal_clicked().connect( - sigc::mem_fun(*this, &DynamicProfilePanel::on_button_edit)); - button_delete_.signal_clicked().connect( - sigc::mem_fun(*this, &DynamicProfilePanel::on_button_delete)); + buttonbox_.pack_start (button_new_, Gtk::PACK_SHRINK); + buttonbox_.pack_start (button_edit_, Gtk::PACK_SHRINK); + buttonbox_.pack_start (button_delete_, Gtk::PACK_SHRINK); + buttonbox_.pack_start (button_up_, Gtk::PACK_SHRINK); + buttonbox_.pack_start (button_down_, Gtk::PACK_SHRINK); + buttonbox_.set_border_width (5); + buttonbox_.set_layout (Gtk::BUTTONBOX_END); + button_up_.signal_clicked().connect ( + sigc::mem_fun (*this, &DynamicProfilePanel::on_button_up)); + button_down_.signal_clicked().connect ( + sigc::mem_fun (*this, &DynamicProfilePanel::on_button_down)); + button_new_.signal_clicked().connect ( + sigc::mem_fun (*this, &DynamicProfilePanel::on_button_new)); + button_edit_.signal_clicked().connect ( + sigc::mem_fun (*this, &DynamicProfilePanel::on_button_edit)); + button_delete_.signal_clicked().connect ( + sigc::mem_fun (*this, &DynamicProfilePanel::on_button_delete)); - treemodel_ = Gtk::ListStore::create(columns_); - treeview_.set_model(treemodel_); + treemodel_ = Gtk::ListStore::create (columns_); + treeview_.set_model (treemodel_); + + auto cell = Gtk::manage (new Gtk::CellRendererText()); + int cols_count = treeview_.append_column ( M ("DYNPROFILEEDITOR_PROFILE"), *cell); + auto col = treeview_.get_column (cols_count - 1); - auto cell = Gtk::manage(new Gtk::CellRendererText()); - int cols_count = treeview_.append_column( - M("DYNPROFILEEDITOR_PROFILE"), *cell); - auto col = treeview_.get_column(cols_count - 1); if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_profilepath)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column( - M("EXIFFILTER_CAMERA"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column ( + M ("EXIFFILTER_CAMERA"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_camera)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column(M("EXIFFILTER_LENS"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column (M ("EXIFFILTER_LENS"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_lens)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column(M("EXIFFILTER_ISO"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column (M ("EXIFFILTER_ISO"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_iso)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column(M("EXIFFILTER_APERTURE"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column (M ("EXIFFILTER_APERTURE"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_fnumber)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column(M("EXIFFILTER_FOCALLEN"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column (M ("EXIFFILTER_FOCALLEN"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_focallen)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column(M("EXIFFILTER_SHUTTER"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column (M ("EXIFFILTER_SHUTTER"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_shutterspeed)); } - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_.append_column( - M("EXIFFILTER_EXPOSURECOMPENSATION"), *cell); - col = treeview_.get_column(cols_count - 1); + + cell = Gtk::manage (new Gtk::CellRendererText()); + cols_count = treeview_.append_column ( + M ("EXIFFILTER_EXPOSURECOMPENSATION"), *cell); + col = treeview_.get_column (cols_count - 1); + if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( + col->set_cell_data_func ( + *cell, sigc::mem_fun ( *this, &DynamicProfilePanel::render_expcomp)); } - + show_all_children(); - for (auto &r : profileStore.getDynamicProfileRules()) { - add_rule(r); + for (auto &r : ProfileStore::getInstance()->getRules()) { + add_rule (r); } } -void DynamicProfilePanel::update_rule(Gtk::TreeModel::Row row, +void DynamicProfilePanel::update_rule (Gtk::TreeModel::Row row, const DynamicProfileRule &rule) { row[columns_.iso] = rule.iso; @@ -316,15 +326,15 @@ void DynamicProfilePanel::update_rule(Gtk::TreeModel::Row row, row[columns_.profilepath] = rule.profilepath; } -void DynamicProfilePanel::add_rule(const DynamicProfileRule &rule) +void DynamicProfilePanel::add_rule (const DynamicProfileRule &rule) { - auto row = *(treemodel_->append()); - update_rule(row, rule); + auto row = * (treemodel_->append()); + update_rule (row, rule); } -DynamicProfileRule DynamicProfilePanel::to_rule(Gtk::TreeModel::Row row, - int serial) +DynamicProfileRule DynamicProfilePanel::to_rule (Gtk::TreeModel::Row row, + int serial) { DynamicProfileRule ret; ret.serial_number = serial; @@ -340,13 +350,14 @@ DynamicProfileRule DynamicProfilePanel::to_rule(Gtk::TreeModel::Row row, } -void DynamicProfilePanel::render_profilepath( +void DynamicProfilePanel::render_profilepath ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { auto row = *iter; - Gtk::CellRendererText *ct = static_cast(cell); + Gtk::CellRendererText *ct = static_cast (cell); auto value = row[columns_.profilepath]; - auto pse = profileStore.findEntryFromFullPath(value); + auto pse = ProfileStore::getInstance()->findEntryFromFullPath (value); + if (pse != nullptr) { ct->property_text() = pse->label; } else { @@ -368,54 +379,56 @@ void DynamicProfilePanel::render_profilepath( } -namespace { +namespace +{ template -Glib::ustring to_str(V n, int precision=1) +Glib::ustring to_str (V n, int precision = 1) { std::ostringstream buf; - buf << std::setprecision(precision) << std::fixed << n; + buf << std::setprecision (precision) << std::fixed << n; return buf.str(); } } // namespace -void DynamicProfilePanel::render_iso( +void DynamicProfilePanel::render_iso ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_RANGE_(int, iso, to_str); + RENDER_RANGE_ (int, iso, to_str); } -void DynamicProfilePanel::render_fnumber( +void DynamicProfilePanel::render_fnumber ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_RANGE_(double, fnumber, - [](double f) - { return std::string("f/") + - rtengine::ImageMetaData::apertureToString(f); }); + RENDER_RANGE_ (double, fnumber, + [] (double f) { + return std::string ("f/") + + rtengine::ImageMetaData::apertureToString (f); + }); } -void DynamicProfilePanel::render_focallen( +void DynamicProfilePanel::render_focallen ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_RANGE_(double, focallen, to_str); + RENDER_RANGE_ (double, focallen, to_str); } -void DynamicProfilePanel::render_shutterspeed( +void DynamicProfilePanel::render_shutterspeed ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_RANGE_(double, shutterspeed, - rtengine::ImageMetaData::shutterToString); + RENDER_RANGE_ (double, shutterspeed, + rtengine::ImageMetaData::shutterToString); } -void DynamicProfilePanel::render_expcomp( +void DynamicProfilePanel::render_expcomp ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_RANGE_(double, expcomp, to_str); + RENDER_RANGE_ (double, expcomp, to_str); } #undef RENDER_RANGE_ @@ -430,17 +443,17 @@ void DynamicProfilePanel::render_expcomp( ct->property_text() = ""; \ } -void DynamicProfilePanel::render_camera( +void DynamicProfilePanel::render_camera ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_OPTIONAL_(camera); + RENDER_OPTIONAL_ (camera); } -void DynamicProfilePanel::render_lens( +void DynamicProfilePanel::render_lens ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_OPTIONAL_(lens); + RENDER_OPTIONAL_ (lens); } #undef RENDER_OPTIONAL_ @@ -448,28 +461,34 @@ void DynamicProfilePanel::render_lens( void DynamicProfilePanel::on_button_up() { auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { return; } + auto it = s->get_selected(); + if (it != treemodel_->children().begin()) { auto it2 = it; --it2; - treemodel_->iter_swap(it, it2); + treemodel_->iter_swap (it, it2); } } void DynamicProfilePanel::on_button_down() { auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { return; } + auto it = s->get_selected(); auto it2 = it; ++it2; + if (it2 != treemodel_->children().end()) { - treemodel_->iter_swap(it, it2); + treemodel_->iter_swap (it, it2); } } @@ -477,22 +496,25 @@ void DynamicProfilePanel::on_button_down() void DynamicProfilePanel::on_button_delete() { auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { return; } + auto it = s->get_selected(); - treemodel_->erase(it); + treemodel_->erase (it); } void DynamicProfilePanel::on_button_new() { - EditDialog d(M("DYNPROFILEEDITOR_NEW_RULE"), - static_cast(*get_toplevel())); + EditDialog d (M ("DYNPROFILEEDITOR_NEW_RULE"), + static_cast (*get_toplevel())); int status = d.run(); + if (status == 1) { DynamicProfileRule rule = d.get_rule(); - add_rule(rule); + add_rule (rule); } } @@ -500,16 +522,19 @@ void DynamicProfilePanel::on_button_new() void DynamicProfilePanel::on_button_edit() { auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { return; } - EditDialog d(M("DYNPROFILEEDITOR_EDIT_RULE"), - static_cast(*get_toplevel())); - Gtk::TreeModel::Row row = *(s->get_selected()); - d.set_rule(to_rule(row)); + + EditDialog d (M ("DYNPROFILEEDITOR_EDIT_RULE"), + static_cast (*get_toplevel())); + Gtk::TreeModel::Row row = * (s->get_selected()); + d.set_rule (to_rule (row)); int status = d.run(); + if (status == 1) { - update_rule(row, d.get_rule()); + update_rule (row, d.get_rule()); } } @@ -518,15 +543,16 @@ void DynamicProfilePanel::save() { std::vector rules; int serial = 1; + for (auto row : treemodel_->children()) { - rules.emplace_back(to_rule(row, serial++)); + rules.emplace_back (to_rule (row, serial++)); } - if (!storeDynamicProfileRules(rules)) { - printf("Error in saving dynamic profile rules\n"); - } else { - profileStore.setDynamicProfileRules(rules); - if (options.rtSettings.verbose) { - printf("Saved %d dynamic profile rules\n", int(rules.size())); - } + + ProfileStore::getInstance()->setRules (rules); + + if (!ProfileStore::getInstance()->storeRules()) { + printf ("Error in saving dynamic profile rules\n"); + } else if (options.rtSettings.verbose) { + printf ("Saved %d dynamic profile rules\n", int (rules.size())); } } diff --git a/rtgui/dynamicprofilepanel.h b/rtgui/dynamicprofilepanel.h index 72ff95b9a..dca62f1e6 100644 --- a/rtgui/dynamicprofilepanel.h +++ b/rtgui/dynamicprofilepanel.h @@ -20,20 +20,20 @@ #define _DYNAMICPROFILEPANEL_H_ #include -#include "dynamicprofile.h" -#include "profilestore.h" +#include "../rtengine/dynamicprofile.h" +#include "profilestorecombobox.h" -class DynamicProfilePanel: public Gtk::VBox { +class DynamicProfilePanel: public Gtk::VBox +{ public: DynamicProfilePanel(); void save(); private: - void update_rule(Gtk::TreeModel::Row row, - const DynamicProfileRule &rule); - void add_rule(const DynamicProfileRule &rule); - DynamicProfileRule to_rule(Gtk::TreeModel::Row row, int serial=0); - + void update_rule (Gtk::TreeModel::Row row, const DynamicProfileRule &rule); + void add_rule (const DynamicProfileRule &rule); + DynamicProfileRule to_rule (Gtk::TreeModel::Row row, int serial = 0); + void on_button_quit(); void on_button_up(); void on_button_down(); @@ -41,18 +41,19 @@ private: void on_button_edit(); void on_button_delete(); - class DynamicProfileColumns: public Gtk::TreeModel::ColumnRecord { + class DynamicProfileColumns: public Gtk::TreeModel::ColumnRecord + { public: DynamicProfileColumns() { - add(iso); - add(fnumber); - add(focallen); - add(shutterspeed); - add(expcomp); - add(camera); - add(lens); - add(profilepath); + add (iso); + add (fnumber); + add (focallen); + add (shutterspeed); + add (expcomp); + add (camera); + add (lens); + add (profilepath); } Gtk::TreeModelColumn> iso; @@ -66,35 +67,26 @@ private: }; // cell renderers - void render_iso(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_fnumber(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_focallen(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_shutterspeed(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_expcomp(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_camera(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_lens(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); - void render_profilepath(Gtk::CellRenderer* cell, - const Gtk::TreeModel::iterator& iter); + void render_iso (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_fnumber (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_focallen (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_shutterspeed (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_expcomp (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_camera (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_lens (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_profilepath (Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); - class EditDialog: public Gtk::Dialog { + class EditDialog: public Gtk::Dialog + { public: - EditDialog(const Glib::ustring &title, Gtk::Window &parent); - void set_rule(const DynamicProfileRule &rule); + EditDialog (const Glib::ustring &title, Gtk::Window &parent); + void set_rule (const DynamicProfileRule &rule); DynamicProfileRule get_rule(); private: void set_ranges(); - void add_range(const Glib::ustring &name, - Gtk::SpinButton *&from, Gtk::SpinButton *&to); - void add_optional(const Glib::ustring &name, - Gtk::CheckButton *&check, Gtk::Entry *&field); + void add_range (const Glib::ustring &name, Gtk::SpinButton *&from, Gtk::SpinButton *&to); + void add_optional (const Glib::ustring &name, Gtk::CheckButton *&check, Gtk::Entry *&field); Gtk::SpinButton *iso_min_; Gtk::SpinButton *iso_max_; diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index d96a89d09..dd37a740b 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -134,7 +134,7 @@ FileBrowser::FileBrowser () fbih->destroyed = false; fbih->pending = 0; - profileStore.addListener(this); + ProfileStore::getInstance()->addListener(this); int p = 0; pmenu = new Gtk::Menu (); @@ -457,7 +457,7 @@ FileBrowser::~FileBrowser () { idle_register.destroy(); - profileStore.removeListener(this); + ProfileStore::getInstance()->removeListener(this); delete pmenu; delete pmenuColorLabels; delete[] amiExtProg; @@ -1346,7 +1346,7 @@ void FileBrowser::applyMenuItemActivated (ProfileStoreLabel *label) { MYREADERLOCK(l, entryRW); - const rtengine::procparams::PartialProfile* partProfile = profileStore.getProfile (label->entry); + const rtengine::procparams::PartialProfile* partProfile = ProfileStore::getInstance()->getProfile (label->entry); if (partProfile->pparams && !selected.empty()) { if (bppcl) { @@ -1376,7 +1376,7 @@ void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label) } } - const rtengine::procparams::PartialProfile* srcProfiles = profileStore.getProfile (label->entry); + const rtengine::procparams::PartialProfile* srcProfiles = ProfileStore::getInstance()->getProfile (label->entry); if (srcProfiles->pparams) { @@ -1982,7 +1982,7 @@ void FileBrowser::updateProfileList () // submenu applmenu int p = 0; - const std::vector *profEntries = profileStore.getFileList(); // lock and get a pointer to the profiles' list + const std::vector *profEntries = ProfileStore::getInstance()->getFileList(); // lock and get a pointer to the profiles' list std::map subMenuList; // store the Gtk::Menu that Gtk::MenuItem will have to be attached to @@ -2067,7 +2067,7 @@ void FileBrowser::updateProfileList () applypartprof->set_submenu (*(subMenuList.at(0))); } - profileStore.releaseFileList(); + ProfileStore::getInstance()->releaseFileList(); subMenuList.clear(); } diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index faede2d8c..4bad832eb 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -29,7 +29,7 @@ #include "partialpastedlg.h" #include "exportpanel.h" #include "extprog.h" -#include "profilestore.h" +#include "profilestorecombobox.h" class ProfileStoreLabel; class FileBrowser; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 8e4ae3613..91284e983 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -45,12 +45,6 @@ IdleRegister::~IdleRegister() void IdleRegister::add(GSourceFunc function, gpointer data, gint priority) { - struct DataWrapper { - IdleRegister* const self; - GSourceFunc function; - gpointer data; - }; - const auto dispatch = [](gpointer data) -> gboolean { DataWrapper* const data_wrapper = static_cast(data); @@ -80,9 +74,11 @@ void IdleRegister::add(GSourceFunc function, gpointer data, gint priority) void IdleRegister::destroy() { mutex.lock(); - for (const auto id : ids) { + for (const auto& id : ids) { g_source_remove(id.second); + delete id.first; } + ids.clear(); mutex.unlock(); } diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index b2ebaa80a..a6ec916f0 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -54,7 +54,13 @@ public: void destroy(); private: - std::map ids; + struct DataWrapper { + IdleRegister* const self; + GSourceFunc function; + gpointer data; + }; + + std::map ids; MyMutex mutex; }; diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index 3a601e18e..91dfc9204 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -49,6 +49,9 @@ #include "conio.h" #endif +// Set this to 1 to make RT work when started with Eclipse and arguments, at least on Windows platform +#define ECLIPSE_ARGS 0 + extern Options options; // stores path to data files @@ -175,7 +178,11 @@ int main(int argc, char **argv) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); if (argc > 1 || options.rtSettings.verbose) { - if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { + Glib::ustring fname(fname_to_utf8 (argv[1])); +#if ECLIPSE_ARGS + fname = fname.substr(1, fname.length()-2); +#endif + if (options.rtSettings.verbose || ( !Glib::file_test (fname, Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname, Glib::FILE_TEST_IS_DIR))) { bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); @@ -191,8 +198,7 @@ int main(int argc, char **argv) break; } - if(Console) { - AllocConsole(); + if(Console && AllocConsole()) { AttachConsole( GetCurrentProcessId() ) ; // Don't allow CTRL-C in console to terminate RT SetConsoleCtrlHandler( NULL, true ); @@ -268,8 +274,12 @@ void deleteProcParams(std::vector &pparam bool dontLoadCache( int argc, char **argv ) { - for( int iArg = 1; iArg < argc; iArg++) { - if( argv[iArg][0] == '-' && argv[iArg][1] == 'q' ) { + for (int iArg = 1; iArg < argc; iArg++) { + Glib::ustring currParam(argv[iArg]); +#if ECLIPSE_ARGS + currParam = currParam.substr(1, currParam.length()-2); +#endif + if( currParam.at(0) == '-' && currParam.at(1) == 'q' ) { return true; } } @@ -288,6 +298,7 @@ int processLineParams( int argc, char **argv ) bool sideProcParams = false; bool copyParamsFile = false; bool skipIfNoSidecar = false; + bool allExtensions = false; bool useDefault = false; unsigned int sideCarFilePos = 0; int compression = 92; @@ -297,16 +308,22 @@ int processLineParams( int argc, char **argv ) unsigned errors = 0; for( int iArg = 1; iArg < argc; iArg++) { - if( argv[iArg][0] == '-' ) { - switch( argv[iArg][1] ) { + Glib::ustring currParam(argv[iArg]); +#if ECLIPSE_ARGS + currParam = currParam.substr(1, currParam.length()-2); +#endif + if( currParam.at(0) == '-' ) { + switch( currParam.at(1) ) { case 'O': copyParamsFile = true; case 'o': // outputfile or dir if( iArg + 1 < argc ) { iArg++; - outputPath = fname_to_utf8 (argv[iArg]); - + outputPath = Glib::ustring(fname_to_utf8(argv[iArg])); +#if ECLIPSE_ARGS + outputPath = outputPath.substr(1, outputPath.length()-2); +#endif if( Glib::file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { outputDirectory = true; } @@ -319,7 +336,10 @@ int processLineParams( int argc, char **argv ) // RT stop if any of them can't be loaded for any reason. if( iArg + 1 < argc ) { iArg++; - Glib::ustring fname = fname_to_utf8 (argv[iArg]); + Glib::ustring fname(fname_to_utf8(argv[iArg])); +#if ECLIPSE_ARGS + fname = fname.substr(1, fname.length()-2); +#endif if (fname.at(0) == '-') { std::cerr << "Error: filename missing next to the -p switch" << std::endl; @@ -359,16 +379,20 @@ int processLineParams( int argc, char **argv ) overwriteFiles = true; break; + case 'a': + allExtensions = true; + break; + case 'j': - if (strlen(argv[iArg]) > 2 && argv[iArg][2] == 's') { - if (strlen(argv[iArg]) == 3) { + if (currParam.length() > 2 && currParam.at(2) == 's') { + if (currParam.length() == 3) { std::cerr << "Error: the -js switch requires a mandatory value!" << std::endl; deleteProcParams(processingParams); return -3; } // looking for the subsampling parameter - sscanf(&argv[iArg][3], "%d", &subsampling); + subsampling = atoi(currParam.substr(3).c_str()); if (subsampling < 1 || subsampling > 3) { std::cerr << "Error: the value accompanying the -js switch has to be in the [1-3] range!" << std::endl; @@ -377,7 +401,7 @@ int processLineParams( int argc, char **argv ) } } else { outputType = "jpg"; - sscanf(&argv[iArg][2], "%d", &compression); + compression = atoi(currParam.substr(2).c_str()); if (compression < 0 || compression > 100) { std::cerr << "Error: the value accompanying the -j switch has to be in the [0-100] range!" << std::endl; @@ -389,7 +413,7 @@ int processLineParams( int argc, char **argv ) break; case 'b': - sscanf(&argv[iArg][2], "%d", &bits); + bits = atoi(currParam.substr(2).c_str()); if (bits != 8 && bits != 16) { std::cerr << "Error: specify -b8 for 8-bit or -b16 for 16-bit output." << std::endl; @@ -401,7 +425,7 @@ int processLineParams( int argc, char **argv ) case 't': outputType = "tif"; - compression = ((argv[iArg][2] != 'z') ? 0 : 1); + compression = ((currParam.at(2) != 'z') ? 0 : 1); break; case 'n': @@ -412,16 +436,35 @@ int processLineParams( int argc, char **argv ) case 'f': fast_export = true; break; - + case 'c': // MUST be last option while (iArg + 1 < argc) { iArg++; + Glib::ustring argument(fname_to_utf8(argv[iArg])); +#if ECLIPSE_ARGS + argument = argument.substr(1, argument.length()-2); +#endif - const auto argument = fname_to_utf8 (argv[iArg]); + if (!Glib::file_test (argument, Glib::FILE_TEST_EXISTS)) { + std::cout << "\"" << argument << "\" doesn't exist !" << std::endl; + continue; + } if (Glib::file_test (argument, Glib::FILE_TEST_IS_REGULAR)) { - inputFiles.emplace_back (argument); + bool notAll = allExtensions && !options.is_parse_extention (argument); + bool notRetained = !allExtensions && !options.has_retained_extention (argument); + if (notAll || notRetained) { + if (notAll) { + std::cout << "\"" << argument << "\" is not one of the file format to process: skipped" << std::endl; + } else if (notRetained) { + std::cout << "\"" << argument << "\" is not one of the retained file format to process: skipped" << std::endl; + } + } + else { + inputFiles.emplace_back (argument); + } continue; + } if (Glib::file_test (argument, Glib::FILE_TEST_IS_DIR)) { @@ -438,19 +481,28 @@ int processLineParams( int argc, char **argv ) while (auto file = enumerator->next_file ()) { const auto fileName = Glib::build_filename (argument, file->get_name ()); + bool isDir = Glib::file_test (fileName, Glib::FILE_TEST_IS_DIR); + bool notAll = allExtensions && !options.is_parse_extention (fileName); + bool notRetained = !allExtensions && !options.has_retained_extention (fileName); - if (Glib::file_test (fileName, Glib::FILE_TEST_IS_DIR)) { + if (isDir || notAll || notRetained) { + if (isDir) { + std::cout << "\"" << fileName << "\" is a directory: skipped" << std::endl; + } else if (notAll) { + std::cout << "\"" << fileName << "\" is not one of the file format to process: skipped" << std::endl; + } else if (notRetained) { + std::cout << "\"" << fileName << "\" is not one of the retained file format to process: skipped" << std::endl; + } continue; + } - // skip files without extension and sidecar files - auto lastdot = fileName.find_last_of('.'); - if (lastdot == Glib::ustring::npos) { - continue; - } - - if (fileName.substr (lastdot).compare (paramFileExtension) == 0) { - continue; + if (sideProcParams && skipIfNoSidecar) { + // look for the sidecar proc params + if (!Glib::file_test(fileName + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + std::cout << "\"" << fileName << "\" has no side-car file: image skipped" << std::endl; + continue; + } } inputFiles.emplace_back (fileName); @@ -500,12 +552,16 @@ int processLineParams( int argc, char **argv ) std::cout << " " << Glib::path_get_basename(argv[0]) << " [-o |-O ] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] [-f] -c " << std::endl; std::cout << std::endl; std::cout << " -q Quick Start mode : do not load cached files to speedup start time." << std::endl; - std::cout << " -c Specify one or more input files." << std::endl; + std::cout << " -c Specify one or more input files or directory." << std::endl; + std::cout << " When specifying directories, Rawtherapee will look for images files that comply with the" << std::endl; + std::cout << " selected extensions (see also '-a')." << std::endl; std::cout << " -c must be the last option." << std::endl; std::cout << " -o | Set output file or folder." << std::endl; std::cout << " Saves output file alongside input file if -o is not specified." << std::endl; std::cout << " -O | Set output file or folder and copy " << pparamsExt << " file into it." << std::endl; std::cout << " Saves output file alongside input file if -O is not specified." << std::endl; + std::cout << " -a stand for 'all'. When specifying a directory, process all images specified in the" << std::endl; + std::cout << " extension list from the options file, even those currently not seleted" << std::endl; std::cout << " -s Use the existing sidecar file to build the processing parameters," << std::endl; std::cout << " e.g. for photo.raw there should be a photo.raw." << pparamsExt << " file in the same folder." << std::endl; std::cout << " If the sidecar file does not exist, neutral values will be used." << std::endl; @@ -546,7 +602,10 @@ int processLineParams( int argc, char **argv ) } } } else { - argv1 = fname_to_utf8 (argv[iArg]); + argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); +#if ECLIPSE_ARGS + argv1 = argv1.substr(1, argv1.length()-2); +#endif if( outputDirectory ) { options.savePathFolder = outputPath; @@ -587,7 +646,7 @@ int processLineParams( int argc, char **argv ) rawParams = new rtengine::procparams::PartialProfile(true, true); Glib::ustring profPath = options.findProfilePath(options.defProfRaw); - if (options.is_defProfRawMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension)))) { + if (options.is_defProfRawMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, Glib::path_get_basename(options.defProfRaw) + paramFileExtension)))) { std::cerr << "Error: default raw processing profile not found" << std::endl; rawParams->deleteInstance(); delete rawParams; @@ -598,7 +657,7 @@ int processLineParams( int argc, char **argv ) imgParams = new rtengine::procparams::PartialProfile(true); profPath = options.findProfilePath(options.defProfImg); - if (options.is_defProfImgMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension)))) { + if (options.is_defProfImgMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, Glib::path_get_basename(options.defProfImg) + paramFileExtension)))) { std::cerr << "Error: default non-raw processing profile not found" << std::endl; imgParams->deleteInstance(); delete imgParams; @@ -635,7 +694,7 @@ int processLineParams( int argc, char **argv ) } else if( outputDirectory ) { Glib::ustring s = Glib::path_get_basename( inputFile ); Glib::ustring::size_type ext = s.find_last_of('.'); - outputFile = outputPath + "/" + s.substr(0, ext) + "." + outputType; + outputFile = Glib::build_filename(outputPath, s.substr(0, ext) + "." + outputType); } else { Glib::ustring s = outputPath; Glib::ustring::size_type ext = s.find_last_of('.'); @@ -673,7 +732,7 @@ int processLineParams( int argc, char **argv ) if (options.defProfRaw == DEFPROFILE_DYNAMIC) { rawParams->deleteInstance(); delete rawParams; - rawParams = loadDynamicProfile(ii->getMetaData()); + rawParams = ProfileStore::getInstance()->loadDynamicProfile(ii->getMetaData()); } std::cout << " Merging default raw processing profile" << std::endl; rawParams->applyTo(¤tParams); @@ -681,7 +740,7 @@ int processLineParams( int argc, char **argv ) if (options.defProfImg == DEFPROFILE_DYNAMIC) { imgParams->deleteInstance(); delete imgParams; - imgParams = loadDynamicProfile(ii->getMetaData()); + imgParams = ProfileStore::getInstance()->loadDynamicProfile(ii->getMetaData()); } std::cout << " Merging default non-raw processing profile" << std::endl; imgParams->applyTo(¤tParams); diff --git a/rtgui/main.cc b/rtgui/main.cc index 88dc4ead4..495374f50 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -38,7 +38,7 @@ #include "rtimage.h" #include "version.h" #include "extprog.h" -#include "dynamicprofile.h" +#include "../rtengine/dynamicprofile.h" #ifndef WIN32 #include @@ -50,6 +50,9 @@ #include "conio.h" #endif +// Set this to 1 to make RT work when started with Eclipse and arguments, at least on Windows platform +#define ECLIPSE_ARGS 0 + extern Options options; // stores path to data files @@ -177,7 +180,6 @@ int main(int argc, char **argv) return -2; } - profileStore.init (); extProgStore->init(); SoundManager::init(); @@ -416,8 +418,12 @@ int processLineParams( int argc, char **argv ) unsigned errors = 0; for( int iArg = 1; iArg < argc; iArg++) { - if( argv[iArg][0] == '-' ) { - switch( argv[iArg][1] ) { + Glib::ustring currParam(argv[iArg]); +#if ECLIPSE_ARGS + currParam = currParam.substr(1, currParam.length()-2); +#endif + if( currParam.at(0) == '-' ) { + switch( currParam.at(1) ) { #ifdef WIN32 case 'w': // This case is handled outside this function @@ -437,9 +443,9 @@ int processLineParams( int argc, char **argv ) std::cout << std::endl; std::cout << "Symbols:" << std::endl; std::cout << " indicate parameters you can change." << std::endl; - std::cout << " [Square brackets] mean the parameter is optional." << std::endl; - std::cout << " The pipe symbol | indicates a choice of one or the other." << std::endl; - std::cout << " The dash symbol - denotes a range of possible values from one to the other." << std::endl; + //std::cout << " [Square brackets] mean the parameter is optional." << std::endl; + //std::cout << " The pipe symbol | indicates a choice of one or the other." << std::endl; + //std::cout << " The dash symbol - denotes a range of possible values from one to the other." << std::endl; std::cout << std::endl; std::cout << "Usage:" << std::endl; std::cout << " " << Glib::path_get_basename(argv[0]) << " Start File Browser inside folder." << std::endl; @@ -454,7 +460,10 @@ int processLineParams( int argc, char **argv ) } } } else { - argv1 = fname_to_utf8 (argv[iArg]); + argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); +#if ECLIPSE_ARGS + argv1 = argv1.substr(1, argv1.length()-2); +#endif break; } } diff --git a/rtgui/options.cc b/rtgui/options.cc index 55b257ec8..df68d0ac9 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -227,7 +227,7 @@ Glib::ustring Options::getPreferredProfilePath() /** @brief Get the absolute path of the given filename or the "Neutral" special value * *@param profName path + filename of the procparam to look for. A filename without path can be provided for backward compatibility. - * In this case, this parameter will be update with the new format. + * In this case, this parameter will be updated with the new format. *@return Send back the absolute path of the given filename or "Neutral" if "Neutral" has been set to profName. Implementor will have * to test for this particular value. If the absolute path is invalid (e.g. the file doesn't exist), it will return an empty string. */ @@ -2365,6 +2365,27 @@ void Options::save () } } +/* + * return true if ext is a parsed extension (retained or not) + */ +bool Options::is_parse_extention (Glib::ustring fname) +{ + Glib::ustring ext = getExtension (fname).lowercase(); + + if (!ext.empty()) { + // there is an extension to the filename + + // look out if it has one of the listed extensions (selected or not) + for (unsigned int i = 0; i < parseExtensions.size(); i++) { + if (ext == parseExtensions[i]) { + return true; + } + } + } + + return false; +} + /* * return true if fname ends with one of the retained image file extensions */ diff --git a/rtgui/options.h b/rtgui/options.h index 1a5ae21ed..f67175c43 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -333,6 +333,7 @@ public: return globalProfilePath; } Glib::ustring findProfilePath(Glib::ustring &profName); + bool is_parse_extention (Glib::ustring fname); bool has_retained_extention (Glib::ustring fname); bool is_extention_enabled(Glib::ustring ext); bool is_defProfRawMissing() diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 1acb7cfb4..d01d00327 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -87,20 +87,20 @@ Preferences::Preferences (RTWindow *rtwindow) get_action_area()->pack_end (*ok); get_action_area()->pack_end (*cancel); - nb->append_page (*getGeneralPanel(), M("PREFERENCES_TAB_GENERAL")); - nb->append_page (*getProcParamsPanel(), M("PREFERENCES_TAB_IMPROC")); - nb->append_page (*getDynProfilePanel(), M("PREFERENCES_TAB_DYNAMICPROFILE")); - nb->append_page (*getFileBrowserPanel(), M("PREFERENCES_TAB_BROWSER")); + nb->append_page (*getGeneralPanel(), M("PREFERENCES_TAB_GENERAL")); + nb->append_page (*getProcParamsPanel(), M("PREFERENCES_TAB_IMPROC")); + nb->append_page (*getDynProfilePanel(), M("PREFERENCES_TAB_DYNAMICPROFILE")); + nb->append_page (*getFileBrowserPanel(), M("PREFERENCES_TAB_BROWSER")); nb->append_page (*getColorManagementPanel(), M("PREFERENCES_TAB_COLORMGR")); - nb->append_page (*getBatchProcPanel(), M("PREFERENCES_BATCH_PROCESSING")); - nb->append_page (*getPerformancePanel(), M("PREFERENCES_TAB_PERFORMANCE")); + nb->append_page (*getBatchProcPanel(), M("PREFERENCES_BATCH_PROCESSING")); + nb->append_page (*getPerformancePanel(), M("PREFERENCES_TAB_PERFORMANCE")); // Sounds only on Windows and Linux #if defined(WIN32) || defined(__linux__) - nb->append_page (*getSoundPanel(), M("PREFERENCES_TAB_SOUND")); + nb->append_page (*getSoundPanel(), M("PREFERENCES_TAB_SOUND")); #endif nb->set_current_page (0); - profileStore.addListener(this); + ProfileStore::getInstance()->addListener(this); fillPreferences (); @@ -111,7 +111,7 @@ Preferences::Preferences (RTWindow *rtwindow) Preferences::~Preferences () { - profileStore.removeListener(this); + ProfileStore::getInstance()->removeListener(this); get_size(options.preferencesWidth, options.preferencesHeight); } @@ -445,13 +445,14 @@ Gtk::Widget* Preferences::getProcParamsPanel () Gtk::VBox* vbpp = Gtk::manage (new Gtk::VBox ()); Gtk::Label* drlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORRAW") + ":", Gtk::ALIGN_START)); rprofiles = Gtk::manage (new ProfileStoreComboBox ()); - rprofiles->addRow(profileStore.getInternalDynamicPSE()); + const ProfileStoreEntry* dynpse = ProfileStore::getInstance()->getInternalDynamicPSE(); + rprofiles->addRow(dynpse); setExpandAlignProperties(rprofiles, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); rprofiles->set_size_request(50, -1); rpconn = rprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forRAWComboChanged) ); Gtk::Label* drimg = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORIMAGE") + ":", Gtk::ALIGN_START)); iprofiles = Gtk::manage (new ProfileStoreComboBox ()); - iprofiles->addRow(profileStore.getInternalDynamicPSE()); + iprofiles->addRow(dynpse); iprofiles->set_size_request(50, -1); setExpandAlignProperties(iprofiles, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); ipconn = iprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forImageComboChanged) ); @@ -2197,7 +2198,7 @@ void Preferences::bundledProfilesChanged () options.useBundledProfiles = useBundledProfiles->get_active (); // rescan the file's tree - profileStore.parseProfiles(); // This will call Preferences::updateProfileList in return + ProfileStore::getInstance()->parseProfiles(); // This will call Preferences::updateProfileList in return // restoring back the old value options.useBundledProfiles = currValue; @@ -2232,8 +2233,9 @@ void Preferences::updateProfileList() { rprofiles->updateProfileList(); iprofiles->updateProfileList(); - rprofiles->addRow(profileStore.getInternalDynamicPSE()); - iprofiles->addRow(profileStore.getInternalDynamicPSE()); + const ProfileStoreEntry* dynpse = ProfileStore::getInstance()->getInternalDynamicPSE(); + rprofiles->addRow(dynpse); + iprofiles->addRow(dynpse); } void Preferences::restoreValue() diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index b988418f0..06768cf56 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -18,9 +18,9 @@ */ #include "profilepanel.h" #include "options.h" -#include "profilestore.h" #include "clipboard.h" #include "multilangmgr.h" +#include "profilestorecombobox.h" #include "rtimage.h" using namespace rtengine; @@ -99,7 +99,7 @@ ProfilePanel::ProfilePanel () : storedPProfile(nullptr), lastFilename(""), image lastsaved = nullptr; dontupdate = false; - profileStore.addListener(this); + ProfileStore::getInstance()->addListener(this); changeconn = profiles->signal_changed().connect( sigc::mem_fun(*this, &ProfilePanel::selection_changed) ); @@ -114,7 +114,7 @@ ProfilePanel::ProfilePanel () : storedPProfile(nullptr), lastFilename(""), image ProfilePanel::~ProfilePanel () { - profileStore.removeListener(this); + ProfileStore::getInstance()->removeListener(this); if (custom) { custom->deleteInstance(); @@ -188,7 +188,7 @@ void ProfilePanel::storeCurrentValue () const ProfileStoreEntry *entry = profiles->getSelectedEntry(); const PartialProfile *currProfile; - if (entry && (currProfile = profileStore.getProfile(entry)) != nullptr) { + if (entry && (currProfile = ProfileStore::getInstance()->getProfile(entry)) != nullptr) { // now storedPProfile has the current entry's values storedPProfile = new PartialProfile(currProfile->pparams, currProfile->pedited, true); } else { @@ -318,7 +318,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) toSave = lastsaved; } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); - toSave = entry ? profileStore.getProfile (profiles->getSelectedEntry()) : nullptr; + toSave = entry ? ProfileStore::getInstance()->getProfile (profiles->getSelectedEntry()) : nullptr; } if (toSave) { @@ -343,7 +343,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) } else { done = true; bool ccPrevState = changeconn.block(true); - profileStore.parseProfiles(); + ProfileStore::getInstance()->parseProfiles(); changeconn.block (ccPrevState); } } else { @@ -355,7 +355,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) } else { done = true; bool ccPrevState = changeconn.block(true); - profileStore.parseProfiles(); + ProfileStore::getInstance()->parseProfiles(); changeconn.block (ccPrevState); } } @@ -388,7 +388,7 @@ void ProfilePanel::copy_clicked (GdkEventButton* event) toSave = lastsaved; } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); - toSave = entry ? profileStore.getProfile (entry) : nullptr; + toSave = entry ? ProfileStore::getInstance()->getProfile (entry) : nullptr; } // toSave has to be a complete procparams @@ -559,7 +559,7 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) const ProfileStoreEntry* entry = profiles->getSelectedEntry(); if (entry) { - const PartialProfile* partProfile = profileStore.getProfile (entry); + const PartialProfile* partProfile = ProfileStore::getInstance()->getProfile (entry); *custom->pparams = *partProfile->pparams; } } @@ -576,7 +576,7 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) const ProfileStoreEntry* entry = profiles->getSelectedEntry(); if (entry) { - const PartialProfile* partProfile = profileStore.getProfile (entry); + const PartialProfile* partProfile = ProfileStore::getInstance()->getProfile (entry); *custom->pparams = *partProfile->pparams; } } @@ -660,7 +660,7 @@ void ProfilePanel::selection_changed () currRow = profiles->get_active(); } - const PartialProfile* s = profileStore.getProfile (pse); + const PartialProfile* s = ProfileStore::getInstance()->getProfile (pse); if (s) { if (fillMode->get_active() && s->pedited) { @@ -745,12 +745,12 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams lasSavedEntry = getLastSavedRow(); } - if (!(pse = profileStore.findEntryFromFullPath(profileFullPath))) { + if (!(pse = ProfileStore::getInstance()->findEntryFromFullPath(profileFullPath))) { // entry not found, pse = the Internal ProfileStoreEntry - pse = profileStore.getInternalDefaultPSE(); + pse = ProfileStore::getInstance()->getInternalDefaultPSE(); } - defprofile = profileStore.getProfile (pse); + defprofile = ProfileStore::getInstance()->getProfile (pse); // selecting the "Internal" entry profiles->setInternalEntry (); diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index 8293c1803..72c9db36b 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -24,9 +24,9 @@ #include "../rtengine/rtengine.h" #include "pparamschangelistener.h" #include "profilechangelistener.h" -#include "profilestore.h" #include "partialpastedlg.h" #include "guiutils.h" +#include "profilestorecombobox.h" #include "rtimage.h" class ProfilePanel : public Gtk::Grid, public PParamsChangeListener, public ProfileStoreListener diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc deleted file mode 100644 index d7bf18ab5..000000000 --- a/rtgui/profilestore.cc +++ /dev/null @@ -1,862 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include "profilestore.h" -#include "options.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "dynamicprofile.h" - -ProfileStore profileStore; - -using namespace rtengine; -using namespace rtengine::procparams; - -ProfileStore::ProfileStore () : parseMutex(nullptr), storeState(STORESTATE_NOTINITIALIZED), internalDefaultProfile(nullptr), internalDefaultEntry(nullptr), internalDynamicEntry(nullptr), dynamicRules(new std::vector()) -{ - internalDefaultProfile = new AutoPartialProfile(); - internalDefaultProfile->set(true); -} - -bool ProfileStore::init () -{ - if (storeState == STORESTATE_DELETED) { - return false; - } - - if (storeState == STORESTATE_NOTINITIALIZED) { - storeState = STORESTATE_BEINGINITIALIZED; - parseMutex = new MyMutex(); - _parseProfiles (); - loadDynamicProfileRules(*dynamicRules); - storeState = STORESTATE_INITIALIZED; - } - - return true; -} - -ProfileStore::~ProfileStore () -{ - - if (storeState == STORESTATE_NOTINITIALIZED) { - return; - } - - // This lock prevent object's suppression while scanning the directories - storeState = STORESTATE_DELETED; - MyMutex::MyLock lock(*parseMutex); - - clearProfileList (); - partProfiles.clear (); - clearFileList(); - delete internalDefaultProfile; - delete internalDefaultEntry; - delete internalDynamicEntry; - lock.release(); - delete parseMutex; - parseMutex = nullptr; -} - -/* - * Public method to parse the profiles' directories - * Since there's a race condition in the multithreaded environment on this object, - * parseProfiles may need to ask for initialization of this object, and then will - * ask a mutex lock on it, has it been initialized by this call or not - * - * This method will scan the directory tree again and update the profile list. When finished, - * the listeners will be called in order to update with the new list - */ -void ProfileStore::parseProfiles () -{ - - if (!init()) - // I don't even know if this situation can occur - { - return; - } - - for (auto listener : listeners) { - listener->storeCurrentValue(); - } - - { - MyMutex::MyLock lock(*parseMutex); - - _parseProfiles (); - } - - for (auto listener : listeners) { - listener->updateProfileList(); - listener->restoreValue(); - } -} - -void ProfileStore::_parseProfiles () -{ - - // Acquire the GUI, since the tree model can interact with combobox - GThreadLock threadLock; - - // clear loaded profiles - folders.clear(); - clearFileList(); - clearProfileList (); - - folders.push_back("<<< ROOT >>>"); // Fake path, so parentFolderId == 0 will be used to attach a ProfileStoreEntry to the root container, not sub-menu - - Glib::ustring p1 = options.getUserProfilePath(); - Glib::ustring p2 = options.getGlobalProfilePath(); - bool displayLevel0 = options.useBundledProfiles && !p1.empty() && !p2.empty() && p1 != p2; - - Glib::ustring virtualPath("${U}"); - Glib::ustring currDir("${U}"); - parseDir (p1, virtualPath, currDir, 0, 0, displayLevel0); - - if (displayLevel0) { - virtualPath = "${G}"; - currDir = "${G}"; - parseDir (p2, virtualPath, currDir, 0, 0, displayLevel0); - } - - // sort profiles - std::sort(entries.begin(), entries.end(), SortProfiles() ); - - // entries and partProfiles are empty, but the entry and profiles already exist (they have survived to clearFileList and clearProfileList) - if (!internalDefaultEntry) { - internalDefaultEntry = new ProfileStoreEntry(Glib::ustring("(") + M("PROFILEPANEL_PINTERNAL") + Glib::ustring(")"), PSET_FILE, 0, 0); - } - - entries.push_back(internalDefaultEntry); - partProfiles[internalDefaultEntry] = internalDefaultProfile; - - if (!internalDynamicEntry) { - internalDynamicEntry = new ProfileStoreEntry(Glib::ustring("(") + M("PROFILEPANEL_PDYNAMIC") + Glib::ustring(")"), PSET_FILE, 0, 0); - // do not add it to the entries. This is here only for the preferences dialog - } - - // Check if the default profiles has been found. - if (findEntryFromFullPathU(options.defProfRaw) == nullptr) { - options.setDefProfRawMissing(true); - - if (options.rtSettings.verbose) { - printf("WARNING: Default profile \"%s\" for raw images not found!\n", options.defProfRaw.c_str()); - } - } - - if (findEntryFromFullPathU(options.defProfImg) == nullptr) { - options.setDefProfImgMissing(true); - - if (options.rtSettings.verbose) { - printf("WARNING: Default profile \"%s\" for standard images not found!\n", options.defProfImg.c_str()); - } - } -} - -/// @return Returns true if some files has been found (directories are ignored) -bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0) -{ - - bool fileFound = false; - - // reload the available profiles from the profile dir - if (!realPath.empty() && Glib::file_test(realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) { - unsigned int folder = 0; // folder's own Id - - // add this entry to the folder list - folders.push_back(virtualPath); - folder = (unsigned int)(folders.size()) - 1; - - if (level > 0 || displayLevel0) { - // replace the virtual folder name by a localized text - if (currDir == "${U}") { - currDir = M("PROFILEPANEL_MYPROFILES"); - } else if (currDir == "${G}") { - currDir = M("PROFILEPANEL_GLOBALPROFILES"); - } - - // add this localized text to the file list - entries.push_back( new ProfileStoreEntry(currDir, PSET_FOLDER, parentId, folder) ); - } - - // walking through the directory - Glib::Dir* dir = nullptr; - dir = new Glib::Dir (realPath); - - for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { - currDir = *i; - - if (currDir == "." || currDir == "..") { - continue; - } - - Glib::ustring fname = Glib::build_filename(realPath, currDir); - - if (Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { - Glib::ustring vp(Glib::build_filename(virtualPath, currDir)); - Glib::ustring rp(Glib::build_filename(realPath, currDir)); - fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0); - } else { - size_t lastdot = currDir.find_last_of ('.'); - - if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr(lastdot).casefold() == paramFileExtension) { - // file found - if( options.rtSettings.verbose ) { - printf ("Processing file %s...", fname.c_str()); - } - - Glib::ustring name = currDir.substr(0, lastdot); - - // create the partial profile - AutoPartialProfile *pProf = new AutoPartialProfile(); - int res = pProf->load (fname); - - if (!res && pProf->pparams->ppVersion >= 220) { - fileFound = true; - - if( options.rtSettings.verbose ) { - printf ("OK\n"); - } - - // adding this file to the list - ProfileStoreEntry* filePSE = new ProfileStoreEntry(name, PSET_FILE, folder, 0); - entries.push_back(filePSE); - - // map the partial profile - partProfiles[filePSE] = pProf; - //partProfiles.insert( std::pair (filePSE, pProf) ); - } else if( options.rtSettings.verbose ) { - printf ("failed!\n"); - } - } - } - } - - delete dir; - } - - if (!fileFound && (level > 0 || displayLevel0)) { - // no files found in this level, we delete the subdirectory entry - folders.pop_back(); - entries.pop_back(); - } - - return fileFound; -} - -int ProfileStore::findFolderId(const Glib::ustring &path) -{ - for (std::vector::iterator i = folders.begin(); i != folders.end(); ++i) { - if (*i == path) { - return i - folders.begin(); - } - } - - return -1; -} - -/** @brief Return the ProfileStoreEntry object that match the given file and path - * - * @param fullPath Path of the file; the filename may end by the standard extension, - * but have to begin with a virtual location ( ${G} or ${U} ) - * Will return null on invalid path or if the entry can't be found - */ -const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path) -{ - if (path.empty()) { - return nullptr; - } - - if (path == DEFPROFILE_INTERNAL || path == DEFPROFILE_DYNAMIC) { - return internalDefaultEntry; - } - - // consistently apply casefold() to make sure dot position is correct - const Glib::ustring casefolded_path = path.casefold(); - const Glib::ustring::size_type lastdot_pos = casefolded_path.find_last_of('.'); - - if ( - lastdot_pos != Glib::ustring::npos - && lastdot_pos <= casefolded_path.size() - 4 - && !casefolded_path.compare(lastdot_pos, 4, paramFileExtension) - ) { - // removing the extension - // now use dot position without casefold() - path = path.substr(0, path.find_last_of('.')); - } - - // dir separator may come from options file and may be \ or /, we convert them to G_DIR_SEPARATOR_S - if (path.size() > 4 && (path[4] == '/' || path[4] == '\\')) { - path = path.substr(0, 4) + G_DIR_SEPARATOR_S + path.substr(5); - } - - // removing the filename - Glib::ustring fName = Glib::path_get_basename(path); - - if (!fName.empty()) { - path = path.substr(0, path.length() - fName.length()); - } else { - // path is malformed, returning NULL; - return nullptr; - } - - path = Glib::path_get_dirname(path); - - // 1. find the path in the folder list - int parentFolderId = findFolderId(path); - - if (parentFolderId == -1) { - return nullptr; - } - - // 2. find the entry that match the given filename and parentFolderId - for (auto entry : entries) { - if (entry->parentFolderId == parentFolderId && entry->label == fName) { - return entry; - } - } - - return nullptr; -} - -/** Protected version of findEntryFromFullPathU */ -const ProfileStoreEntry* ProfileStore::findEntryFromFullPath(Glib::ustring path) -{ - MyMutex::MyLock lock(*parseMutex); - return findEntryFromFullPathU(path); -} - -const PartialProfile* ProfileStore::getProfile (Glib::ustring path) -{ - - if (!init()) - // I don't even know if this situation can occur - { - return nullptr; - } - - const ProfileStoreEntry *pse = findEntryFromFullPath(path); - - if (!pse) { - return nullptr; - } - - return getProfile(pse); -} - -const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) -{ - - if (!init()) - // I don't even know if this situation can occur - { - return nullptr; - } - - MyMutex::MyLock lock(*parseMutex); - - if (entry == internalDefaultEntry) { - return internalDefaultProfile; - } - - std::map::iterator iter = partProfiles.find(entry); - - if (iter != partProfiles.end()) { - return iter->second; - } else { - // This shouldn't happen! -#ifndef NDEBUG - printf("WARNING! Profile not found!\n"); -#endif - return nullptr; - } -} - -/** @brief Get a pointer to the profile's vector list - * - * This method grants you unique access to the vector list through Mutex locking. - * When you're done with the file list, you MUST call the releaseFileList method to release the lock. - */ -const std::vector* ProfileStore::getFileList () -{ - /*if (!init()) { - // I don't even know if this situation can occur - return NULL; - }*/ - - parseMutex->lock(); - - return &entries; -} - -void ProfileStore::releaseFileList() -{ - parseMutex->unlock(); -} - -/* - * Send back a pointer to the default procparams for raw or standard images. - * If the profile doesn't already exist in the profile list, - * it will add it with default internal values, so this method never fails - */ -const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) -{ - - if (!init()) - // I don't even know if this situation can occur - { - return nullptr; - } - - //Note: the mutex is locked in getProfile, called below - - const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - - if (!pProf) { - pProf = internalDefaultProfile; - } - - return pProf->pparams; -} - -/* - * Send back a pointer to the default partial profile for raw or standard images. - * If it doesn't already exist in the profile list, it will add it with default internal values, - * so this method will never fails - */ -const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) -{ - - if (!init()) - // I don't even know if this situation can occur - { - return nullptr; - } - - //Note: the mutex is locked in getProfile, called below - - const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - - if (!pProf) { - pProf = internalDefaultProfile; - } - - return pProf; -} - -const Glib::ustring ProfileStore::getPathFromId(int folderId) -{ - return folders.at(folderId); -} - - -void ProfileStore::clearFileList() -{ - for (auto entry : entries) { - if (entry != internalDefaultEntry) { - delete entry; - } - } - - entries.clear(); -} - -void ProfileStore::clearProfileList() -{ - for (auto partProfile : partProfiles) { - if (partProfile.second != internalDefaultProfile) { - delete partProfile.second; - } - } - - partProfiles.clear(); -} - -void ProfileStore::addListener(ProfileStoreListener *listener) -{ - listeners.push_back(listener); -} - -void ProfileStore::removeListener(ProfileStoreListener *listener) -{ - listeners.remove(listener); -} - -void ProfileStore::dumpFolderList() -{ - printf("Folder list:\n------------\n"); - - for (unsigned int i = 0; i < folders.size(); i++) { - printf(" #%3ud - %s\n", i, folders.at(i).c_str()); - } - - printf("\n"); -} - - -const std::vector &ProfileStore::getDynamicProfileRules() const -{ - return *dynamicRules; -} - - -void ProfileStore::setDynamicProfileRules(const std::vector &r) -{ - *dynamicRules = r; -} - - - -ProfileStoreEntry::ProfileStoreEntry() : label(""), type(PSET_FOLDER), parentFolderId(0), folderId(0) {} - -ProfileStoreEntry::ProfileStoreEntry(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) : label(label), type(type), parentFolderId(parentFolder), folderId(folder) {} - -void ProfileStoreEntry::setValues(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) -{ - this->label = label; - this->type = type; - parentFolderId = parentFolder; - folderId = folder; -} - -ProfileStoreLabel::ProfileStoreLabel(const ProfileStoreEntry *entry) : Gtk::Label(entry->label), entry(entry) -{ - set_alignment(0, 0.5); - set_ellipsize(Pango::ELLIPSIZE_END); - show(); -} - -ProfileStoreComboBox::ProfileStoreComboBox () -{ - updateProfileList(); - setPreferredWidth(50, 120); -} - -Glib::ustring ProfileStoreComboBox::getCurrentLabel() -{ - Glib::ustring currLabel; - Gtk::TreeModel::iterator currRow = get_active(); - - if (currRow) { - const ProfileStoreEntry *currEntry = (*currRow)[methodColumns.profileStoreEntry]; - return currEntry->label; - } - - return currLabel; -} - -const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() -{ - Gtk::TreeModel::iterator currRow_ = get_active(); - Gtk::TreeModel::Row currRow = *currRow_; - - if (currRow) { - return currRow[methodColumns.profileStoreEntry]; - } else { - return nullptr; - } -} - -/** @brief Recursive method to update the combobox entries */ -void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList) -{ - for (auto entry : *entryList) { - if (entry->parentFolderId == parentFolderId) { // filtering the entry of the same folder - if (entry->type == PSET_FOLDER) { - Glib::ustring folderPath( profileStore.getPathFromId(entry->folderId) ); - - if (options.useBundledProfiles || ((folderPath != "${G}" ) && (folderPath != "${U}" ))) { - // creating the new submenu - Gtk::TreeModel::Row newSubMenu; - - if (initial) { - newSubMenu = *(refTreeModel->append()); - } else { - newSubMenu = *(refTreeModel->append(parentRow->children())); - } - - // creating and assigning the custom Label object - newSubMenu[methodColumns.label] = entry->label; - newSubMenu[methodColumns.profileStoreEntry] = entry; -#if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION == 18 - // HACK: Workaround for bug in Gtk+ 3.18... - Gtk::TreeModel::Row menuHeader = *(refTreeModel->append(newSubMenu->children())); - menuHeader[methodColumns.label] = "-"; - menuHeader[methodColumns.profileStoreEntry] = entry; -#endif - refreshProfileList_ (&newSubMenu, entry->folderId, false, entryList); - } else { - refreshProfileList_ (parentRow, entry->folderId, true, entryList); - } - } else { - Gtk::TreeModel::Row newItem; - - // creating a menu entry - if (initial) { - newItem = *(refTreeModel->append()); - } else { - newItem = *(refTreeModel->append(parentRow->children())); - } - - newItem[methodColumns.label] = entry->label; - newItem[methodColumns.profileStoreEntry] = entry; - } - } - } -} -/** @brief Get the ProfileStore's entry list and recreate the combobox entries. - * If you want to update the ProfileStore list itself (rescan the dir tree), use the "ProfileStore::parseProfiles" method instead - * - * This method has to be called by the ProfileStoreListener having a ProfileStoreComboBox. - */ -void ProfileStoreComboBox::updateProfileList () -{ - // clear items - clear(); - refTreeModel.clear(); - // Create the Tree model - refTreeModel = Gtk::TreeStore::create(methodColumns); - // Assign the model to the Combobox - set_model(refTreeModel); - - // this will lock the profilestore's entry list too - const std::vector *entryList = profileStore.getFileList(); - - //profileStore.dumpFolderList(); - refreshProfileList_ (NULL, entryList->at(0)->parentFolderId, true, entryList); - - if (entryList->at(0)->parentFolderId != 0) { - // special case for the Internal default entry - addRow(profileStore.getInternalDefaultPSE()); - } - - // releasing the profilestore's entry list mutex - profileStore.releaseFileList(); - - pack_start(methodColumns.label, false); - - Gtk::CellRendererText* cellRenderer = dynamic_cast(get_first_cell()); - cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE; - cellRenderer->property_ellipsize_set() = true; -} - -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) -{ - Gtk::TreeModel::Row row; - Gtk::TreeIter rowInSubLevel; - - for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - row = *iter; - // Hombre: is there a smarter way of knowing if this row has childs? - const ProfileStoreEntry *pse_ = row[methodColumns.profileStoreEntry]; - - if (pse_->type == PSET_FOLDER) { - rowInSubLevel = findRowFromEntry_ (iter->children(), pse); - - if (rowInSubLevel) { - // entry found - return rowInSubLevel; - } - } else if (pse_ == pse) { - // entry found - return iter; - } - } - - return childs.end(); -} - -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) -{ - Gtk::TreeModel::Children childs = refTreeModel->children(); - - if (pse) { - Gtk::TreeIter row = findRowFromEntry_ (childs, pse); - return row; - } - - return childs.end(); -} - -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name) -{ - Gtk::TreeModel::Row row; - Gtk::TreeIter rowInSubLevel; - - for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - row = *iter; - // Hombre: is there a smarter way of knowing if this row has childs? - const ProfileStoreEntry *pse = row[methodColumns.profileStoreEntry]; - - if (pse->type == PSET_FOLDER) { - rowInSubLevel = findRowFromFullPath_ (iter->children(), parentFolderId, name); - - if (rowInSubLevel) { - // entry found - return rowInSubLevel; - } - } else if (parentFolderId == pse->parentFolderId && name == pse->label) { - // entry found - return iter; - } - } - - return childs.end(); -} - -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) -{ - Gtk::TreeIter row; - - if (path.empty()) { - return row; - } - - if (path == DEFPROFILE_INTERNAL) { - row = findRowFromEntry(profileStore.getInternalDefaultPSE()); - return row; - } - - if (path == DEFPROFILE_DYNAMIC) { - row = findRowFromEntry(profileStore.getInternalDynamicPSE()); - return row; - } - - // removing the filename - Glib::ustring fName = Glib::path_get_basename(path); - - if (!fName.empty()) { - path = path.substr(0, path.length() - fName.length()); - } else { - // path is malformed; - return row; - } - - path = Glib::path_get_dirname(path); - int parentFolderId = profileStore.findFolderId(path); - - // 1. find the path in the folder list - if (parentFolderId != -1) { - row = findRowFromFullPath_ (refTreeModel->children(), parentFolderId, fName); - } - - return row; -} - -/** @brief Get the absolute full path of the active row entry. - * @return The absolute full path of the active row entry, or the "Internal" keyword, - * or an empty string if the ComboBox is in an invalid state - */ -Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() -{ - Glib::ustring path; - Gtk::TreeModel::iterator currRowI = get_active(); - - if (!currRowI) { - return path; - } - - Gtk::TreeModel::Row currRow = *currRowI; - - if (currRow) { - - const ProfileStoreEntry *currEntry = currRow[methodColumns.profileStoreEntry]; - - if (!currEntry) { - return path; - } - - if (currEntry == profileStore.getInternalDefaultPSE()) { - return Glib::ustring(DEFPROFILE_INTERNAL); - } - - if (currEntry == profileStore.getInternalDynamicPSE()) { - return Glib::ustring(DEFPROFILE_DYNAMIC); - } - - path = Glib::build_filename(profileStore.getPathFromId(currEntry->parentFolderId), currEntry->label); - } - - return path; -} - -bool ProfileStoreComboBox::setActiveRowFromFullPath(Glib::ustring path) -{ - if (!path.empty()) { - Gtk::TreeIter row = findRowFromFullPath(path); - - if (row) { - set_active(row); - return true; - } - } - - return false; -} - -bool ProfileStoreComboBox::setActiveRowFromEntry(const ProfileStoreEntry *pse) -{ - if (pse) { - Gtk::TreeIter row = findRowFromEntry(pse); - - if (row) { - set_active(row); - return true; - } - } - - return false; -} - -bool ProfileStoreComboBox::setInternalEntry () -{ - return setActiveRowFromEntry(profileStore.getInternalDefaultPSE()); -} - -/** @brief Get the row from the first level of the tree that match the provided name */ -Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel(Glib::ustring name) -{ - Gtk::TreeIter row; - Gtk::TreeModel::Children childs = refTreeModel->children(); - - if (!name.empty()) { - Gtk::TreeModel::Row currRow; - - for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - currRow = *iter; - const ProfileStoreEntry *pse = currRow[methodColumns.profileStoreEntry]; - - if (pse->label == name) { - return currRow; - } - } - } - - return childs.end(); - //return refTreeModel->get_iter(""); // is this fast? We want to send back a null, anvalid or end() iterator object here -} - -/** @brief Add a new row to the first level of the tree */ -Gtk::TreeIter ProfileStoreComboBox::addRow(const ProfileStoreEntry *profileStoreEntry) -{ - Gtk::TreeIter newEntry = refTreeModel->append(); - Gtk::TreeModel::Row row = *newEntry; - row[methodColumns.label] = profileStoreEntry->label; - row[methodColumns.profileStoreEntry] = profileStoreEntry; - return newEntry; -} - diff --git a/rtgui/profilestorecombobox.cc b/rtgui/profilestorecombobox.cc new file mode 100644 index 000000000..186309aa3 --- /dev/null +++ b/rtgui/profilestorecombobox.cc @@ -0,0 +1,358 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "../rtengine/profilestore.h" +#include "profilestorecombobox.h" + +#include "../rtengine/dynamicprofile.h" +#include "options.h" +#include "toolpanel.h" +#include "guiutils.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +ProfileStoreLabel::ProfileStoreLabel (const ProfileStoreEntry *entry) : Gtk::Label (entry->label), entry (entry) +{ + set_alignment (0, 0.5); + set_ellipsize (Pango::ELLIPSIZE_END); + show(); +} + +ProfileStoreComboBox::ProfileStoreComboBox () +{ + updateProfileList(); + setPreferredWidth (50, 120); +} + +Glib::ustring ProfileStoreComboBox::getCurrentLabel() +{ + Glib::ustring currLabel; + Gtk::TreeModel::iterator currRow = get_active(); + + if (currRow) { + const ProfileStoreEntry *currEntry = (*currRow)[methodColumns.profileStoreEntry]; + return currEntry->label; + } + + return currLabel; +} + +const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() +{ + Gtk::TreeModel::iterator currRow_ = get_active(); + Gtk::TreeModel::Row currRow = *currRow_; + + if (currRow) { + return currRow[methodColumns.profileStoreEntry]; + } else { + return nullptr; + } +} + +/** @brief Recursive method to update the combobox entries */ +void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList) +{ + for (auto entry : *entryList) { + if (entry->parentFolderId == parentFolderId) { // filtering the entry of the same folder + if (entry->type == PSET_FOLDER) { + Glib::ustring folderPath ( ProfileStore::getInstance()->getPathFromId (entry->folderId) ); + + if (options.useBundledProfiles || ((folderPath != "${G}" ) && (folderPath != "${U}" ))) { + // creating the new submenu + Gtk::TreeModel::Row newSubMenu; + + if (initial) { + newSubMenu = * (refTreeModel->append()); + } else { + newSubMenu = * (refTreeModel->append (parentRow->children())); + } + + // creating and assigning the custom Label object + newSubMenu[methodColumns.label] = entry->label; + newSubMenu[methodColumns.profileStoreEntry] = entry; +#if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION == 18 + // HACK: Workaround for bug in Gtk+ 3.18... + Gtk::TreeModel::Row menuHeader = * (refTreeModel->append (newSubMenu->children())); + menuHeader[methodColumns.label] = "-"; + menuHeader[methodColumns.profileStoreEntry] = entry; +#endif + refreshProfileList_ (&newSubMenu, entry->folderId, false, entryList); + } else { + refreshProfileList_ (parentRow, entry->folderId, true, entryList); + } + } else { + Gtk::TreeModel::Row newItem; + + // creating a menu entry + if (initial) { + newItem = * (refTreeModel->append()); + } else { + newItem = * (refTreeModel->append (parentRow->children())); + } + + newItem[methodColumns.label] = entry->label; + newItem[methodColumns.profileStoreEntry] = entry; + } + } + } +} +/** @brief Get the ProfileStore's entry list and recreate the combobox entries. + * If you want to update the ProfileStore list itself (rescan the dir tree), use the "ProfileStore::parseProfiles" method instead + * + * This method has to be called by the ProfileStoreListener having a ProfileStoreComboBox. + */ +void ProfileStoreComboBox::updateProfileList () +{ + // clear items + clear(); + refTreeModel.clear(); + // Create the Tree model + refTreeModel = Gtk::TreeStore::create (methodColumns); + // Assign the model to the Combobox + set_model (refTreeModel); + + // this will lock the profilestore's entry list too + const std::vector *entryList = ProfileStore::getInstance()->getFileList(); + + //profileStore.dumpFolderList(); + refreshProfileList_ (NULL, entryList->at (0)->parentFolderId, true, entryList); + + if (entryList->at (0)->parentFolderId != 0) { + // special case for the Internal default entry + addRow (ProfileStore::getInstance()->getInternalDefaultPSE()); + } + + // releasing the profilestore's entry list mutex + ProfileStore::getInstance()->releaseFileList(); + + pack_start (methodColumns.label, false); + + Gtk::CellRendererText* cellRenderer = dynamic_cast (get_first_cell()); + cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE; + cellRenderer->property_ellipsize_set() = true; +} + +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) +{ + Gtk::TreeModel::Row row; + Gtk::TreeIter rowInSubLevel; + + for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { + row = *iter; + // Hombre: is there a smarter way of knowing if this row has childs? + const ProfileStoreEntry *pse_ = row[methodColumns.profileStoreEntry]; + + if (pse_->type == PSET_FOLDER) { + rowInSubLevel = findRowFromEntry_ (iter->children(), pse); + + if (rowInSubLevel) { + // entry found + return rowInSubLevel; + } + } else if (pse_ == pse) { + // entry found + return iter; + } + } + + return childs.end(); +} + +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) +{ + Gtk::TreeModel::Children childs = refTreeModel->children(); + + if (pse) { + Gtk::TreeIter row = findRowFromEntry_ (childs, pse); + return row; + } + + return childs.end(); +} + +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name) +{ + Gtk::TreeModel::Row row; + Gtk::TreeIter rowInSubLevel; + + for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { + row = *iter; + // Hombre: is there a smarter way of knowing if this row has childs? + const ProfileStoreEntry *pse = row[methodColumns.profileStoreEntry]; + + if (pse->type == PSET_FOLDER) { + rowInSubLevel = findRowFromFullPath_ (iter->children(), parentFolderId, name); + + if (rowInSubLevel) { + // entry found + return rowInSubLevel; + } + } else if (parentFolderId == pse->parentFolderId && name == pse->label) { + // entry found + return iter; + } + } + + return childs.end(); +} + +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) +{ + Gtk::TreeIter row; + ProfileStore *profileStore = ProfileStore::getInstance(); + + if (path.empty()) { + return row; + } + + if (path == DEFPROFILE_INTERNAL) { + row = findRowFromEntry (profileStore->getInternalDefaultPSE()); + return row; + } + + if (path == DEFPROFILE_DYNAMIC) { + row = findRowFromEntry (profileStore->getInternalDynamicPSE()); + return row; + } + + // removing the filename + Glib::ustring fName = Glib::path_get_basename (path); + + if (!fName.empty()) { + path = path.substr (0, path.length() - fName.length()); + } else { + // path is malformed; + return row; + } + + path = Glib::path_get_dirname (path); + int parentFolderId = profileStore->findFolderId (path); + + // 1. find the path in the folder list + if (parentFolderId != -1) { + row = findRowFromFullPath_ (refTreeModel->children(), parentFolderId, fName); + } + + return row; +} + +/** @brief Get the absolute full path of the active row entry. + * @return The absolute full path of the active row entry, or the "Internal" keyword, + * or an empty string if the ComboBox is in an invalid state + */ +Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() +{ + Glib::ustring path; + Gtk::TreeModel::iterator currRowI = get_active(); + ProfileStore *profileStore = ProfileStore::getInstance(); + + if (!currRowI) { + return path; + } + + Gtk::TreeModel::Row currRow = *currRowI; + + if (currRow) { + + const ProfileStoreEntry *currEntry = currRow[methodColumns.profileStoreEntry]; + + if (!currEntry) { + return path; + } + + if (currEntry == profileStore->getInternalDefaultPSE()) { + return Glib::ustring (DEFPROFILE_INTERNAL); + } + + if (currEntry == profileStore->getInternalDynamicPSE()) { + return Glib::ustring (DEFPROFILE_DYNAMIC); + } + + path = Glib::build_filename (profileStore->getPathFromId (currEntry->parentFolderId), currEntry->label); + } + + return path; +} + +bool ProfileStoreComboBox::setActiveRowFromFullPath (Glib::ustring path) +{ + if (!path.empty()) { + Gtk::TreeIter row = findRowFromFullPath (path); + + if (row) { + set_active (row); + return true; + } + } + + return false; +} + +bool ProfileStoreComboBox::setActiveRowFromEntry (const ProfileStoreEntry *pse) +{ + if (pse) { + Gtk::TreeIter row = findRowFromEntry (pse); + + if (row) { + set_active (row); + return true; + } + } + + return false; +} + +bool ProfileStoreComboBox::setInternalEntry () +{ + return setActiveRowFromEntry (ProfileStore::getInstance()->getInternalDefaultPSE()); +} + +/** @brief Get the row from the first level of the tree that match the provided name */ +Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel (Glib::ustring name) +{ + Gtk::TreeIter row; + Gtk::TreeModel::Children childs = refTreeModel->children(); + + if (!name.empty()) { + Gtk::TreeModel::Row currRow; + + for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { + currRow = *iter; + const ProfileStoreEntry *pse = currRow[methodColumns.profileStoreEntry]; + + if (pse->label == name) { + return currRow; + } + } + } + + return childs.end(); + //return refTreeModel->get_iter(""); // is this fast? We want to send back a null, anvalid or end() iterator object here +} + +/** @brief Add a new row to the first level of the tree */ +Gtk::TreeIter ProfileStoreComboBox::addRow (const ProfileStoreEntry *profileStoreEntry) +{ + Gtk::TreeIter newEntry = refTreeModel->append(); + Gtk::TreeModel::Row row = *newEntry; + row[methodColumns.label] = profileStoreEntry->label; + row[methodColumns.profileStoreEntry] = profileStoreEntry; + return newEntry; +} + diff --git a/rtgui/profilestorecombobox.h b/rtgui/profilestorecombobox.h new file mode 100644 index 000000000..111e767c2 --- /dev/null +++ b/rtgui/profilestorecombobox.h @@ -0,0 +1,95 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _PROFILESTORECOMBOBOX_ +#define _PROFILESTORECOMBOBOX_ + +#include +#include +#include + +#include "../rtengine/rtengine.h" +#include "../rtengine/noncopyable.h" +#include "../rtengine/profilestore.h" + +#include "threadutils.h" +#include "paramsedited.h" +#include "guiutils.h" + + +/** + * @brief subclass of Gtk::Label with extra fields for Combobox and Menu, to link with a ProfileStoreEntry + */ +class ProfileStoreLabel : public Gtk::Label +{ + +public: + const ProfileStoreEntry *entry; + +#ifndef NDEBUG + ProfileStoreLabel() : Gtk::Label ("*** error ***"), entry (nullptr) {} +#else + ProfileStoreLabel() : Gtk::Label (""), entry (NULL) {} +#endif + + /** @brief Create a new ProfileStoreLabel + * + * @param entry Pointer to the ProfileStoreEntry object, be it a directory or a file + */ + explicit ProfileStoreLabel (const ProfileStoreEntry *entry); + ProfileStoreLabel (const ProfileStoreLabel &other); +}; + +class ProfileStoreComboBox : public MyComboBox +{ + +protected: + class MethodColumns : public Gtk::TreeModel::ColumnRecord + { + public: + Gtk::TreeModelColumn label; + Gtk::TreeModelColumn profileStoreEntry; + MethodColumns() + { + add (label); + add (profileStoreEntry); + } + }; + + Glib::RefPtr refTreeModel; + MethodColumns methodColumns; + void refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList); + Gtk::TreeIter findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse); + Gtk::TreeIter findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name); + +public: + ProfileStoreComboBox(); + void updateProfileList(); + Glib::ustring getCurrentLabel(); + const ProfileStoreEntry* getSelectedEntry(); + Gtk::TreeIter findRowFromEntry (const ProfileStoreEntry *pse); + Gtk::TreeIter findRowFromFullPath (Glib::ustring path); + Glib::ustring getFullPathFromActiveRow (); + bool setActiveRowFromFullPath (Glib::ustring oldPath); + bool setActiveRowFromEntry (const ProfileStoreEntry *pse); + bool setInternalEntry (); + Gtk::TreeIter getRowFromLabel (Glib::ustring name); + Gtk::TreeIter addRow (const ProfileStoreEntry *profileStoreEntry); +}; + +#endif diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 80ef51e9d..6f05f3f72 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -8,9 +8,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), false, true), lastmedianmap(false) +Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL"), false, true), lastmedianmap (false) { - CurveListener::setMulti(true); + CurveListener::setMulti (true); std::vector defaultCurve; std::vector milestones; nextmin = 0.; @@ -31,78 +31,78 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), Gtk::Grid *retinexGrid = Gtk::manage ( new Gtk::Grid()); - setExpandAlignProperties(retinexGrid, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (retinexGrid, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); dhgrid = Gtk::manage (new Gtk::Grid ()); - setExpandAlignProperties(dhgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (dhgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - labmdh = Gtk::manage (new Gtk::Label (M("TP_RETINEX_METHOD") + ":")); - setExpandAlignProperties(labmdh, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - dhgrid->attach(*labmdh, 0, 0, 1, 1); + labmdh = Gtk::manage (new Gtk::Label (M ("TP_RETINEX_METHOD") + ":")); + setExpandAlignProperties (labmdh, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + dhgrid->attach (*labmdh, 0, 0, 1, 1); retinexMethod = Gtk::manage (new MyComboBoxText ()); - setExpandAlignProperties(retinexMethod, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - retinexMethod->append (M("TP_RETINEX_LOW")); - retinexMethod->append (M("TP_RETINEX_UNIFORM")); - retinexMethod->append (M("TP_RETINEX_HIGH")); - retinexMethod->append (M("TP_RETINEX_HIGHLIG")); + setExpandAlignProperties (retinexMethod, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + retinexMethod->append (M ("TP_RETINEX_LOW")); + retinexMethod->append (M ("TP_RETINEX_UNIFORM")); + retinexMethod->append (M ("TP_RETINEX_HIGH")); + retinexMethod->append (M ("TP_RETINEX_HIGHLIG")); // retinexMethod->append (M("TP_RETINEX_HIGHLIGPLUS")); - retinexMethod->set_active(0); - retinexMethodConn = retinexMethod->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::retinexMethodChanged) ); - retinexMethod->set_tooltip_markup (M("TP_RETINEX_METHOD_TOOLTIP")); - dhgrid->attach(*retinexMethod, 1, 0, 1, 1); + retinexMethod->set_active (0); + retinexMethodConn = retinexMethod->signal_changed().connect ( sigc::mem_fun (*this, &Retinex::retinexMethodChanged) ); + retinexMethod->set_tooltip_markup (M ("TP_RETINEX_METHOD_TOOLTIP")); + dhgrid->attach (*retinexMethod, 1, 0, 1, 1); retinexcolorspace = Gtk::manage (new MyComboBoxText ()); - setExpandAlignProperties(retinexcolorspace, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - retinexcolorspace->append (M("TP_RETINEX_LABSPACE")); - retinexcolorspace->append (M("TP_RETINEX_HSLSPACE_LOG")); - retinexcolorspace->append (M("TP_RETINEX_HSLSPACE_LIN")); - retinexcolorspace->set_active(0); - retinexColorSpaceConn = retinexcolorspace->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::retinexColorSpaceChanged) ); - dhgrid->attach(*retinexcolorspace, 2, 0, 1, 1); - retinexGrid->attach(*dhgrid, 0, 0, 1, 1); + setExpandAlignProperties (retinexcolorspace, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + retinexcolorspace->append (M ("TP_RETINEX_LABSPACE")); + retinexcolorspace->append (M ("TP_RETINEX_HSLSPACE_LOG")); + retinexcolorspace->append (M ("TP_RETINEX_HSLSPACE_LIN")); + retinexcolorspace->set_active (0); + retinexColorSpaceConn = retinexcolorspace->signal_changed().connect ( sigc::mem_fun (*this, &Retinex::retinexColorSpaceChanged) ); + dhgrid->attach (*retinexcolorspace, 2, 0, 1, 1); + retinexGrid->attach (*dhgrid, 0, 0, 1, 1); - str = Gtk::manage (new Adjuster (M("TP_RETINEX_STRENGTH"), 0, 100., 1., 20.)); - setExpandAlignProperties(str, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - retinexGrid->attach(*str, 0, 1, 1, 1); + str = Gtk::manage (new Adjuster (M ("TP_RETINEX_STRENGTH"), 0, 100., 1., 20.)); + setExpandAlignProperties (str, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + retinexGrid->attach (*str, 0, 1, 1, 1); str->show (); - neigh = Gtk::manage (new Adjuster (M("TP_RETINEX_NEIGHBOR"), 6, 100., 1., 80.)); - setExpandAlignProperties(neigh, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - retinexGrid->attach(*neigh, 0, 2, 1, 1); + neigh = Gtk::manage (new Adjuster (M ("TP_RETINEX_NEIGHBOR"), 6, 100., 1., 80.)); + setExpandAlignProperties (neigh, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + retinexGrid->attach (*neigh, 0, 2, 1, 1); neigh->show (); - vart = Gtk::manage (new Adjuster (M("TP_RETINEX_VARIANCE"), 50, 500, 1, 200)); - setExpandAlignProperties(vart, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - vart->set_tooltip_markup (M("TP_RETINEX_VARIANCE_TOOLTIP")); - retinexGrid->attach(*vart, 0, 3, 1, 1); + vart = Gtk::manage (new Adjuster (M ("TP_RETINEX_VARIANCE"), 50, 500, 1, 200)); + setExpandAlignProperties (vart, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + vart->set_tooltip_markup (M ("TP_RETINEX_VARIANCE_TOOLTIP")); + retinexGrid->attach (*vart, 0, 3, 1, 1); vart->show (); - highl = Gtk::manage (new Adjuster (M("TP_RETINEX_HIGHLIGHT"), 1, 20, 1, 4)); - setExpandAlignProperties(highl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - highl->set_tooltip_markup (M("TP_RETINEX_HIGHLIGHT_TOOLTIP")); - retinexGrid->attach(*highl, 0, 4, 1, 1); + highl = Gtk::manage (new Adjuster (M ("TP_RETINEX_HIGHLIGHT"), 1, 20, 1, 4)); + setExpandAlignProperties (highl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + highl->set_tooltip_markup (M ("TP_RETINEX_HIGHLIGHT_TOOLTIP")); + retinexGrid->attach (*highl, 0, 4, 1, 1); highl->show (); viewgrid = Gtk::manage (new Gtk::Grid ()); - setExpandAlignProperties(viewgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (viewgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - labview = Gtk::manage (new Gtk::Label (M("TP_RETINEX_VIEW") + ":")); - setExpandAlignProperties(labview, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - viewgrid->attach(*labview, 0, 0, 1, 1); + labview = Gtk::manage (new Gtk::Label (M ("TP_RETINEX_VIEW") + ":")); + setExpandAlignProperties (labview, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + viewgrid->attach (*labview, 0, 0, 1, 1); viewMethod = Gtk::manage (new MyComboBoxText ()); - setExpandAlignProperties(viewMethod, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - viewMethod->append (M("TP_RETINEX_VIEW_NONE")); - viewMethod->append (M("TP_RETINEX_VIEW_UNSHARP")); - viewMethod->append (M("TP_RETINEX_VIEW_MASK")); - viewMethod->append (M("TP_RETINEX_VIEW_TRAN")); - viewMethod->append (M("TP_RETINEX_VIEW_TRAN2")); - viewMethod->set_active(0); - viewMethodConn = viewMethod->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::viewMethodChanged) ); - viewMethod->set_tooltip_markup (M("TP_RETINEX_VIEW_METHOD_TOOLTIP")); - viewgrid->attach(*viewMethod, 1, 0, 1, 1); - retinexGrid->attach(*viewgrid, 0, 5, 1, 1); + setExpandAlignProperties (viewMethod, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + viewMethod->append (M ("TP_RETINEX_VIEW_NONE")); + viewMethod->append (M ("TP_RETINEX_VIEW_UNSHARP")); + viewMethod->append (M ("TP_RETINEX_VIEW_MASK")); + viewMethod->append (M ("TP_RETINEX_VIEW_TRAN")); + viewMethod->append (M ("TP_RETINEX_VIEW_TRAN2")); + viewMethod->set_active (0); + viewMethodConn = viewMethod->signal_changed().connect ( sigc::mem_fun (*this, &Retinex::viewMethodChanged) ); + viewMethod->set_tooltip_markup (M ("TP_RETINEX_VIEW_METHOD_TOOLTIP")); + viewgrid->attach (*viewMethod, 1, 0, 1, 1); + retinexGrid->attach (*viewgrid, 0, 5, 1, 1); //------------- @@ -112,78 +112,78 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), // MAP (MASK) Frame --------------------------------------------------------------- - Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_LABEL_MASK")) ); - setExpandAlignProperties(maskFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) ); + setExpandAlignProperties (maskFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); Gtk::Grid *maskGrid = Gtk::manage ( new Gtk::Grid()); - setExpandAlignProperties(maskGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (maskGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); // Map Method mapgrid = Gtk::manage (new Gtk::Grid ()); - setExpandAlignProperties(mapgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (mapgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - labmap = Gtk::manage (new Gtk::Label (M("TP_RETINEX_MAP") + ":")); - setExpandAlignProperties(labmap, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - mapgrid->attach(*labmap, 0, 0, 1, 1); + labmap = Gtk::manage (new Gtk::Label (M ("TP_RETINEX_MAP") + ":")); + setExpandAlignProperties (labmap, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + mapgrid->attach (*labmap, 0, 0, 1, 1); mapMethod = Gtk::manage (new MyComboBoxText ()); - setExpandAlignProperties(mapMethod, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - mapMethod->append (M("TP_RETINEX_MAP_NONE")); - mapMethod->append (M("TP_RETINEX_MAP_GAUS")); - mapMethod->append (M("TP_RETINEX_MAP_MAPP")); - mapMethod->append (M("TP_RETINEX_MAP_MAPT")); - mapMethod->set_active(0); - mapMethodConn = mapMethod->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::mapMethodChanged) ); - mapMethod->set_tooltip_markup (M("TP_RETINEX_MAP_METHOD_TOOLTIP")); - mapgrid->attach(*mapMethod, 1, 0, 1, 1); + setExpandAlignProperties (mapMethod, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + mapMethod->append (M ("TP_RETINEX_MAP_NONE")); + mapMethod->append (M ("TP_RETINEX_MAP_GAUS")); + mapMethod->append (M ("TP_RETINEX_MAP_MAPP")); + mapMethod->append (M ("TP_RETINEX_MAP_MAPT")); + mapMethod->set_active (0); + mapMethodConn = mapMethod->signal_changed().connect ( sigc::mem_fun (*this, &Retinex::mapMethodChanged) ); + mapMethod->set_tooltip_markup (M ("TP_RETINEX_MAP_METHOD_TOOLTIP")); + mapgrid->attach (*mapMethod, 1, 0, 1, 1); - maskGrid->attach(*mapgrid, 0, 0, 1, 1); + maskGrid->attach (*mapgrid, 0, 0, 1, 1); mapgrid->show(); // Map Equalizer - curveEditormap = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_MAP")); - setExpandAlignProperties(curveEditormap, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + curveEditormap = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_CONTEDIT_MAP")); + setExpandAlignProperties (curveEditormap, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); curveEditormap->setCurveListener (this); std::vector milestones222; - milestones222.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones222.push_back( GradientMilestone(1., 1., 1., 1.) ); - mapshape = static_cast(curveEditormap->addCurve(CT_Diagonal, M("TP_RETINEX_CURVEEDITOR_MAP"))); - mapshape->setTooltip(M("TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP")); - mapshape->setBottomBarBgGradient(milestones222); - mapshape->setLeftBarBgGradient(milestones222); + milestones222.push_back ( GradientMilestone (0., 0., 0., 0.) ); + milestones222.push_back ( GradientMilestone (1., 1., 1., 1.) ); + mapshape = static_cast (curveEditormap->addCurve (CT_Diagonal, M ("TP_RETINEX_CURVEEDITOR_MAP"))); + mapshape->setTooltip (M ("TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP")); + mapshape->setBottomBarBgGradient (milestones222); + mapshape->setLeftBarBgGradient (milestones222); curveEditormap->curveListComplete(); - maskGrid->attach(*curveEditormap, 0, 1, 1, 1); + maskGrid->attach (*curveEditormap, 0, 1, 1, 1); curveEditormap->show(); // Adjusters - highlights = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0)); - setExpandAlignProperties(highlights, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - maskGrid->attach(*highlights, 0, 2, 1, 1); + highlights = Gtk::manage (new Adjuster (M ("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0)); + setExpandAlignProperties (highlights, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + maskGrid->attach (*highlights, 0, 2, 1, 1); highlights->show(); - h_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 80)); - setExpandAlignProperties(h_tonalwidth, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - maskGrid->attach(*h_tonalwidth, 0, 3, 1, 1); + h_tonalwidth = Gtk::manage (new Adjuster (M ("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 80)); + setExpandAlignProperties (h_tonalwidth, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + maskGrid->attach (*h_tonalwidth, 0, 3, 1, 1); h_tonalwidth->show(); - shadows = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0)); - setExpandAlignProperties(shadows, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - maskGrid->attach(*shadows, 0, 4, 1, 1); + shadows = Gtk::manage (new Adjuster (M ("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0)); + setExpandAlignProperties (shadows, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + maskGrid->attach (*shadows, 0, 4, 1, 1); shadows->show(); - s_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 80)); - setExpandAlignProperties(s_tonalwidth, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - maskGrid->attach(*s_tonalwidth, 0, 5, 1, 1); + s_tonalwidth = Gtk::manage (new Adjuster (M ("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 80)); + setExpandAlignProperties (s_tonalwidth, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + maskGrid->attach (*s_tonalwidth, 0, 5, 1, 1); s_tonalwidth->show(); - radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 40)); - setExpandAlignProperties(radius, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - maskGrid->attach(*radius, 0, 6, 1, 1); + radius = Gtk::manage (new Adjuster (M ("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 40)); + setExpandAlignProperties (radius, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + maskGrid->attach (*radius, 0, 6, 1, 1); radius->show(); //------------- - maskFrame->add(*maskGrid); + maskFrame->add (*maskGrid); pack_start (*maskFrame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -194,286 +194,288 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), - expsettings = new MyExpander (false, M("TP_RETINEX_SETTINGS")); - setExpandAlignProperties(expsettings, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - expsettings->signal_button_release_event().connect_notify( sigc::bind( sigc::mem_fun(this, &Retinex::foldAllButMe), expsettings) ); + expsettings = new MyExpander (false, M ("TP_RETINEX_SETTINGS")); + setExpandAlignProperties (expsettings, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + expsettings->signal_button_release_event().connect_notify ( sigc::bind ( sigc::mem_fun (this, &Retinex::foldAllButMe), expsettings) ); Gtk::Grid *settingsGrid = Gtk::manage ( new Gtk::Grid()); - setExpandAlignProperties(settingsGrid, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (settingsGrid, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - mMLabels = Gtk::manage(new Gtk::Label("---")); - setExpandAlignProperties(mMLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); - mMLabels->set_tooltip_markup (M("TP_RETINEX_MLABEL_TOOLTIP")); - settingsGrid->attach(*mMLabels, 0, 0, 1, 1); + mMLabels = Gtk::manage (new Gtk::Label ("---")); + setExpandAlignProperties (mMLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + mMLabels->set_tooltip_markup (M ("TP_RETINEX_MLABEL_TOOLTIP")); + settingsGrid->attach (*mMLabels, 0, 0, 1, 1); mMLabels->show (); - transLabels = Gtk::manage(new Gtk::Label("---")); - setExpandAlignProperties(transLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); - transLabels->set_tooltip_markup (M("TP_RETINEX_TLABEL_TOOLTIP")); - settingsGrid->attach(*transLabels, 0, 1, 1, 1); + transLabels = Gtk::manage (new Gtk::Label ("---")); + setExpandAlignProperties (transLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + transLabels->set_tooltip_markup (M ("TP_RETINEX_TLABEL_TOOLTIP")); + settingsGrid->attach (*transLabels, 0, 1, 1, 1); transLabels->show (); - transLabels2 = Gtk::manage(new Gtk::Label("---")); - setExpandAlignProperties(transLabels2, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); - settingsGrid->attach(*transLabels2, 0, 2, 1, 1); + transLabels2 = Gtk::manage (new Gtk::Label ("---")); + setExpandAlignProperties (transLabels2, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + settingsGrid->attach (*transLabels2, 0, 2, 1, 1); transLabels2->show (); // EQUALIZER Frame ---------------------------------------------------------------- - equalFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_EQUAL"))); - setExpandAlignProperties(equalFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + equalFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_EQUAL"))); + setExpandAlignProperties (equalFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 - equalFrame->set_border_width(5); + equalFrame->set_border_width (5); #endif //GTK318 Gtk::Grid *equalGrid = Gtk::manage (new Gtk::Grid()); - setExpandAlignProperties(equalGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (equalGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); // Histogram equalizer Lab curve - curveEditorGD = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_LAB")); - setExpandAlignProperties(curveEditorGD, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + curveEditorGD = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_CONTEDIT_LAB")); + setExpandAlignProperties (curveEditorGD, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); curveEditorGD->setCurveListener (this); std::vector milestones22; - milestones22.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones22.push_back( GradientMilestone(1., 1., 1., 1.) ); - cdshape = static_cast(curveEditorGD->addCurve(CT_Diagonal, M("TP_RETINEX_CURVEEDITOR_CD"))); - cdshape->setTooltip(M("TP_RETINEX_CURVEEDITOR_CD_TOOLTIP")); - cdshape->setBottomBarBgGradient(milestones22); - cdshape->setLeftBarBgGradient(milestones22); + milestones22.push_back ( GradientMilestone (0., 0., 0., 0.) ); + milestones22.push_back ( GradientMilestone (1., 1., 1., 1.) ); + cdshape = static_cast (curveEditorGD->addCurve (CT_Diagonal, M ("TP_RETINEX_CURVEEDITOR_CD"))); + cdshape->setTooltip (M ("TP_RETINEX_CURVEEDITOR_CD_TOOLTIP")); + cdshape->setBottomBarBgGradient (milestones22); + cdshape->setLeftBarBgGradient (milestones22); curveEditorGD->curveListComplete(); - equalGrid->attach(*curveEditorGD, 0, 0, 1, 1); + equalGrid->attach (*curveEditorGD, 0, 0, 1, 1); curveEditorGD->show(); // Histogram equalizer HSL curve - curveEditorGDH = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_HSL")); - setExpandAlignProperties(curveEditorGDH, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + curveEditorGDH = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_CONTEDIT_HSL")); + setExpandAlignProperties (curveEditorGDH, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); curveEditorGDH->setCurveListener (this); std::vector milestones22H; - milestones22H.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones22H.push_back( GradientMilestone(1., 1., 1., 1.) ); - cdshapeH = static_cast(curveEditorGDH->addCurve(CT_Diagonal, M("TP_RETINEX_CURVEEDITOR_CD"))); - cdshapeH->setTooltip(M("TP_RETINEX_CURVEEDITOR_CD_TOOLTIP")); - cdshapeH->setBottomBarBgGradient(milestones22H); - cdshapeH->setLeftBarBgGradient(milestones22H); + milestones22H.push_back ( GradientMilestone (0., 0., 0., 0.) ); + milestones22H.push_back ( GradientMilestone (1., 1., 1., 1.) ); + cdshapeH = static_cast (curveEditorGDH->addCurve (CT_Diagonal, M ("TP_RETINEX_CURVEEDITOR_CD"))); + cdshapeH->setTooltip (M ("TP_RETINEX_CURVEEDITOR_CD_TOOLTIP")); + cdshapeH->setBottomBarBgGradient (milestones22H); + cdshapeH->setLeftBarBgGradient (milestones22H); curveEditorGDH->curveListComplete(); - equalGrid->attach(*curveEditorGDH, 0, 1, 1, 1); + equalGrid->attach (*curveEditorGDH, 0, 1, 1, 1); curveEditorGDH->show(); // Hue equalizer - curveEditorGH = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_LH")); - setExpandAlignProperties(curveEditorGH, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + curveEditorGH = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_CONTEDIT_LH")); + setExpandAlignProperties (curveEditorGH, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); curveEditorGH->setCurveListener (this); - lhshape = static_cast(curveEditorGH->addCurve(CT_Flat, M("TP_RETINEX_CURVEEDITOR_LH"))); - lhshape->setTooltip(M("TP_RETINEX_CURVEEDITOR_LH_TOOLTIP")); - lhshape->setCurveColorProvider(this, 4); + lhshape = static_cast (curveEditorGH->addCurve (CT_Flat, M ("TP_RETINEX_CURVEEDITOR_LH"))); + lhshape->setTooltip (M ("TP_RETINEX_CURVEEDITOR_LH_TOOLTIP")); + lhshape->setCurveColorProvider (this, 4); milestones.clear(); + for (int i = 0; i < 7; i++) { float R, G, B; - float x = float(i) * (1.0f / 6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + float x = float (i) * (1.0f / 6.0); + Color::hsv2rgb01 (x, 0.5f, 0.5f, R, G, B); + milestones.push_back ( GradientMilestone (double (x), double (R), double (G), double (B)) ); } - lhshape->setBottomBarBgGradient(milestones); + + lhshape->setBottomBarBgGradient (milestones); curveEditorGH->curveListComplete(); - equalGrid->attach(*curveEditorGH, 0, 2, 1, 1); + equalGrid->attach (*curveEditorGH, 0, 2, 1, 1); curveEditorGH->show(); // Gamma settings gamgrid = Gtk::manage (new Gtk::Grid ()); - setExpandAlignProperties(gamgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (gamgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - labgam = Gtk::manage (new Gtk::Label (M("TP_RETINEX_GAMMA") + ":")); - setExpandAlignProperties(labgam, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - gamgrid->attach(*labgam, 0, 0, 1, 1); + labgam = Gtk::manage (new Gtk::Label (M ("TP_RETINEX_GAMMA") + ":")); + setExpandAlignProperties (labgam, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + gamgrid->attach (*labgam, 0, 0, 1, 1); gammaretinex = Gtk::manage (new MyComboBoxText ()); - setExpandAlignProperties(gammaretinex, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - gammaretinex->append (M("TP_RETINEX_GAMMA_NONE")); - gammaretinex->append (M("TP_RETINEX_GAMMA_LOW")); - gammaretinex->append (M("TP_RETINEX_GAMMA_MID")); - gammaretinex->append (M("TP_RETINEX_GAMMA_HIGH")); - gammaretinex->append (M("TP_RETINEX_GAMMA_FREE")); - gammaretinex->set_active(0); - gammaretinexConn = gammaretinex->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::gammaretinexChanged) ); - gammaretinex->set_tooltip_markup (M("TP_RETINEX_GAMMA_TOOLTIP")); - gamgrid->attach(*gammaretinex, 1, 0, 1, 1); - equalGrid->attach(*gamgrid, 0, 3, 1, 1); + setExpandAlignProperties (gammaretinex, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + gammaretinex->append (M ("TP_RETINEX_GAMMA_NONE")); + gammaretinex->append (M ("TP_RETINEX_GAMMA_LOW")); + gammaretinex->append (M ("TP_RETINEX_GAMMA_MID")); + gammaretinex->append (M ("TP_RETINEX_GAMMA_HIGH")); + gammaretinex->append (M ("TP_RETINEX_GAMMA_FREE")); + gammaretinex->set_active (0); + gammaretinexConn = gammaretinex->signal_changed().connect ( sigc::mem_fun (*this, &Retinex::gammaretinexChanged) ); + gammaretinex->set_tooltip_markup (M ("TP_RETINEX_GAMMA_TOOLTIP")); + gamgrid->attach (*gammaretinex, 1, 0, 1, 1); + equalGrid->attach (*gamgrid, 0, 3, 1, 1); gammaretinex->show(); - gam = Gtk::manage (new Adjuster (M("TP_RETINEX_FREEGAMMA"), 0.6, 3.0, 0.01, 1.30)); - setExpandAlignProperties(gam, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - equalGrid->attach(*gam, 0, 4, 1, 1); + gam = Gtk::manage (new Adjuster (M ("TP_RETINEX_FREEGAMMA"), 0.6, 3.0, 0.01, 1.30)); + setExpandAlignProperties (gam, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + equalGrid->attach (*gam, 0, 4, 1, 1); gam->show (); - slope = Gtk::manage (new Adjuster (M("TP_RETINEX_SLOPE"), 1., 20., 0.1, 3.)); - setExpandAlignProperties(slope, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - equalGrid->attach(*slope, 0, 5, 1, 1); + slope = Gtk::manage (new Adjuster (M ("TP_RETINEX_SLOPE"), 1., 20., 0.1, 3.)); + setExpandAlignProperties (slope, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + equalGrid->attach (*slope, 0, 5, 1, 1); slope->show (); //------------- - equalFrame->add(*equalGrid); - settingsGrid->attach(*equalFrame, 0, 3, 1, 1); + equalFrame->add (*equalGrid); + settingsGrid->attach (*equalFrame, 0, 3, 1, 1); // TONE MAPPING Frame ------------------------------------------------------------- - iterFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_ITERF"))); - setExpandAlignProperties(iterFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + iterFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_ITERF"))); + setExpandAlignProperties (iterFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 - iterFrame->set_border_width(5); + iterFrame->set_border_width (5); #endif //GTK318 Gtk::Grid *iterGrid = Gtk::manage (new Gtk::Grid()); - setExpandAlignProperties(iterGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (iterGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - iter = Gtk::manage (new Adjuster (M("TP_RETINEX_ITER"), 1, 5., 1., 1.)); - setExpandAlignProperties(iter, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - iter->set_tooltip_markup (M("TP_RETINEX_ITER_TOOLTIP")); - iterGrid->attach(*iter, 0, 0, 1, 1); + iter = Gtk::manage (new Adjuster (M ("TP_RETINEX_ITER"), 1, 5., 1., 1.)); + setExpandAlignProperties (iter, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + iter->set_tooltip_markup (M ("TP_RETINEX_ITER_TOOLTIP")); + iterGrid->attach (*iter, 0, 0, 1, 1); iter->show (); - scal = Gtk::manage (new Adjuster (M("TP_RETINEX_SCALES"), -1, 6., 1., 3.)); - setExpandAlignProperties(scal, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - scal->set_tooltip_markup (M("TP_RETINEX_SCALES_TOOLTIP")); - iterGrid->attach(*scal, 0, 1, 1, 1); + scal = Gtk::manage (new Adjuster (M ("TP_RETINEX_SCALES"), -1, 6., 1., 3.)); + setExpandAlignProperties (scal, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + scal->set_tooltip_markup (M ("TP_RETINEX_SCALES_TOOLTIP")); + iterGrid->attach (*scal, 0, 1, 1, 1); scal->show (); - grad = Gtk::manage (new Adjuster (M("TP_RETINEX_GRAD"), -2., 2., 1., 1.)); - setExpandAlignProperties(grad, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - grad->set_tooltip_markup (M("TP_RETINEX_GRAD_TOOLTIP")); - iterGrid->attach(*grad, 0, 2, 1, 1); + grad = Gtk::manage (new Adjuster (M ("TP_RETINEX_GRAD"), -2., 2., 1., 1.)); + setExpandAlignProperties (grad, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + grad->set_tooltip_markup (M ("TP_RETINEX_GRAD_TOOLTIP")); + iterGrid->attach (*grad, 0, 2, 1, 1); grad->show (); - grads = Gtk::manage (new Adjuster (M("TP_RETINEX_GRADS"), -2., 2., 1., 1.)); - setExpandAlignProperties(grads, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - grads->set_tooltip_markup (M("TP_RETINEX_GRADS_TOOLTIP")); - iterGrid->attach(*grads, 0, 3, 1, 1); + grads = Gtk::manage (new Adjuster (M ("TP_RETINEX_GRADS"), -2., 2., 1., 1.)); + setExpandAlignProperties (grads, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + grads->set_tooltip_markup (M ("TP_RETINEX_GRADS_TOOLTIP")); + iterGrid->attach (*grads, 0, 3, 1, 1); grads->show (); //------------- - iterFrame->add(*iterGrid); - settingsGrid->attach(*iterFrame, 0, 4, 1, 1); + iterFrame->add (*iterGrid); + settingsGrid->attach (*iterFrame, 0, 4, 1, 1); // TRANSMISSION Frame ------------------------------------------------------------- - tranFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_TRANF"))); - setExpandAlignProperties(tranFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + tranFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_TRANF"))); + setExpandAlignProperties (tranFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 - tranFrame->set_border_width(5); + tranFrame->set_border_width (5); #endif //GTK318 Gtk::Grid *tranGrid = Gtk::manage (new Gtk::Grid()); - setExpandAlignProperties(tranGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (tranGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); // Transmission map curve - transmissionCurveEditorG = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_TRANSMISSION")); - setExpandAlignProperties(transmissionCurveEditorG, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + transmissionCurveEditorG = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_TRANSMISSION")); + setExpandAlignProperties (transmissionCurveEditorG, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); transmissionCurveEditorG->setCurveListener (this); - rtengine::RetinexParams::getDefaulttransmissionCurve(defaultCurve); - transmissionShape = static_cast(transmissionCurveEditorG->addCurve(CT_Flat, "", nullptr, false, false)); - transmissionShape->setIdentityValue(0.); - transmissionShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - transmissionShape->setBottomBarBgGradient(milestones); + rtengine::RetinexParams::getDefaulttransmissionCurve (defaultCurve); + transmissionShape = static_cast (transmissionCurveEditorG->addCurve (CT_Flat, "", nullptr, false, false)); + transmissionShape->setIdentityValue (0.); + transmissionShape->setResetCurve (FlatCurveType (defaultCurve.at (0)), defaultCurve); + // transmissionShape->setBottomBarBgGradient(milestones); transmissionCurveEditorG->curveListComplete(); - transmissionCurveEditorG->set_tooltip_markup (M("TP_RETINEX_TRANSMISSION_TOOLTIP")); - tranGrid->attach( *transmissionCurveEditorG, 0, 0, 1, 1); + transmissionCurveEditorG->set_tooltip_markup (M ("TP_RETINEX_TRANSMISSION_TOOLTIP")); + tranGrid->attach ( *transmissionCurveEditorG, 0, 0, 1, 1); transmissionCurveEditorG->show(); // Scale - skal = Gtk::manage (new Adjuster (M("TP_RETINEX_SKAL"), 1, 8, 1, 3)); - setExpandAlignProperties(skal, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - tranGrid->attach(*skal, 0, 1, 1, 1); + skal = Gtk::manage (new Adjuster (M ("TP_RETINEX_SKAL"), 1, 8, 1, 3)); + setExpandAlignProperties (skal, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + tranGrid->attach (*skal, 0, 1, 1, 1); skal->show (); // Threshold - limd = Gtk::manage (new Adjuster (M("TP_RETINEX_THRESHOLD"), 2, 100, 1, 8)); - setExpandAlignProperties(limd, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - limd->set_tooltip_markup (M("TP_RETINEX_THRESHOLD_TOOLTIP")); - tranGrid->attach(*limd, 0, 2, 1, 1); + limd = Gtk::manage (new Adjuster (M ("TP_RETINEX_THRESHOLD"), 2, 100, 1, 8)); + setExpandAlignProperties (limd, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + limd->set_tooltip_markup (M ("TP_RETINEX_THRESHOLD_TOOLTIP")); + tranGrid->attach (*limd, 0, 2, 1, 1); limd->show (); // Transmission median filter - medianmap = Gtk::manage (new Gtk::CheckButton (M("TP_RETINEX_MEDIAN"))); - setExpandAlignProperties(medianmap, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + medianmap = Gtk::manage (new Gtk::CheckButton (M ("TP_RETINEX_MEDIAN"))); + setExpandAlignProperties (medianmap, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); medianmap->set_active (true); - medianmapConn = medianmap->signal_toggled().connect( sigc::mem_fun(*this, &Retinex::medianmapChanged) ); - tranGrid->attach(*medianmap, 0, 3, 1, 1); + medianmapConn = medianmap->signal_toggled().connect ( sigc::mem_fun (*this, &Retinex::medianmapChanged) ); + tranGrid->attach (*medianmap, 0, 3, 1, 1); medianmap->show (); //------------- - tranFrame->add(*tranGrid); - settingsGrid->attach(*tranFrame, 0, 5, 1, 1); + tranFrame->add (*tranGrid); + settingsGrid->attach (*tranFrame, 0, 5, 1, 1); // GAIN AND OFFSET Frame ---------------------------------------------------------- - gainFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_GAINOFFS"))); - setExpandAlignProperties(gainFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + gainFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_GAINOFFS"))); + setExpandAlignProperties (gainFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 - gainFrame->set_border_width(5); + gainFrame->set_border_width (5); #endif //GTK318 Gtk::Grid *gainGrid = Gtk::manage (new Gtk::Grid()); - setExpandAlignProperties(gainGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties (gainGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); // Gain Transmission map curve - gaintransmissionCurve = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_GAINTRANSMISSION")); - setExpandAlignProperties(gaintransmissionCurve, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + gaintransmissionCurve = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_GAINTRANSMISSION")); + setExpandAlignProperties (gaintransmissionCurve, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); gaintransmissionCurve->setCurveListener (this); - rtengine::RetinexParams::getDefaultgaintransmissionCurve(defaultCurve); - gaintransmissionShape = static_cast(gaintransmissionCurve->addCurve(CT_Flat, "", nullptr, false, false)); - gaintransmissionShape->setIdentityValue(0.); - gaintransmissionShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - gaintransmissionShape->setBottomBarBgGradient(milestones); - gaintransmissionCurve->set_tooltip_markup (M("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); + rtengine::RetinexParams::getDefaultgaintransmissionCurve (defaultCurve); + gaintransmissionShape = static_cast (gaintransmissionCurve->addCurve (CT_Flat, "", nullptr, false, false)); + gaintransmissionShape->setIdentityValue (0.); + gaintransmissionShape->setResetCurve (FlatCurveType (defaultCurve.at (0)), defaultCurve); + //gaintransmissionShape->setBottomBarBgGradient(milestones); + gaintransmissionCurve->set_tooltip_markup (M ("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); gaintransmissionCurve->curveListComplete(); - gainGrid->attach( *gaintransmissionCurve, 0, 0, 1, 1); + gainGrid->attach ( *gaintransmissionCurve, 0, 0, 1, 1); gaintransmissionCurve->show(); - gain = Gtk::manage (new Adjuster (M("TP_RETINEX_GAIN"), 20, 200, 1, 50)); // Unused !? - setExpandAlignProperties(gain, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - gain->set_tooltip_markup (M("TP_RETINEX_GAIN_TOOLTIP")); + gain = Gtk::manage (new Adjuster (M ("TP_RETINEX_GAIN"), 20, 200, 1, 50)); // Unused !? + setExpandAlignProperties (gain, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + gain->set_tooltip_markup (M ("TP_RETINEX_GAIN_TOOLTIP")); - offs = Gtk::manage (new Adjuster (M("TP_RETINEX_OFFSET"), -1000, 5000, 1, 0)); - setExpandAlignProperties(offs, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - gainGrid->attach(*offs, 0, 1, 1, 1); + offs = Gtk::manage (new Adjuster (M ("TP_RETINEX_OFFSET"), -1000, 5000, 1, 0)); + setExpandAlignProperties (offs, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + gainGrid->attach (*offs, 0, 1, 1, 1); offs->show (); //------------- - gainFrame->add(*gainGrid); - settingsGrid->attach(*gainFrame, 0, 6, 1, 1); + gainFrame->add (*gainGrid); + settingsGrid->attach (*gainFrame, 0, 6, 1, 1); - baselog = Gtk::manage (new Adjuster (M("TP_RETINEX_BASELOG"), 1., 10., 1., 3.)); // Unused !? - setExpandAlignProperties(baselog, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - baselog->set_tooltip_markup (M("TP_RETINEX_BASELOG_TOOLTIP")); + baselog = Gtk::manage (new Adjuster (M ("TP_RETINEX_BASELOG"), 1., 10., 1., 3.)); // Unused !? + setExpandAlignProperties (baselog, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + baselog->set_tooltip_markup (M ("TP_RETINEX_BASELOG_TOOLTIP")); // settingsGrid->attach(*baselog, 0, 7, 1, 1); // baselog->show (); //-------------------------- - expsettings->add(*settingsGrid); - expsettings->setLevel(2); + expsettings->add (*settingsGrid); + expsettings->setLevel (2); pack_start (*expsettings); @@ -486,13 +488,13 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), // Reset button - neutral = Gtk::manage (new Gtk::Button (M("TP_RETINEX_NEUTRAL"))); - setExpandAlignProperties(neutral, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + neutral = Gtk::manage (new Gtk::Button (M ("TP_RETINEX_NEUTRAL"))); + setExpandAlignProperties (neutral, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); - setExpandAlignProperties(resetImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); - neutral->set_image(*resetImg); - neutral->set_tooltip_text (M("TP_RETINEX_NEUTRAL_TIP")); - neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &Retinex::neutral_pressed) ); + setExpandAlignProperties (resetImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + neutral->set_image (*resetImg); + neutral->set_tooltip_text (M ("TP_RETINEX_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect ( sigc::mem_fun (*this, &Retinex::neutral_pressed) ); neutral->show(); //------------- @@ -646,30 +648,30 @@ Retinex::~Retinex() } void Retinex::neutral_pressed () { - neigh->resetValue(false); - gain->resetValue(false); - offs->resetValue(false); - str->resetValue(false); - scal->resetValue(false); - iter->resetValue(false); - grad->resetValue(false); - grads->resetValue(false); - vart->resetValue(false); - limd->resetValue(false); - highl->resetValue(false); - baselog->resetValue(false); - gam->resetValue(false); - slope->resetValue(false); - highlights->resetValue(false); - h_tonalwidth->resetValue(false); - shadows->resetValue(false); - s_tonalwidth->resetValue(false); - radius->resetValue(false); - mapMethod->set_active(0); - viewMethod->set_active(0); - retinexMethod->set_active(2); - retinexcolorspace->set_active(0); - gammaretinex->set_active(0); + neigh->resetValue (false); + gain->resetValue (false); + offs->resetValue (false); + str->resetValue (false); + scal->resetValue (false); + iter->resetValue (false); + grad->resetValue (false); + grads->resetValue (false); + vart->resetValue (false); + limd->resetValue (false); + highl->resetValue (false); + baselog->resetValue (false); + gam->resetValue (false); + slope->resetValue (false); + highlights->resetValue (false); + h_tonalwidth->resetValue (false); + shadows->resetValue (false); + s_tonalwidth->resetValue (false); + radius->resetValue (false); + mapMethod->set_active (0); + viewMethod->set_active (0); + retinexMethod->set_active (2); + retinexcolorspace->set_active (0); + gammaretinex->set_active (0); transmissionShape->reset(); gaintransmissionShape->reset(); cdshape->reset(); @@ -681,19 +683,19 @@ void Retinex::neutral_pressed () void Retinex::foldAllButMe (GdkEventButton* event, MyExpander *expander) { if (event->button == 3) { - expsettings->set_expanded(expsettings == expander); + expsettings->set_expanded (expsettings == expander); } } -void Retinex::writeOptions(std::vector &tpOpen) +void Retinex::writeOptions (std::vector &tpOpen) { tpOpen.push_back (expsettings->get_expanded ()); } -void Retinex::updateToolState(std::vector &tpOpen) +void Retinex::updateToolState (std::vector &tpOpen) { - if(tpOpen.size() == 10) { - expsettings->set_expanded(tpOpen.at(9)); + if (tpOpen.size() == 10) { + expsettings->set_expanded (tpOpen.at (9)); } } @@ -708,14 +710,14 @@ void Retinex::minmaxChanged (double cdma, double cdmin, double mini, double maxi nextminT = Tmin; nextmaxT = Tmax; - const auto func = [](gpointer data) -> gboolean { + const auto func = [] (gpointer data) -> gboolean { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - static_cast(data)->minmaxComputed_(); + static_cast (data)->minmaxComputed_(); return FALSE; }; - idle_register.add(func, this); + idle_register.add (func, this); } bool Retinex::minmaxComputed_ () @@ -735,10 +737,10 @@ void Retinex::updateLabel () nX = nextmin; nY = nextmax; { - mMLabels->set_text( - Glib::ustring::compose(M("TP_RETINEX_MLABEL"), - Glib::ustring::format(std::fixed, std::setprecision(0), nX), - Glib::ustring::format(std::fixed, std::setprecision(0), nY)) + mMLabels->set_text ( + Glib::ustring::compose (M ("TP_RETINEX_MLABEL"), + Glib::ustring::format (std::fixed, std::setprecision (0), nX), + Glib::ustring::format (std::fixed, std::setprecision (0), nY)) ); } } @@ -755,17 +757,17 @@ void Retinex::updateTrans () nB = nextmaxT; nS = nextsigma; { - transLabels->set_text( - Glib::ustring::compose(M("TP_RETINEX_TLABEL"), - Glib::ustring::format(std::fixed, std::setprecision(1), nm), - Glib::ustring::format(std::fixed, std::setprecision(1), nM), - Glib::ustring::format(std::fixed, std::setprecision(1), nZ), - Glib::ustring::format(std::fixed, std::setprecision(1), nS)) + transLabels->set_text ( + Glib::ustring::compose (M ("TP_RETINEX_TLABEL"), + Glib::ustring::format (std::fixed, std::setprecision (1), nm), + Glib::ustring::format (std::fixed, std::setprecision (1), nM), + Glib::ustring::format (std::fixed, std::setprecision (1), nZ), + Glib::ustring::format (std::fixed, std::setprecision (1), nS)) ); - transLabels2->set_text( - Glib::ustring::compose(M("TP_RETINEX_TLABEL2"), - Glib::ustring::format(std::fixed, std::setprecision(1), nA), - Glib::ustring::format(std::fixed, std::setprecision(1), nB)) + transLabels2->set_text ( + Glib::ustring::compose (M ("TP_RETINEX_TLABEL2"), + Glib::ustring::format (std::fixed, std::setprecision (1), nA), + Glib::ustring::format (std::fixed, std::setprecision (1), nB)) ); @@ -778,11 +780,11 @@ void Retinex::updateTrans () void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); - retinexMethodConn.block(true); - retinexColorSpaceConn.block(true); - gammaretinexConn.block(true); - mapMethodConn.block(true); - viewMethodConn.block(true); + retinexMethodConn.block (true); + retinexColorSpaceConn.block (true); + gammaretinexConn.block (true); + mapMethodConn.block (true); + viewMethodConn.block (true); if (pedited) { @@ -810,23 +812,23 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) if (!pedited->retinex.retinexMethod) { - retinexMethod->set_active_text(M("GENERAL_UNCHANGED")); + retinexMethod->set_active_text (M ("GENERAL_UNCHANGED")); } if (!pedited->retinex.mapMethod) { - mapMethod->set_active_text(M("GENERAL_UNCHANGED")); + mapMethod->set_active_text (M ("GENERAL_UNCHANGED")); } if (!pedited->retinex.viewMethod) { - viewMethod->set_active_text(M("GENERAL_UNCHANGED")); + viewMethod->set_active_text (M ("GENERAL_UNCHANGED")); } if (!pedited->retinex.retinexcolorspace) { - retinexcolorspace->set_active_text(M("GENERAL_UNCHANGED")); + retinexcolorspace->set_active_text (M ("GENERAL_UNCHANGED")); } if (!pedited->retinex.gammaretinex) { - gammaretinex->set_active_text(M("GENERAL_UNCHANGED")); + gammaretinex->set_active_text (M ("GENERAL_UNCHANGED")); } cdshape->setUnChanged (!pedited->retinex.cdcurve); @@ -862,14 +864,14 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) skal->setValue (pp->retinex.skal); if (!batchMode) { - if(pp->retinex.iter == 1) { - grad->set_sensitive(false); - scal->set_sensitive(false); - grads->set_sensitive(false); + if (pp->retinex.iter == 1) { + grad->set_sensitive (false); + scal->set_sensitive (false); + grads->set_sensitive (false); } else { - grad->set_sensitive(true); - scal->set_sensitive(true); - grads->set_sensitive(true); + grad->set_sensitive (true); + scal->set_sensitive (true); + grads->set_sensitive (true); } } @@ -941,20 +943,20 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) mapMethodChanged (); viewMethodChanged (); - medianmapConn.block(true); + medianmapConn.block (true); medianmapChanged (); - medianmapConn.block(false); + medianmapConn.block (false); cdshape->setCurve (pp->retinex.cdcurve); cdshapeH->setCurve (pp->retinex.cdHcurve); lhshape->setCurve (pp->retinex.lhcurve); mapshape->setCurve (pp->retinex.mapcurve); - retinexMethodConn.block(false); - retinexColorSpaceConn.block(false); - gammaretinexConn.block(false); - mapMethodConn.block(false); - viewMethodConn.block(false); + retinexMethodConn.block (false); + retinexColorSpaceConn.block (false); + gammaretinexConn.block (false); + mapMethodConn.block (false); + viewMethodConn.block (false); transmissionShape->setCurve (pp->retinex.transmissionCurve); gaintransmissionShape->setCurve (pp->retinex.gaintransmissionCurve); @@ -998,11 +1000,11 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pp->retinex.stonalwidth = (int)s_tonalwidth->getValue (); if (pedited) { - pedited->retinex.retinexMethod = retinexMethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->retinex.retinexcolorspace = retinexcolorspace->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->retinex.gammaretinex = gammaretinex->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->retinex.mapMethod = mapMethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->retinex.viewMethod = viewMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->retinex.retinexMethod = retinexMethod->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->retinex.retinexcolorspace = retinexcolorspace->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->retinex.gammaretinex = gammaretinex->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->retinex.mapMethod = mapMethod->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->retinex.viewMethod = viewMethod->get_active_text() != M ("GENERAL_UNCHANGED"); //%%%%%%%%%%%%%%%%%%%%%% pedited->retinex.str = str->getEditedState (); @@ -1099,7 +1101,7 @@ void Retinex::retinexMethodChanged() { if (!batchMode) { - if(retinexMethod->get_active_row_number() == 3) { + if (retinexMethod->get_active_row_number() == 3) { highl->show(); } else { highl->hide(); @@ -1117,14 +1119,14 @@ void Retinex::mapMethodChanged() { if (!batchMode) { - if(mapMethod->get_active_row_number() == 1 /*|| mapMethod->get_active_row_number() == 2*/) { + if (mapMethod->get_active_row_number() == 1 /*|| mapMethod->get_active_row_number() == 2*/) { curveEditormap->show(); highlights->show(); h_tonalwidth->show(); shadows->show(); s_tonalwidth->show(); radius->show(); - } else if(mapMethod->get_active_row_number() == 2 || mapMethod->get_active_row_number() == 3) { + } else if (mapMethod->get_active_row_number() == 2 || mapMethod->get_active_row_number() == 3) { curveEditormap->show(); highlights->show(); h_tonalwidth->show(); @@ -1149,7 +1151,7 @@ void Retinex::mapMethodChanged() void Retinex::viewMethodChanged() { if (!batchMode) { - if(viewMethod->get_active_row_number() == 1 || viewMethod->get_active_row_number() == 2) { + if (viewMethod->get_active_row_number() == 1 || viewMethod->get_active_row_number() == 2) { //vart->hide(); gain->hide(); offs->hide(); @@ -1166,7 +1168,7 @@ void Retinex::viewMethodChanged() */ curveEditorGH->hide(); - } else if(viewMethod->get_active_row_number() == 3 || viewMethod->get_active_row_number() == 4) { + } else if (viewMethod->get_active_row_number() == 3 || viewMethod->get_active_row_number() == 4) { gain->hide(); offs->hide(); transmissionCurveEditorG->show(); @@ -1205,15 +1207,15 @@ void Retinex::ColorSpaceUpdateUI () if (!batchMode) { curveEditorGH->show(); - if(retinexcolorspace->get_active_row_number() == 0) { + if (retinexcolorspace->get_active_row_number() == 0) { curveEditorGD->show(); curveEditorGDH->hide(); baselog->show(); - } else if(retinexcolorspace->get_active_row_number() == 1) { + } else if (retinexcolorspace->get_active_row_number() == 1) { curveEditorGD->hide(); curveEditorGDH->show(); baselog->show(); - } else if(retinexcolorspace->get_active_row_number() == 2) { + } else if (retinexcolorspace->get_active_row_number() == 2) { curveEditorGD->hide(); curveEditorGDH->show(); baselog->hide(); @@ -1234,10 +1236,10 @@ void Retinex::retinexColorSpaceChanged() void Retinex::gammaretinexChanged() { if (!batchMode) { - if(gammaretinex->get_active_row_number() == 4) { + if (gammaretinex->get_active_row_number() == 4) { gam->show(); slope->show(); - } else /*if(gammaretinex->get_active_row_number() != 4)*/ { + } else { /*if(gammaretinex->get_active_row_number() != 4)*/ gam->hide(); slope->hide(); } @@ -1268,11 +1270,11 @@ void Retinex::medianmapChanged () if (listener) { if (medianmap->get_active()) { if (getEnabled()) { - listener->panelChanged (EvRetinexmedianmap, M("GENERAL_ENABLED")); + listener->panelChanged (EvRetinexmedianmap, M ("GENERAL_ENABLED")); } } else { if (getEnabled()) { - listener->panelChanged (EvRetinexmedianmap, M("GENERAL_DISABLED")); + listener->panelChanged (EvRetinexmedianmap, M ("GENERAL_DISABLED")); } } @@ -1356,29 +1358,29 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi void Retinex::setAdjusterBehavior (bool strAdd, bool neighAdd, bool limdAdd, bool gainAdd, bool offsAdd, bool vartAdd, bool gamAdd, bool slopeAdd) { - str->setAddMode(strAdd); - neigh->setAddMode(neighAdd); - limd->setAddMode(limdAdd); - gain->setAddMode(gainAdd); - offs->setAddMode(offsAdd); - vart->setAddMode(vartAdd); - gam->setAddMode(gamAdd); - slope->setAddMode(slopeAdd); + str->setAddMode (strAdd); + neigh->setAddMode (neighAdd); + limd->setAddMode (limdAdd); + gain->setAddMode (gainAdd); + offs->setAddMode (offsAdd); + vart->setAddMode (vartAdd); + gam->setAddMode (gamAdd); + slope->setAddMode (slopeAdd); } void Retinex::adjusterChanged (Adjuster* a, double newval) { - if (a==iter && !batchMode) { - if(iter->getIntValue() > 1) { - scal->set_sensitive(true); - grad->set_sensitive(true); - grads->set_sensitive(true); + if (a == iter && !batchMode) { + if (iter->getIntValue() > 1) { + scal->set_sensitive (true); + grad->set_sensitive (true); + grads->set_sensitive (true); } else { - scal->set_sensitive(false); - grad->set_sensitive(false); - grads->set_sensitive(false); + scal->set_sensitive (false); + grad->set_sensitive (false); + grads->set_sensitive (false); } } @@ -1450,17 +1452,17 @@ void Retinex::curveChanged (CurveEditor* ce) { if (listener && getEnabled()) { if (ce == cdshape) { - listener->panelChanged (EvLCDCurve, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvLCDCurve, M ("HISTORY_CUSTOMCURVE")); } else if (ce == cdshapeH) { - listener->panelChanged (EvLCDHCurve, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvLCDHCurve, M ("HISTORY_CUSTOMCURVE")); } else if (ce == transmissionShape) { - listener->panelChanged (EvRetinextransmission, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvRetinextransmission, M ("HISTORY_CUSTOMCURVE")); } else if (ce == gaintransmissionShape) { - listener->panelChanged (EvRetinexgaintransmission, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvRetinexgaintransmission, M ("HISTORY_CUSTOMCURVE")); } else if (ce == lhshape) { - listener->panelChanged (EvRetinexlhcurve, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvRetinexlhcurve, M ("HISTORY_CUSTOMCURVE")); } else if (ce == mapshape) { - listener->panelChanged (EvRetinexmapcurve, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvRetinexmapcurve, M ("HISTORY_CUSTOMCURVE")); } } } @@ -1470,11 +1472,11 @@ void Retinex::enabledChanged () if (listener) { if (get_inconsistent()) { - listener->panelChanged (EvRetinexEnabled, M("GENERAL_UNCHANGED")); + listener->panelChanged (EvRetinexEnabled, M ("GENERAL_UNCHANGED")); } else if (getEnabled()) { - listener->panelChanged (EvRetinexEnabled, M("GENERAL_ENABLED")); + listener->panelChanged (EvRetinexEnabled, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvRetinexEnabled, M("GENERAL_DISABLED")); + listener->panelChanged (EvRetinexEnabled, M ("GENERAL_DISABLED")); } } } @@ -1482,22 +1484,22 @@ void Retinex::enabledChanged () void Retinex::trimValues (rtengine::procparams::ProcParams* pp) { - str->trimValue(pp->retinex.str); - scal->trimValue(pp->retinex.scal); - iter->trimValue(pp->retinex.iter); - grad->trimValue(pp->retinex.grad); - grads->trimValue(pp->retinex.grads); - neigh->trimValue(pp->retinex.neigh); - gain->trimValue(pp->retinex.gain); - offs->trimValue(pp->retinex.offs); - vart->trimValue(pp->retinex.vart); - limd->trimValue(pp->retinex.limd); - highl->trimValue(pp->retinex.highl); - baselog->trimValue(pp->retinex.baselog); - gam->trimValue(pp->retinex.gam); - slope->trimValue(pp->retinex.slope); - highlights->trimValue(pp->retinex.highlights); - shadows->trimValue(pp->retinex.shadows); + str->trimValue (pp->retinex.str); + scal->trimValue (pp->retinex.scal); + iter->trimValue (pp->retinex.iter); + grad->trimValue (pp->retinex.grad); + grads->trimValue (pp->retinex.grads); + neigh->trimValue (pp->retinex.neigh); + gain->trimValue (pp->retinex.gain); + offs->trimValue (pp->retinex.offs); + vart->trimValue (pp->retinex.vart); + limd->trimValue (pp->retinex.limd); + highl->trimValue (pp->retinex.highl); + baselog->trimValue (pp->retinex.baselog); + gam->trimValue (pp->retinex.gam); + slope->trimValue (pp->retinex.slope); + highlights->trimValue (pp->retinex.highlights); + shadows->trimValue (pp->retinex.shadows); } @@ -1519,24 +1521,24 @@ void Retinex::colorForValue (double valX, double valY, enum ColorCaller::ElemTyp if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); + Color::hsv2rgb01 (float (valX), float (valY), 0.5f, R, G, B); } else if (callerId == 2) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; + float value = (1.f - 0.7f) * float (valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01 (float (valY), float (valX), value, R, G, B); } else if (callerId == 3) { // lc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; + float value = (1.f - 0.7f) * float (valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01 (float (valY), float (valX), value, R, G, B); } else if (callerId == 4) { // LH - bottom bar - Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); + Color::hsv2rgb01 (float (valX), 0.5f, float (valY), R, G, B); } else if (callerId == 5) { // HH - bottom bar - float h = float((valY - 0.5) * 0.3 + valX); + float h = float ((valY - 0.5) * 0.3 + valX); if (h > 1.0f) { h -= 1.0f; @@ -1544,12 +1546,12 @@ void Retinex::colorForValue (double valX, double valY, enum ColorCaller::ElemTyp h += 1.0f; } - Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + Color::hsv2rgb01 (h, 0.5f, 0.5f, R, G, B); } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + caller->ccRed = double (R); + caller->ccGreen = double (G); + caller->ccBlue = double (B); } diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index cd33f393d..54527a5d5 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -26,11 +26,12 @@ #include #include "../rtengine/imagedata.h" #include + +#include "../rtengine/dynamicprofile.h" #include "guiutils.h" -#include "profilestore.h" #include "batchqueue.h" #include "extprog.h" -#include "dynamicprofile.h" +#include "profilestorecombobox.h" using namespace rtengine::procparams; @@ -177,7 +178,7 @@ const ProcParams& Thumbnail::getProcParamsU () if (pparamsValid) { return pparams; } else { - pparams = *(profileStore.getDefaultProcParams (getType() == FT_Raw)); + pparams = *(ProfileStore::getInstance()->getDefaultProcParams (getType() == FT_Raw)); if (pparams.wb.method == "Camera") { double ct; @@ -231,7 +232,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } else { imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); } - PartialProfile *pp = loadDynamicProfile(imageMetaData); + PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData); int err = pp->pparams->save(outFName); pp->deleteInstance(); delete pp; @@ -239,7 +240,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu loadProcParams(); } } else if (create && defProf != DEFPROFILE_DYNAMIC) { - const PartialProfile *p = profileStore.getProfile(defProf); + const PartialProfile *p = ProfileStore::getInstance()->getProfile(defProf); if (p && !p->pparams->save(outFName)) { loadProcParams(); } @@ -315,7 +316,7 @@ void Thumbnail::loadProcParams () pparamsValid = false; pparams.setDefaults(); - const PartialProfile *defaultPP = profileStore.getDefaultPartialProfile(getType() == FT_Raw); + const PartialProfile *defaultPP = ProfileStore::getInstance()->getDefaultPartialProfile(getType() == FT_Raw); defaultPP->applyTo(&pparams); if (options.paramsLoadLocation == PLL_Input) {