diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index bd026e360..7362ad4c4 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -1,6 +1,3 @@ - - - !!!!!!!!!!!!!!!!!!!!!!!!! ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/rtdata/languages/default b/rtdata/languages/default index 220eb6711..bde5f2911 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -412,7 +412,8 @@ PREFERENCES_DIRLAST;Last visited directory PREFERENCES_DIROTHER;Other PREFERENCES_DIRSELECTDLG;Select Image Directory at Startup... PREFERENCES_DIRSOFTWARE;Installation directory -PREFERENCES_DMETHOD;Method +PREFERENCES_DMETHOD;Preview +PREFERENCES_DMETHODBATCH;Batch PREFERENCES_EDITORCMDLINE;Other command line PREFERENCES_EXTERNALEDITOR;External editor PREFERENCES_FALSECOLOR;False color suppression steps @@ -471,6 +472,10 @@ PREFERENCES_TAB_GENERAL;General PREFERENCES_TAB_IMPROC;Image Processing PREFERENCES_TAB_OUTPUT;Output Options PREFERENCES_THUMBSIZE;Thumbnail Size +PREFERENCES_WORKFLOW;Workflow +PREFERENCES_EDITORLAYOUT;Editor Layout +PREFERENCES_SINGLETAB;Single tab mode +PREFERENCES_MULTITAB;Multiple tabs mode PROFILEPANEL_FILEDLGFILTERANY;Any files PROFILEPANEL_FILEDLGFILTERPP;Postprocessing profiles PROFILEPANEL_LABEL;Postprocessing Profiles diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index aa64fe988..e046ff2f2 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -1,5 +1,6 @@ [General] +TabbedEditor=true StoreLastProfile=true StartupDirectory=last StartupPath= @@ -85,6 +86,7 @@ ToolPanelsExpanded=1;1;0;0;0;1;1;0;0;0;0;1;1;0;0;0;0;0; [Algorithms] DemosaicMethod=hphd +DemosaicMethodBatch=hphd ColorCorrection=1 [Crop Settings] diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index a7c5e6ec3..5d9d4f813 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -1,5 +1,6 @@ [General] +TabbedEditor=true StoreLastProfile=true StartupDirectory=last StartupPath= @@ -85,6 +86,7 @@ ToolPanelsExpanded=1;1;0;0;0;1;1;0;0;0;0;1;1;0;0;0;0;0; [Algorithms] DemosaicMethod=hphd +DemosaicMethodBatch=hphd ColorCorrection=1 [Crop Settings] diff --git a/rtdata/options/options.win b/rtdata/options/options.win index f589ba814..4c450f427 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -1,5 +1,6 @@ [General] +TabbedEditor=true StoreLastProfile=true StartupDirectory=last StartupPath= @@ -85,6 +86,7 @@ ToolPanelsExpanded=1;1;0;0;0;1;1;0;0;0;0;1;1;0;0;0;0;0; [Algorithms] DemosaicMethod=hphd +DemosaicMethodBatch=hphd ColorCorrection=1 [Crop Settings] diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 2e260c853..c38977729 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -65,7 +65,7 @@ class ImageSource : public InitialImage { ImageSource () : references (1), embProfile(NULL), idata(NULL) {} virtual ~ImageSource () {} - virtual int load (Glib::ustring fname) =0; + virtual int load (Glib::ustring fname, bool batch = false) =0; virtual void getImage (ColorTemp ctemp, int tran, Image16* image, PreviewProps pp, HRecParams hlp, ColorManagementParams cmp) {} virtual ColorTemp getWB () =0; virtual ColorTemp getAutoWB () =0; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index e361afec4..38b9d5b1d 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -20,6 +20,7 @@ #include #include #include +#include #define CLIPTO(a,b,c) ((a)>b?((a)getMutex().lock(); - ipf.lab2rgb (nprevl, previmg); + try + { + ipf.lab2rgb (nprevl, previmg); + } + catch(char * str) + { + progress ("Error converting file...",0); + mProcessing.unlock (); + return; + } previmg->getMutex().unlock(); } if (!resultValid) { @@ -566,7 +576,11 @@ void ImProcCoordinator::startProcessing () { thread = NULL; updaterRunning = true; updaterThreadStart.unlock (); - thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, false, true, Glib::THREAD_PRIORITY_NORMAL); + + batchThread->yield(); //the running batch should wait other threads to avoid conflict + + thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); + } else updaterThreadStart.unlock (); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 659d839a2..cf94f25e7 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -38,6 +38,9 @@ extern const Settings* settings; void ImProcFunctions::lab2rgb (LabImage* lab, Image8* image) { + if (chroma_scale == 0) + return; + if (monitorTransform) { int ix = 0; short* buffer = new short [3*lab->W]; diff --git a/rtengine/loadinitial.cc b/rtengine/loadinitial.cc index f12ce63b8..0bd524351 100644 --- a/rtengine/loadinitial.cc +++ b/rtengine/loadinitial.cc @@ -32,7 +32,11 @@ InitialImage* InitialImage::load (const Glib::ustring& fname, bool isRaw, int* e isrc = new RawImageSource (); isrc->setProgressListener (pl); - *errorCode = isrc->load (fname); + + if(isRaw && pl == NULL) + *errorCode = isrc->load (fname, true); + else + *errorCode = isrc->load (fname); if (*errorCode) { delete isrc; return NULL; diff --git a/rtengine/loadinitial.cc.orig b/rtengine/loadinitial.cc.orig new file mode 100644 index 000000000..455efdf4c --- /dev/null +++ b/rtengine/loadinitial.cc.orig @@ -0,0 +1,54 @@ +/* + * 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 +#include +#include + +namespace rtengine { + + Glib::Mutex* qMutex2 = NULL; +InitialImage* InitialImage::load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl) { + + if (!qMutex2) + qMutex2 = new Glib::Mutex (); + + qMutex2->lock(); + + ImageSource* isrc; + + if (!isRaw) + isrc = new StdImageSource (); + else + isrc = new RawImageSource (); + + isrc->setProgressListener (pl); + + if(isRaw && pl == NULL) + *errorCode = isrc->load (fname, true); + else + *errorCode = isrc->load (fname); + if (*errorCode) { + delete isrc; + return NULL; + } + qMutex2->unlock(); + return isrc; +} +} + diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 7b6be804d..1a2969042 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -724,7 +724,7 @@ void RawImageSource::inverse33 (double (*coeff)[3], double (*icoeff)[3]) { icoeff[2][2] = (coeff[0][1]*coeff[1][0]-coeff[0][0]*coeff[1][1]) / nom; } -int RawImageSource::load (Glib::ustring fname) { +int RawImageSource::load (Glib::ustring fname, bool batch) { fileName = fname; @@ -802,6 +802,7 @@ int RawImageSource::load (Glib::ustring fname) { // global correction int ng1=0, ng2=0; double avgg1=0, avgg2=0; +#pragma omp parallel for for (int i=border; idemosaicMethod=="hphd") - hphd_demosaic (); - else if (settings->demosaicMethod=="vng4") - vng4_demosaic (); - else if (settings->demosaicMethod=="ahd") + if(!batch) + { + if (settings->demosaicMethod=="hphd") + hphd_demosaic (); + else if (settings->demosaicMethod=="vng4") + vng4_demosaic (); + else if (settings->demosaicMethod=="ahd") //ahd_demosaic (); fast_demo (); - else if (settings->demosaicMethod=="bilinear") - bilinear_demosaic(); - //else if (settings->demosaicMethod=="ppg") - // ppg_demosaic (); - else if (settings->demosaicMethod=="amaze") - amaze_demosaic_RT ();//Emil's code for AMaZE - else if (settings->demosaicMethod=="dcb") - dcb_demosaic(settings->dcb_iterations, settings->dcb_enhance? 1:0); + else if (settings->demosaicMethod=="bilinear") + bilinear_demosaic(); + //else if (settings->demosaicMethod=="ppg") + // ppg_demosaic (); + else if (settings->demosaicMethod=="amaze") + amaze_demosaic_RT ();//Emil's code for AMaZE + else if (settings->demosaicMethod=="dcb") + dcb_demosaic(settings->dcb_iterations, settings->dcb_enhance? 1:0); + else + eahd_demosaic (); + } else - eahd_demosaic (); + { + if (settings->demosaicMethodBatch =="hphd") + hphd_demosaic (); + else if (settings->demosaicMethodBatch=="vng4") + vng4_demosaic (); + else if (settings->demosaicMethodBatch=="ahd") + fast_demo (); + else if (settings->demosaicMethodBatch=="bilinear") + bilinear_demosaic(); + //else if (settings->demosaicMethod=="ppg") + // ppg_demosaic (); + else if (settings->demosaicMethodBatch=="amaze") + amaze_demosaic_RT ();//Emil's code for AMaZE + else if (settings->demosaicMethodBatch=="dcb") + dcb_demosaic(settings->dcb_iterations, settings->dcb_enhance? 1:0); + else + eahd_demosaic (); + } //t2.set(); //printf("Demosaicing:%d usec\n",t2.etime(t1)); } @@ -1155,7 +1179,8 @@ void RawImageSource::colorSpaceConversion (Image16* im, ColorManagementParams cm for (int j=0; j<3; j++) for (int k=0; k<3; k++) mat[i][j] += camMatrix[i][k] * work[k][j]; - + +#pragma omp parallel for for (int i=0; iheight; i++) for (int j=0; jwidth; j++) { @@ -1177,7 +1202,8 @@ void RawImageSource::colorSpaceConversion (Image16* im, ColorManagementParams cm if (hTransform) { if (cmp.gammaOnInput) { double gd = pow (2.0, defgain); - defgain = 0.0; + defgain = 0.0; +#pragma omp parallel for for (int i=0; iheight; i++) for (int j=0; jwidth; j++) { im->r[i][j] = CurveFactory::gamma (CLIP(defgain*im->r[i][j])); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 0dd2bca47..d9f455b37 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -1,183 +1,183 @@ -/* - * 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 _RAWIMAGESOURCE_ -#define _RAWIMAGESOURCE_ - -#include -#include -#define HR_SCALE 2 - -namespace rtengine { - -template void freeArray (T** a, int H) { - for (int i=0; i T** allocArray (int W, int H) { - - T** t = new T*[H]; - for (int i=0; i void freeArray2 (T** a, int H) { - for (int i=0; i red, std::vector green, std::vector& blue, int tran); - - double getDefGain () { return defGain; } - double getGamma () { return 2.2; } - - void getFullSize (int& w, int& h, int tr = TR_NONE); - void getSize (int tran, PreviewProps pp, int& w, int& h); - - ImageData* getImageData () { return idata; } - void setProgressListener (ProgressListener* pl) { plistener = pl; } - int getAEHistogram (unsigned int* histogram, int& histcompr); - - static void colorSpaceConversion (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain); - static void inverse33 (double (*coeff)[3], double (*icoeff)[3]); - - static void HLRecovery_Luminance (unsigned short* rin, unsigned short* gin, unsigned short* bin, unsigned short* rout, unsigned short* gout, unsigned short* bout, int width, int maxval); - static void HLRecovery_CIELab (unsigned short* rin, unsigned short* gin, unsigned short* bin, unsigned short* rout, unsigned short* gout, unsigned short* bout, int width, int maxval, double cam[3][3], double icam[3][3]); - - protected: - typedef unsigned short ushort; - void correction_YIQ_LQ (Image16* i, int times); - inline void convert_row_to_YIQ (unsigned short* r, unsigned short* g, unsigned short* b, int* Y, int* I, int* Q, int W); - inline void convert_row_to_RGB (unsigned short* r, unsigned short* g, unsigned short* b, int* Y, int* I, int* Q, int W); - - inline void convert_to_cielab_row (unsigned short* ar, unsigned short* ag, unsigned short* ab, short* oL, short* oa, short* ob); - inline void interpolate_row_g (unsigned short* agh, unsigned short* agv, int i); - inline void interpolate_row_rb (unsigned short* ar, unsigned short* ab, unsigned short* pg, unsigned short* cg, unsigned short* ng, int i); - inline void interpolate_row_rb_mul_pp (unsigned short* ar, unsigned short* ab, unsigned short* pg, unsigned short* cg, unsigned short* ng, int i, double r_mul, double g_mul, double b_mul, int x1, int width, int skip); - - int LinEqSolve (int nDim, float* pfMatr, float* pfVect, float* pfSolution);//Emil's CA auto correction - void CA_correct_RT (); //Emil's pre-demosaic CA correction - - void cfa_clean (float thresh); //Emil's hot/dead pixel filter - void ddct8x8s(int isgn, float **a); - - void cfa_linedn (float linenoiselevel); //Emil's line denoise - - void green_equilibrate (float greenthresh);//Emil's green equilibration - - - void eahd_demosaic (); - void hphd_demosaic (); - void vng4_demosaic (); - void ppg_demosaic(); - void amaze_demosaic_RT (); //Emil's code for AMaZE - void fast_demo (); //Emil's fast demosaic - void dcb_demosaic(int iterations, int dcb_enhance); - void ahd_demosaic(); - void bilinear_demosaic(); - void bilinear_interpolate_block(ushort (*image)[4], int start, int end); - void border_interpolate(int border, ushort (*image)[4], int start = 0, int end = 0); - void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); - void fill_raw( ushort (*cache )[4], int x0, int y0, ushort** rawData); - void fill_border( ushort (*cache )[4], int border, int x0, int y0); - void copy_to_buffer(ushort (*image2)[3], ushort (*image)[4]); - void dcb_hid(ushort (*image)[4], ushort (*bufferH)[3], ushort (*bufferV)[3], int x0, int y0); - void dcb_color(ushort (*image)[4], int x0, int y0); - void dcb_hid2(ushort (*image)[4], int x0, int y0); - void dcb_map(ushort (*image)[4], int x0, int y0); - void dcb_correction(ushort (*image)[4], int x0, int y0); - void dcb_pp(ushort (*image)[4], int x0, int y0); - void dcb_correction2(ushort (*image)[4], int x0, int y0); - void restore_from_buffer(ushort (*image)[4], ushort (*image2)[3]); - void dcb_refinement(ushort (*image)[4], int x0, int y0); - void dcb_color_full(ushort (*image)[4], int x0, int y0, float (*chroma)[2]); - - void transLine (unsigned short* red, unsigned short* green, unsigned short* blue, int i, Image16* image, int tran, int imw, int imh, int fw); - void hflip (Image16* im); - void vflip (Image16* im); - -}; -}; -#endif +/* + * 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 _RAWIMAGESOURCE_ +#define _RAWIMAGESOURCE_ + +#include +#include +#define HR_SCALE 2 + +namespace rtengine { + +template void freeArray (T** a, int H) { + for (int i=0; i T** allocArray (int W, int H) { + + T** t = new T*[H]; + for (int i=0; i void freeArray2 (T** a, int H) { + for (int i=0; i red, std::vector green, std::vector& blue, int tran); + + double getDefGain () { return defGain; } + double getGamma () { return 2.2; } + + void getFullSize (int& w, int& h, int tr = TR_NONE); + void getSize (int tran, PreviewProps pp, int& w, int& h); + + ImageData* getImageData () { return idata; } + void setProgressListener (ProgressListener* pl) { plistener = pl; } + int getAEHistogram (unsigned int* histogram, int& histcompr); + + static void colorSpaceConversion (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain); + static void inverse33 (double (*coeff)[3], double (*icoeff)[3]); + + static void HLRecovery_Luminance (unsigned short* rin, unsigned short* gin, unsigned short* bin, unsigned short* rout, unsigned short* gout, unsigned short* bout, int width, int maxval); + static void HLRecovery_CIELab (unsigned short* rin, unsigned short* gin, unsigned short* bin, unsigned short* rout, unsigned short* gout, unsigned short* bout, int width, int maxval, double cam[3][3], double icam[3][3]); + + protected: + typedef unsigned short ushort; + void correction_YIQ_LQ (Image16* i, int times); + inline void convert_row_to_YIQ (unsigned short* r, unsigned short* g, unsigned short* b, int* Y, int* I, int* Q, int W); + inline void convert_row_to_RGB (unsigned short* r, unsigned short* g, unsigned short* b, int* Y, int* I, int* Q, int W); + + inline void convert_to_cielab_row (unsigned short* ar, unsigned short* ag, unsigned short* ab, short* oL, short* oa, short* ob); + inline void interpolate_row_g (unsigned short* agh, unsigned short* agv, int i); + inline void interpolate_row_rb (unsigned short* ar, unsigned short* ab, unsigned short* pg, unsigned short* cg, unsigned short* ng, int i); + inline void interpolate_row_rb_mul_pp (unsigned short* ar, unsigned short* ab, unsigned short* pg, unsigned short* cg, unsigned short* ng, int i, double r_mul, double g_mul, double b_mul, int x1, int width, int skip); + + int LinEqSolve (int nDim, float* pfMatr, float* pfVect, float* pfSolution);//Emil's CA auto correction + void CA_correct_RT (); + + void cfa_clean (float thresh);//Emil's hot/dead pixel filter + void ddct8x8s(int isgn, float **a); + + void cfa_linedn (float linenoiselevel);//Emil's line denoise + + void green_equilibrate (float greenthresh);//Emil's green equilibration + + + void eahd_demosaic (); + void hphd_demosaic (); + void vng4_demosaic (); + void ppg_demosaic(); + void amaze_demosaic_RT ();//Emil's code for AMaZE + void fast_demo (); + void dcb_demosaic(int iterations, int dcb_enhance); + void ahd_demosaic(); + void bilinear_demosaic(); + void bilinear_interpolate_block(ushort (*image)[4], int start, int end); + void border_interpolate(int border, ushort (*image)[4], int start = 0, int end = 0); + void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); + void fill_raw( ushort (*cache )[4], int x0, int y0, ushort** rawData); + void fill_border( ushort (*cache )[4], int border, int x0, int y0); + void copy_to_buffer(ushort (*image2)[3], ushort (*image)[4]); + void dcb_hid(ushort (*image)[4], ushort (*bufferH)[3], ushort (*bufferV)[3], int x0, int y0); + void dcb_color(ushort (*image)[4], int x0, int y0); + void dcb_hid2(ushort (*image)[4], int x0, int y0); + void dcb_map(ushort (*image)[4], int x0, int y0); + void dcb_correction(ushort (*image)[4], int x0, int y0); + void dcb_pp(ushort (*image)[4], int x0, int y0); + void dcb_correction2(ushort (*image)[4], int x0, int y0); + void restore_from_buffer(ushort (*image)[4], ushort (*image2)[3]); + void dcb_refinement(ushort (*image)[4], int x0, int y0); + void dcb_color_full(ushort (*image)[4], int x0, int y0, float (*chroma)[2]); + + void transLine (unsigned short* red, unsigned short* green, unsigned short* blue, int i, Image16* image, int tran, int imw, int imh, int fw); + void hflip (Image16* im); + void vflip (Image16* im); + +}; +}; +#endif diff --git a/rtengine/settings.h b/rtengine/settings.h index 6eca8c4da..a171ffeec 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -26,6 +26,7 @@ namespace rtengine { public: bool dualThreadEnabled; ///< If true, the image processing operations with utilize two processor cores (if possible) std::string demosaicMethod; ///< The algorithm used for demosaicing. Can be "eahd", "hphd", "ahd", "vng4", "amaze", "bilinear". + std::string demosaicMethodBatch; ///< The algorithm used for demosaicing. Can be "eahd", "hphd", "ahd", "vng4", "amaze", "bilinear". int colorCorrectionSteps; ///< The number of color correction steps applied right after the demosaicing Glib::ustring iccDirectory; ///< The directory containing the possible output icc profiles int colorimetricIntent; ///< Colorimetric intent used at color space conversions diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 6a65aac59..d9abb1082 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -29,6 +29,9 @@ #undef THREAD_PRIORITY_NORMAL +Glib::Thread *batchThread = NULL; +Glib::Mutex* qMutex = NULL; + namespace rtengine { IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) { @@ -213,6 +216,10 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) { + if (!qMutex) + qMutex = new Glib::Mutex (); + + qMutex->lock(); ProcessingJob* currentJob = job; while (currentJob) { @@ -222,12 +229,22 @@ void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) { bpl->error ("Can not load input image."); currentJob = bpl->imageReady (img); } + qMutex->unlock(); } void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) { + + if (bpl) - Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, false, true, Glib::THREAD_PRIORITY_NORMAL); + batchThread = Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW); + + if(qMutex) + { + delete qMutex; + qMutex = NULL; + } + } } diff --git a/rtengine/simpleprocess.h b/rtengine/simpleprocess.h new file mode 100644 index 000000000..fb5a24ff6 --- /dev/null +++ b/rtengine/simpleprocess.h @@ -0,0 +1,26 @@ +/* + * File: simpleprocess.h + * Author: askv + * + * Created on September 18, 2010, 8:31 PM + */ + +#ifndef SIMPLEPROCESS_H +#define SIMPLEPROCESS_H + +#ifdef __cplusplus +extern "C" { +#endif + + + + +#ifdef __cplusplus +} +#endif +namespace rtengine { + +extern Glib::Thread *batchThread; +} +#endif /* SIMPLEPROCESS_H */ + diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index e1bc98165..3ef593ead 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -70,7 +70,7 @@ StdImageSource::~StdImageSource () { freeArray(needhr, img->height); } -int StdImageSource::load (Glib::ustring fname) { +int StdImageSource::load (Glib::ustring fname, bool batch) { fileName = fname; diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 8565c5670..7442fda0b 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -43,7 +43,7 @@ class StdImageSource : public ImageSource { StdImageSource (); ~StdImageSource (); - int load (Glib::ustring fname); + int load (Glib::ustring fname, bool batch = false); void getImage (ColorTemp ctemp, int tran, Image16* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp); ColorTemp getWB () { return wb; } ColorTemp getAutoWB (); diff --git a/rtengine/updater.cc b/rtengine/updater.cc index 5a0b5a3b6..b0ff8f433 100644 --- a/rtengine/updater.cc +++ b/rtengine/updater.cc @@ -54,13 +54,13 @@ ProcParams* Updater::getParams () { void Updater::startProcessing () { - #undef THREAD_PRIORITY_NORMAL + #undef THREAD_PRIORITY_LOW tstart.lock (); if (ipc && !running) { running = true; tstart.unlock (); - Glib::Thread::create(sigc::mem_fun(*this, &Updater::process), 0, false, true, Glib::THREAD_PRIORITY_NORMAL); + Glib::Thread::create(sigc::mem_fun(*this, &Updater::process), 0, false, true, Glib::THREAD_PRIORITY_LOW); } else tstart.unlock (); diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index f98cab189..3ad75b669 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -57,9 +57,10 @@ void BatchQueueEntryUpdater::add (guint8* oimg, int ow, int oh, int newh, BQEntr void BatchQueueEntryUpdater::process () { - if (stopped) - #undef THREAD_PRIORITY_NORMAL - thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); + if (stopped){ + #undef THREAD_PRIORITY_LOW + thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); + } } void BatchQueueEntryUpdater::process_ () { @@ -93,7 +94,7 @@ void BatchQueueEntryUpdater::stop () { tostop = true; Glib::Thread::self()->yield(); if (!stopped) - thread->join (); + thread->join (); gdk_threads_enter(); } diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index b30474cec..d08bd4782 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -268,7 +268,7 @@ void CropHandler::update () { // crop->setWindow (cropX, cropY, cropW, cropH, zoom>=1000 ? 1 : zoom); --> we use the "getWindow" hook instead of setting the size before crop->setListener (this); cropPixbuf.clear (); - Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), 0, false, true, Glib::THREAD_PRIORITY_NORMAL); + Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), 0, false, true, Glib::THREAD_PRIORITY_LOW); } } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index 5a69154d1..59b7129fc 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -66,7 +66,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener { int xpos, ypos, width, height; // image handling - CropHandler cropHandler; + ImageArea* iarea; int cropZoom; // *1000 @@ -88,6 +88,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener { void getObservedFrameArea(int& x, int& y, int& w, int& h); public: + CropHandler cropHandler; CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_); ~CropWindow (); diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 4eba917f3..4ec439529 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1,968 +1,1014 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include - -using namespace rtengine::procparams; - -EditorPanel::EditorPanel () : beforePreviewHandler(NULL), beforeIarea(NULL), parent(NULL), beforeIpc(NULL) { - - epih = new EditorPanelIdleHelper; - epih->epanel = this; - epih->destroyed = false; - epih->pending = 0; - -// construct toolpanelcoordinator - tpc = new ToolPanelCoordinator (); - -// build GUI - // build left side panel - leftbox = new Gtk::VBox (); - leftbox->set_border_width (4); - leftbox->set_size_request(100,250); - - histogramPanel = Gtk::manage (new HistogramPanel ()); - histogramPanel->set_size_request (-1, 150); -// leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); - - profilep = Gtk::manage (new ProfilePanel ()); - Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ()); - ppframe->add (*profilep); - ppframe->set_label (M("PROFILEPANEL_LABEL")); -// leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); - - navigator = Gtk::manage (new Navigator ()); - navigator->previewWindow->set_size_request (-1, 150); - leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4); - - history = Gtk::manage (new History ()); - leftbox->pack_start (*history); - - leftbox->show_all (); - - // build the middle of the screen - Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ()); - - info = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (argv0+"/images/info.png")); - info->add (*infoimg); - info->set_relief(Gtk::RELIEF_NONE); - info->set_tooltip_markup (M("MAIN_TOOLTIP_QINFO")); - - beforeAfter = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* beforeAfterIcon = Gtk::manage (new Gtk::Image (argv0+"/images/beforeafter.png")); - beforeAfter->add(*beforeAfterIcon); - beforeAfter->set_relief(Gtk::RELIEF_NONE); - beforeAfter->set_tooltip_markup (M("MAIN_TOOLTIP_TOGGLE")); - - - Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ()); - - hidehp = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ()); - hidehpLabel->set_markup ("H"); - Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (argv0+"/images/left.png")); - Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ()); - hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2); - hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2); - hidehp->add (*hidehpBox); - hidehp->set_relief(Gtk::RELIEF_NONE); - hidehp->set_active (options.showHistory); - hidehp->set_tooltip_markup (M("MAIN_TOOLTIP_HIDEHP")); - - Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ()); - - iarea = new ImageAreaPanel (); - - Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); - toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4); - toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4); - toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0); - toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2); - - afterBox = Gtk::manage (new Gtk::VBox ()); - afterBox->pack_start (*iarea); - - beforeAfterBox = Gtk::manage (new Gtk::HBox()); - beforeAfterBox->pack_start (*afterBox); - - editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK); - editbox->pack_start (*beforeAfterBox); - - // build right side panel - vboxright = new Gtk::VBox (false, 0); - vboxright->set_size_request(100,250); - - vboxright->set_border_width (4); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); - vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); - // main notebook - vboxright->pack_start (*tpc->toolPanelNotebook); - - // Save buttons - Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ()); - - Gtk::HBox * saveButtonBox = Gtk::manage(new Gtk::HBox()); - saveButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); - saveButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SAVE"))), Gtk::PACK_SHRINK, 2); - saveimgas = Gtk::manage (new Gtk::Button ()); - saveimgas->add(*saveButtonBox); - saveimgas->set_tooltip_markup(M("MAIN_BUTTON_SAVE_TOOLTIP")); - - Gtk::HBox * queueButtonBox = Gtk::manage(new Gtk::HBox()); - queueButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); - queueButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_PUTTOQUEUE"))), Gtk::PACK_SHRINK, 2); - queueimg = Gtk::manage (new Gtk::Button ()); - queueimg->add(*queueButtonBox); - queueimg->set_tooltip_markup(M("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP")); - - Gtk::HBox * sendToEditorButtonBox = Gtk::manage(new Gtk::HBox()); - sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Image (argv0+"/images/gimp.png")), Gtk::PACK_SHRINK, 2); - sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SENDTOEDITOR"))), Gtk::PACK_SHRINK, 2); - sendtogimp = Gtk::manage (new Gtk::Button ()); - sendtogimp->add(*sendToEditorButtonBox); - sendtogimp->set_tooltip_markup(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP")); - - iops->pack_start (*saveimgas, Gtk::PACK_SHRINK); - iops->pack_start (*queueimg, Gtk::PACK_SHRINK); - iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK); - - // Status box - statusBox = Gtk::manage (new Gtk::HBox ()); - progressLabel = Gtk::manage (new Gtk::Label("")); - statusBox->pack_start (*progressLabel); - red = new Gtk::Image (argv0+"/images/red.png"); - green = new Gtk::Image (argv0+"/images/green.png"); - red->show (); - green->show (); - statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); - iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4); - - // Zoom panel - iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); - iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2); - - - editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4); - editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4); - editbox->show_all (); - - // build screen - hpanedl = Gtk::manage (new Gtk::HPaned()); - hpanedr = Gtk::manage (new Gtk::HPaned()); - leftbox->reference (); - vboxright->reference (); - if (options.showHistory) { - hpanedl->pack1(*leftbox, false, true); - hpanedl->set_position (options.historyPanelWidth); - } - - Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); - vbfr->set_size_request(100,250); - vbfr->add (*editbox); - hpanedl->pack2(*vbfr, true, true); - - hpanedr->pack1(*hpanedl, true, true); - hpanedr->pack2(*vboxright, false, true); - hpanedl->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &EditorPanel::leftPaneButtonReleased) ); - hpanedr->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &EditorPanel::rightPaneButtonReleased) ); - - pack_start (*hpanedr); - show_all (); - - // save as dialog - if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) - saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); - else - saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES)); - - saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); - -// connect listeners - profilep->setProfileChangeListener (tpc); - history->setProfileChangeListener (tpc); - history->setHistoryBeforeLineListener (this); - tpc->addPParamsChangeListener (profilep); - tpc->addPParamsChangeListener (history); - tpc->addPParamsChangeListener (this); - iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener()); - iarea->imageArea->setPointerMotionListener (navigator); - iarea->imageArea->setImageAreaToolListener (tpc); - -// initialize components - info->set_active (options.showInfo); - tpc->readOptions (); - -// connect event handlers - info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) ); - beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) ); - hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) ); - saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) ); - queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) ); - sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) ); - -} - -EditorPanel::~EditorPanel () { - - history->setHistoryBeforeLineListener (NULL); - // the order is important! - delete iarea; - delete beforeIarea; - - if (ipc) - ipc->setPreviewImageListener (NULL); - if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); - - delete previewHandler; - delete beforePreviewHandler; - - if (ipc) - close (); - - if (epih->pending) - epih->destroyed = true; - else - delete epih; - - delete tpc; - - delete red; - delete green; - delete leftbox; - delete vboxright; - - delete saveAsDialog; -} - -void EditorPanel::leftPaneButtonReleased(GdkEventButton *event) { - if (event->button == 1) { - // Button 1 released : it's a resize - options.historyPanelWidth = hpanedl->get_position(); - } - /*else if (event->button == 3) { - }*/ -} - -void EditorPanel::rightPaneButtonReleased(GdkEventButton *event) { - if (event->button == 1) { - int winW, winH; - parent->get_size(winW, winH); - // Button 1 released : it's a resize - options.toolPanelWidth = winW - hpanedr->get_position(); - } - /*else if (event->button == 3) { - }*/ -} - -void EditorPanel::setAspect () { - int winW, winH; - parent->get_size(winW, winH); - hpanedl->set_position(options.historyPanelWidth); - hpanedr->set_position(winW - options.toolPanelWidth); - // initialize components - if (info->get_active() != options.showInfo) - info->set_active (options.showInfo); -} - -void EditorPanel::on_realize () { - - Gtk::VBox::on_realize (); - // This line is needed to avoid autoexpansion of the window :-/ - vboxright->set_size_request (options.toolPanelWidth, -1); -} - -void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { - - // initialize everything - openThm = tmb; - openThm->increaseRef (); - - previewHandler = new PreviewHandler (); - - this->isrc = isrc; - ipc = rtengine::StagedImageProcessor::create (isrc); - ipc->setProgressListener (this); - ipc->setPreviewImageListener (previewHandler); - ipc->setPreviewScale (10); - tpc->initImage (ipc, tmb->getType()==FT_Raw); - ipc->setHistogramListener (this); - -// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen - iarea->imageArea->setPreviewHandler (previewHandler); - iarea->imageArea->setImProcCoordinator (ipc); - navigator->previewWindow->setPreviewHandler (previewHandler); - navigator->previewWindow->setImageArea (iarea->imageArea); - - // try to load the last saved parameters from the cache or from the paramfile file - ProcParams* ldprof = NULL; - if (openThm->hasProcParams()) { - ldprof = new ProcParams (); - *ldprof = openThm->getProcParams (); - } - - // initialize profile - if (openThm->getType()!=FT_Raw) - profilep->initProfile (options.defProfImg, ldprof, NULL); - else - profilep->initProfile (options.defProfRaw, ldprof, NULL); - - openThm->addThumbnailListener (this); - info_toggled (); -} - -void EditorPanel::close () { - - saveProfile (); - - // close image processor and the current thumbnail - tpc->closeImage (); // this call stops image processing - tpc->writeOptions (); - - if (ipc) - rtengine::StagedImageProcessor::destroy (ipc); - if (beforeIpc) - rtengine::StagedImageProcessor::destroy (beforeIpc); - - openThm->removeThumbnailListener (this); - openThm->decreaseRef (); -} - -void EditorPanel::saveProfile () { - - ProcParams params; - ipc->getParams (¶ms); - - if (options.saveParamsFile) - params.save (openThm->getFileName() + paramFileExtension); - if (openThm && options.saveParamsCache) - openThm->setProcParams (params, EDITOR); -} - -Glib::ustring EditorPanel::getShortName () { - - return Glib::path_get_basename (openThm->getFileName ()); -} - -Glib::ustring EditorPanel::getFileName () { - - return openThm->getFileName (); -} - -// TODO!!! -void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { - -// if (ev!=EvPhotoLoaded) -// saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); -} - -struct spsparams { - bool state; - EditorPanelIdleHelper* epih; -}; - -int setprocstate (void* data) { - - gdk_threads_enter (); - spsparams* p = (spsparams*)data; - - if (p->epih->destroyed) { - if (p->epih->pending == 1) - delete p->epih; - else - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; - } - - p->epih->epanel->refreshProcessingState (p->state); - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; -} - -void EditorPanel::setProgressState (int state) { - - epih->pending++; - - spsparams* p = new spsparams; - p->state = state; - p->epih = epih; - g_idle_add (setprocstate, p); -} - -void EditorPanel::refreshProcessingState (bool state) { - - // Set proc params of thumbnail. It saves it into the cache and updates the file browser. - if (ipc && openThm && !state && tpc->getChangedState()) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - openThm->setProcParams (pparams, EDITOR, false); - } - - // change state of the led - std::vector children = (std::vector) statusBox->get_children(); - if (children.size()>=1) { - Gtk::Widget* wlast = children[children.size()-1]; - if (wlast) - statusBox->remove (*wlast); - } - if (state) - statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4); - else - statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); -} - -struct errparams { - Glib::ustring descr; - EditorPanelIdleHelper* epih; -}; - -void EditorPanel::displayError (Glib::ustring descr) { - - if (parent) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_title (M("MAIN_MSG_CANNOTSAVE")); - msgd->run (); - delete msgd; - } -} - -int disperror (void* data) { - - gdk_threads_enter (); - errparams* p = (errparams*)data; - - if (p->epih->destroyed) { - if (p->epih->pending == 1) - delete p->epih; - else - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; - } - - p->epih->epanel->displayError (p->descr); - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; -} - -void EditorPanel::error (Glib::ustring descr) { - - epih->pending++; - errparams* p = new errparams; - p->descr = descr; - p->epih = epih; - g_idle_add (disperror, p); -} - -void EditorPanel::info_toggled () { - - Glib::ustring infoString; - - const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); - if (idata && idata->hasExif()) -// infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n", -// Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()), -// Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), -// M("QINFO_ISO"), idata->getISOSpeed(), -// M("QINFO_FOCALLENGTH"), idata->getFocalLen()) -// + Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens())); - infoString = Glib::ustring::compose ( - "%1 + %2\n%3s f/%4 %5%6 f=%7mm", - Glib::ustring(idata->getModel()), - Glib::ustring(idata->getLens()), - Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), - Glib::ustring(idata->apertureToString(idata->getFNumber())), - M("QINFO_ISO"), idata->getISOSpeed(), - idata->getFocalLen() - ); - else - infoString = M("QINFO_NOEXIF"); - - iarea->imageArea->setInfoText (infoString); - iarea->imageArea->infoEnabled (info->get_active ()); -} - -void EditorPanel::hideHistoryActivated () { - - removeIfThere (hpanedl, leftbox, false); - if (hidehp->get_active()) - hpanedl->pack1 (*leftbox, false, true); - options.showHistory = hidehp->get_active(); -} - -bool EditorPanel::handleShortcutKey (GdkEventKey* event) { - - bool ctrl = event->state & GDK_CONTROL_MASK; - bool shift = event->state & GDK_SHIFT_MASK; - - if (!ctrl) { - switch(event->keyval) { - case GDK_h: - case GDK_H: - hidehp->set_active (!hidehp->get_active()); - return true; - case GDK_i: - case GDK_I: - info->set_active (!info->get_active()); - return true; - case GDK_b: - case GDK_B: - beforeAfter->set_active (!beforeAfter->get_active()); - return true; - case GDK_plus: - case GDK_equal: - iarea->imageArea->zoomPanel->zoomInClicked(); - return true; - case GDK_minus: - case GDK_underscore: - iarea->imageArea->zoomPanel->zoomOutClicked(); - return true; - case GDK_1: - iarea->imageArea->zoomPanel->zoom11Clicked(); - return true; - case GDK_f: - case GDK_F: - iarea->imageArea->zoomPanel->zoomFitClicked(); - return true; - } - } - else { - switch (event->keyval) { - case GDK_s: - saveAsPressed(); - return true; - case GDK_q: - queueImgPressed(); - return true; - case GDK_e: - sendToGimpPressed(); - return true; - case GDK_z: - history->undo (); - return true; - case GDK_Z: - history->redo (); - return true; - } - } - - if(tpc->getToolBar()->handleShortcutKey(event)) - return true; - - return false; -} - -void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { - - if (whoChangedIt!=EDITOR) - tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, M("PROGRESSDLG_PROFILECHANGEDINBROWSER")); -} - -bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, bool findNewNameIfNeeded){ - rtengine::IImage16* img = pc->returnValue(); - delete pc; - if( img ) - saveImage( img, fname, sf, findNewNameIfNeeded); - else{ - Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - - } - return false; -} - -BatchQueueEntry* EditorPanel::createBatchQueueEntry () { - - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - int prevh = options.maxThumbnailHeight; - int prevw = prevh; - guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh); - double tmpscale; - rtengine::IImage8* img = openThm->processThumbImage (pparams, options.maxThumbnailHeight, tmpscale); - if (img) { - prevw = img->getWidth (); - prevh = img->getHeight (); - prev = new guint8 [prevw*prevh*3]; - memcpy (prev, img->getData (), prevw*prevh*3); - img->free(); - } - return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm); -} - -int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) { - - Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); - if (findNewNameIfNeeded) { - int tries = 1; - while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { - fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); - tries++; - } - if (tries==1000) - return -1000; - } - ProgressConnector *ld = new ProgressConnector(); - img->setSaveProgressListener (parent->getProgressListener()); - if (sf.format=="tif") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - else if (sf.format=="png") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - else if (sf.format=="jpg") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - return 0; -} - -bool EditorPanel::idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf){ - img->free (); - if (! pc->returnValue() ) { - openThm->imageDeveloped (); - // save processing parameters, if needed - if (sf.saveParams) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - // We keep the extension to avoid overwriting the profile when we have - // the same output filename with different extension - //pparams.save (removeExtension (fname) + ".out" + paramFileExtension); - pparams.save (fname + ".out" + paramFileExtension); - } - }else{ - Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image saving\n"; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - } - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); - delete pc; - return false; -} - -void EditorPanel::saveAsPressed () { - - bool fnameOK = false; - Glib::ustring fname; - - saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName()))); - do { - saveAsDialog->run (); - fname = saveAsDialog->getFileName (); - if (fname=="") - return; - - options.lastSaveAsPath = saveAsDialog->getDirectory (); - options.saveAsDialogWidth = saveAsDialog->get_width(); - options.saveAsDialogHeight = saveAsDialog->get_height(); - - SaveFormat sf = saveAsDialog->getFormat (); - - options.saveFormat = sf; - options.autoSuffix = saveAsDialog->getAutoSuffix(); - - if (saveAsDialog->getImmediately ()) { - // separate filename and the path to the destination directory - Glib::ustring dstdir = Glib::path_get_dirname (fname); - Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fname)); - - if (saveAsDialog->getAutoSuffix()) { - - Glib::ustring fnameTemp; - for (int tries=0; tries<100; tries++) { - if (tries==0) - fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), sf.format); - else - fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, sf.format); - - if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { - fname = fnameTemp; - fnameOK = true; - break; - } - } - } - // check if it exists - if (!fnameOK) { - fname = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), sf.format); - if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) { - Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + ""; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); - int response = msgd.run (); - if (response==Gtk::RESPONSE_YES) - fnameOK = true; - } - else fnameOK = true; - } - - if (fnameOK) { - // save image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - fname = removeExtension (fname); - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fname,sf,false )); - saveimgas->set_sensitive(false); - sendtogimp->set_sensitive(false); - } - } - else { - BatchQueueEntry* bqe = createBatchQueueEntry (); - bqe->outFileName = fname; - bqe->saveFormat = saveAsDialog->getFormat (); - parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); - fnameOK = true; - } - // ask parent to redraw file browser - // ... or does it automatically when the tab is switched to it - } while (!fnameOK); -} - -void EditorPanel::queueImgPressed () { - - saveProfile (); - parent->addBatchQueueJob (createBatchQueueEntry ()); -} - -void EditorPanel::sendToGimpPressed () { - // develop image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_sendToGimp ),ld )); - saveimgas->set_sensitive(false); - sendtogimp->set_sensitive(false); -} - -bool EditorPanel::idle_sendToGimp( ProgressConnector *pc){ - - rtengine::IImage16* img = pc->returnValue(); - delete pc; - if (img) { - // get file name base - Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName())); - Glib::ustring dirname = Glib::get_tmp_dir (); - Glib::ustring fname = Glib::build_filename (dirname, shortname); - - SaveFormat sf; - sf.format = "tif"; - sf.tiffBits = 16; - - Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); - - int tries = 1; - while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { - fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); - tries++; - } - if (tries==1000){ - img->free (); - return false; - } - - ProgressConnector *ld = new ProgressConnector(); - img->setSaveProgressListener (parent->getProgressListener()); - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_sentToGimp), ld, img, fileName)); - }else{ - Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - } - return false; -} - -bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename){ - img->free (); - int errore = pc->returnValue(); - delete pc; - if (!errore) { - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); - bool success=false; - Glib::ustring cmdLine; - // start gimp - if (options.editorToSendTo==1) { -#ifdef _WIN32 - cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\""; -#else - cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - if (!success){ -#ifdef _WIN32 - int ver = 12; - while (!success && ver) { - cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\""; - ver--; - success = safe_spawn_command_line_async (cmdLine); - } -#elif defined __APPLE__ - cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; - success = safe_spawn_command_line_async (cmdLine); -#else - cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; - success = safe_spawn_command_line_async (cmdLine); -#endif - } - } - else if (options.editorToSendTo==2) { -#ifdef __APPLE__ - cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir,"Photoshop.app\' ") + "\'" + filename + "\'"; -#else - cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - } - else if (options.editorToSendTo==3) { -#ifdef __APPLE__ - cmdLine = Glib::ustring("") + options.customEditorProg + filename; -#else - cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - } - - if (!success) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); - msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR")); - msgd->run (); - delete msgd; - } - - } - - return false; -} - -/* -void EditorPanel::saveOptions () { -} -*/ - -void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { - - if (beforeIpc) { - ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged); - *pparams = params; - beforeIpc->paramsUpdateReady (); - } -} - -void EditorPanel::beforeAfterToggled () { - - removeIfThere (beforeAfterBox, beforeBox, false); - removeIfThere (afterBox, afterLabel, false); - - if (beforeIarea) { - if (beforeIpc) - beforeIpc->stopProcessing (); - iarea->setBeforeAfterViews (NULL, iarea); - delete beforeIarea; - beforeIarea = NULL; - if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); - delete beforePreviewHandler; - beforePreviewHandler = NULL; - if (beforeIpc) - rtengine::StagedImageProcessor::destroy (beforeIpc); - beforeIpc = NULL; - } - - if (beforeAfter->get_active ()) { - - beforeIarea = new ImageAreaPanel (); - - beforeLabel = Gtk::manage (new Gtk::Label ()); - beforeLabel->set_markup (Glib::ustring("") + M("GENERAL_BEFORE") + ""); - beforeBox = Gtk::manage (new Gtk::VBox ()); - beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2); - beforeBox->pack_start (*beforeIarea); - - afterLabel = Gtk::manage (new Gtk::Label ()); - afterLabel->set_markup (Glib::ustring("") + M("GENERAL_AFTER") + ""); - afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2); - afterBox->reorder_child (*afterLabel, 0); - - beforeAfterBox->pack_start (*beforeBox); - beforeAfterBox->reorder_child (*beforeBox, 0); - beforeAfterBox->show_all (); - - beforePreviewHandler = new PreviewHandler (); - isrc->increaseRef (); - beforeIpc = rtengine::StagedImageProcessor::create (isrc); - beforeIpc->setPreviewScale (10); - beforeIpc->setPreviewImageListener (beforePreviewHandler); - beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler); - beforeIarea->imageArea->setImProcCoordinator (beforeIpc); - - iarea->setBeforeAfterViews (beforeIarea, iarea); - beforeIarea->setBeforeAfterViews (beforeIarea, iarea); - - rtengine::procparams::ProcParams params; - if (history->getBeforeLineParams (params)) - historyBeforeLineChanged (params); - } -} - -void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) { - - histogramPanel->histogramChanged (rh, gh, bh, lh); - tpc->updateCurveBackgroundHistogram (bcrgb, bcl); -} +/* + * 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 +#include +#include +#include +#include +#include +#include + +using namespace rtengine::procparams; + +EditorPanel::EditorPanel (FilePanel* filePanel) : beforePreviewHandler(NULL), beforeIarea(NULL), parent(NULL), beforeIpc(NULL), ipc(NULL), catalogPane(NULL) { + + epih = new EditorPanelIdleHelper; + epih->epanel = this; + epih->destroyed = false; + epih->pending = 0; + +// construct toolpanelcoordinator + tpc = new ToolPanelCoordinator (); + +// build GUI + // build left side panel + leftbox = new Gtk::VBox (); + leftbox->set_border_width (4); + leftbox->set_size_request(100,250); + + histogramPanel = Gtk::manage (new HistogramPanel ()); + histogramPanel->set_size_request (-1, 150); +// leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); + + profilep = Gtk::manage (new ProfilePanel ()); + Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ()); + ppframe->add (*profilep); + ppframe->set_label (M("PROFILEPANEL_LABEL")); +// leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); + + navigator = Gtk::manage (new Navigator ()); + navigator->previewWindow->set_size_request (-1, 150); + leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4); + + history = Gtk::manage (new History ()); + leftbox->pack_start (*history); + + leftbox->show_all (); + + // build the middle of the screen + Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ()); + + info = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (argv0+"/images/info.png")); + info->add (*infoimg); + info->set_relief(Gtk::RELIEF_NONE); + info->set_tooltip_markup (M("MAIN_TOOLTIP_QINFO")); + + beforeAfter = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* beforeAfterIcon = Gtk::manage (new Gtk::Image (argv0+"/images/beforeafter.png")); + beforeAfter->add(*beforeAfterIcon); + beforeAfter->set_relief(Gtk::RELIEF_NONE); + beforeAfter->set_tooltip_markup (M("MAIN_TOOLTIP_TOGGLE")); + + + Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ()); + + hidehp = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ()); + hidehpLabel->set_markup ("H"); + Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (argv0+"/images/left.png")); + Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ()); + hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2); + hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2); + hidehp->add (*hidehpBox); + hidehp->set_relief(Gtk::RELIEF_NONE); + hidehp->set_active (options.showHistory); + hidehp->set_tooltip_markup (M("MAIN_TOOLTIP_HIDEHP")); + + Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ()); + + iarea = new ImageAreaPanel (); + + Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); + toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4); + toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4); + toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0); + toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2); + + afterBox = Gtk::manage (new Gtk::VBox ()); + afterBox->pack_start (*iarea); + + beforeAfterBox = Gtk::manage (new Gtk::HBox()); + beforeAfterBox->pack_start (*afterBox); + + editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK); + editbox->pack_start (*beforeAfterBox); + + // build right side panel + vboxright = new Gtk::VBox (false, 0); + vboxright->set_size_request(100,250); + + vboxright->set_border_width (4); + vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); + vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); + // main notebook + vboxright->pack_start (*tpc->toolPanelNotebook); + + // Save buttons + Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ()); + + Gtk::HBox * saveButtonBox = Gtk::manage(new Gtk::HBox()); + saveButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); + saveButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SAVE"))), Gtk::PACK_SHRINK, 2); + saveimgas = Gtk::manage (new Gtk::Button ()); + saveimgas->add(*saveButtonBox); + saveimgas->set_tooltip_markup(M("MAIN_BUTTON_SAVE_TOOLTIP")); + + Gtk::HBox * queueButtonBox = Gtk::manage(new Gtk::HBox()); + queueButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); + queueButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_PUTTOQUEUE"))), Gtk::PACK_SHRINK, 2); + queueimg = Gtk::manage (new Gtk::Button ()); + queueimg->add(*queueButtonBox); + queueimg->set_tooltip_markup(M("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP")); + + Gtk::HBox * sendToEditorButtonBox = Gtk::manage(new Gtk::HBox()); + sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Image (argv0+"/images/gimp.png")), Gtk::PACK_SHRINK, 2); + sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SENDTOEDITOR"))), Gtk::PACK_SHRINK, 2); + sendtogimp = Gtk::manage (new Gtk::Button ()); + sendtogimp->add(*sendToEditorButtonBox); + sendtogimp->set_tooltip_markup(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP")); + + iops->pack_start (*saveimgas, Gtk::PACK_SHRINK); + iops->pack_start (*queueimg, Gtk::PACK_SHRINK); + iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK); + + // Status box + statusBox = Gtk::manage (new Gtk::HBox ()); + progressLabel = Gtk::manage (new Gtk::Label("")); + statusBox->pack_start (*progressLabel); + red = new Gtk::Image (argv0+"/images/red.png"); + green = new Gtk::Image (argv0+"/images/green.png"); + red->show (); + green->show (); + statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); + iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4); + + // Zoom panel + iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); + iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2); + + + editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4); + editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4); + editbox->show_all (); + + // build screen + hpanedl = Gtk::manage (new Gtk::HPaned()); + hpanedr = Gtk::manage (new Gtk::HPaned()); + leftbox->reference (); + vboxright->reference (); + if (options.showHistory) { + hpanedl->pack1(*leftbox, false, true); + hpanedl->set_position (options.historyPanelWidth); + } + + + Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned()); + fPanel = filePanel; + if(filePanel) + { + catalogPane = new Gtk::Paned(); + viewpaned->pack1(*catalogPane, false, true); + } + viewpaned->pack2(*editbox, true, true); + + + Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); + vbfr->add (*viewpaned); + vbfr->set_size_request(100,250); + hpanedl->pack2(*vbfr, true, true); + + hpanedr->pack1(*hpanedl, true, true); + hpanedr->pack2(*vboxright, false, true); + hpanedl->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &EditorPanel::leftPaneButtonReleased) ); + hpanedr->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &EditorPanel::rightPaneButtonReleased) ); + + pack_start (*hpanedr); + show_all (); + + // save as dialog + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); + else + saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES)); + + saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); + +// connect listeners + profilep->setProfileChangeListener (tpc); + history->setProfileChangeListener (tpc); + history->setHistoryBeforeLineListener (this); + tpc->addPParamsChangeListener (profilep); + tpc->addPParamsChangeListener (history); + tpc->addPParamsChangeListener (this); + iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener()); + iarea->imageArea->setPointerMotionListener (navigator); + iarea->imageArea->setImageAreaToolListener (tpc); + +// initialize components + info->set_active (options.showInfo); + tpc->readOptions (); + +// connect event handlers + info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) ); + beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) ); + hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) ); + saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) ); + queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) ); + sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) ); + +} + + + +EditorPanel::~EditorPanel () { + + history->setHistoryBeforeLineListener (NULL); + // the order is important! + delete iarea; + iarea = NULL; + delete beforeIarea; + beforeIarea = NULL; + + delete beforePreviewHandler; + + close (); + + if (epih->pending) + epih->destroyed = true; + else + delete epih; + + delete tpc; + + delete red; + delete green; + delete leftbox; + delete vboxright; + delete saveAsDialog; + if(catalogPane) + delete catalogPane; +} + +void EditorPanel::leftPaneButtonReleased(GdkEventButton *event) { + if (event->button == 1) { + // Button 1 released : it's a resize + options.historyPanelWidth = hpanedl->get_position(); + } + /*else if (event->button == 3) { + }*/ +} + +void EditorPanel::rightPaneButtonReleased(GdkEventButton *event) { + if (event->button == 1) { + int winW, winH; + parent->get_size(winW, winH); + // Button 1 released : it's a resize + options.toolPanelWidth = winW - hpanedr->get_position(); + } + /*else if (event->button == 3) { + }*/ +} + +void EditorPanel::setAspect () { + int winW, winH; + parent->get_size(winW, winH); + hpanedl->set_position(options.historyPanelWidth); + hpanedr->set_position(winW - options.toolPanelWidth); + // initialize components + if (info->get_active() != options.showInfo) + info->set_active (options.showInfo); +} + +void EditorPanel::on_realize () { + + Gtk::VBox::on_realize (); + // This line is needed to avoid autoexpansion of the window :-/ + vboxright->set_size_request (options.toolPanelWidth, -1); +} + +void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { + + if (ipc) close(); + // initialize everything + openThm = tmb; + openThm->increaseRef (); + + previewHandler = new PreviewHandler (); + + this->isrc = isrc; + ipc = rtengine::StagedImageProcessor::create (isrc); + ipc->setProgressListener (this); + ipc->setPreviewImageListener (previewHandler); + ipc->setPreviewScale (10); + tpc->initImage (ipc, tmb->getType()==FT_Raw); + ipc->setHistogramListener (this); + +// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen + iarea->imageArea->setPreviewHandler (previewHandler); + iarea->imageArea->setImProcCoordinator (ipc); + navigator->previewWindow->setPreviewHandler (previewHandler); + navigator->previewWindow->setImageArea (iarea->imageArea); + + // try to load the last saved parameters from the cache or from the paramfile file + ProcParams* ldprof = NULL; + if (openThm->hasProcParams()) { + ldprof = new ProcParams (); + *ldprof = openThm->getProcParams (); + } + + // initialize profile + if (openThm->getType()!=FT_Raw) + profilep->initProfile (options.defProfImg, ldprof, NULL); + else + profilep->initProfile (options.defProfRaw, ldprof, NULL); + + openThm->addThumbnailListener (this); + info_toggled (); + + if (beforeIarea) + { + beforeAfterToggled(); + beforeAfterToggled(); + } + + if (iarea->imageArea->mainCropWindow) + { + iarea->imageArea->mainCropWindow->cropHandler.newImage(ipc); + iarea->imageArea->mainCropWindow->initialImageArrived(); + } +} + +void EditorPanel::close () { + + if (ipc) + { + saveProfile (); + // close image processor and the current thumbnail + tpc->closeImage (); // this call stops image processing + tpc->writeOptions (); + + if (ipc) + ipc->setPreviewImageListener (NULL); + + if (beforeIpc) + beforeIpc->setPreviewImageListener (NULL); + + delete previewHandler; + previewHandler= NULL; + + rtengine::StagedImageProcessor::destroy (ipc); + ipc = NULL; + + if(iarea) + { + iarea->imageArea->setPreviewHandler (NULL); + iarea->imageArea->setImProcCoordinator (NULL); + } + navigator->previewWindow->setPreviewHandler (NULL); + // navigator->previewWindow->setImageArea (NULL); + + openThm->removeThumbnailListener (this); + openThm->decreaseRef (); + + } +} + +void EditorPanel::saveProfile () { + + if (!ipc) + return; + ProcParams params; + ipc->getParams (¶ms); + + if (options.saveParamsFile) + params.save (openThm->getFileName() + paramFileExtension); + if (openThm && options.saveParamsCache) + openThm->setProcParams (params, EDITOR); +} + +Glib::ustring EditorPanel::getShortName () { + + return Glib::path_get_basename (openThm->getFileName ()); +} + +Glib::ustring EditorPanel::getFileName () { + + return openThm->getFileName (); +} + +// TODO!!! +void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { + +// if (ev!=EvPhotoLoaded) +// saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); +} + +struct spsparams { + bool state; + EditorPanelIdleHelper* epih; +}; + +int setprocstate (void* data) { + + gdk_threads_enter (); + spsparams* p = (spsparams*)data; + + if (p->epih->destroyed) { + if (p->epih->pending == 1) + delete p->epih; + else + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; + } + + p->epih->epanel->refreshProcessingState (p->state); + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; +} + +void EditorPanel::setProgressState (int state) { + + epih->pending++; + + spsparams* p = new spsparams; + p->state = state; + p->epih = epih; + g_idle_add (setprocstate, p); +} + +void EditorPanel::refreshProcessingState (bool state) { + + // Set proc params of thumbnail. It saves it into the cache and updates the file browser. + if (ipc && openThm && !state && tpc->getChangedState()) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + openThm->setProcParams (pparams, EDITOR, false); + } + + // change state of the led + std::vector children = (std::vector) statusBox->get_children(); + if (children.size()>=1) { + Gtk::Widget* wlast = children[children.size()-1]; + if (wlast) + statusBox->remove (*wlast); + } + if (state) + statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4); + else + statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); +} + +struct errparams { + Glib::ustring descr; + EditorPanelIdleHelper* epih; +}; + +void EditorPanel::displayError (Glib::ustring descr) { + + if (parent) { + Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd->set_title (M("MAIN_MSG_CANNOTSAVE")); + msgd->run (); + delete msgd; + } +} + +int disperror (void* data) { + + gdk_threads_enter (); + errparams* p = (errparams*)data; + + if (p->epih->destroyed) { + if (p->epih->pending == 1) + delete p->epih; + else + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; + } + + p->epih->epanel->displayError (p->descr); + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; +} + +void EditorPanel::error (Glib::ustring descr) { + + epih->pending++; + errparams* p = new errparams; + p->descr = descr; + p->epih = epih; + g_idle_add (disperror, p); +} + +void EditorPanel::info_toggled () { + + Glib::ustring infoString; + + const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); + if (idata && idata->hasExif()) +// infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n", +// Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()), +// Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), +// M("QINFO_ISO"), idata->getISOSpeed(), +// M("QINFO_FOCALLENGTH"), idata->getFocalLen()) +// + Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens())); +infoString = Glib::ustring::compose ( + "%1 + %2\n%3s f/%4 %5%6 f=%7mm", + Glib::ustring(idata->getModel()), + Glib::ustring(idata->getLens()), + Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), + Glib::ustring(idata->apertureToString(idata->getFNumber())), + M("QINFO_ISO"), idata->getISOSpeed(), + idata->getFocalLen() + ); + else + infoString = M("QINFO_NOEXIF"); + + iarea->imageArea->setInfoText (infoString); + iarea->imageArea->infoEnabled (info->get_active ()); +} + +void EditorPanel::hideHistoryActivated () { + + removeIfThere (hpanedl, leftbox, false); + if (hidehp->get_active()) + hpanedl->pack1 (*leftbox, false, true); + options.showHistory = hidehp->get_active(); +} + +bool EditorPanel::handleShortcutKey (GdkEventKey* event) { + + bool ctrl = event->state & GDK_CONTROL_MASK; + bool shift = event->state & GDK_SHIFT_MASK; + + if (!ctrl) { + switch(event->keyval) { + case GDK_h: + case GDK_H: + hidehp->set_active (!hidehp->get_active()); + return true; + case GDK_i: + case GDK_I: + info->set_active (!info->get_active()); + return true; + case GDK_b: + case GDK_B: + beforeAfter->set_active (!beforeAfter->get_active()); + return true; + case GDK_plus: + case GDK_equal: + iarea->imageArea->zoomPanel->zoomInClicked(); + return true; + case GDK_minus: + case GDK_underscore: + iarea->imageArea->zoomPanel->zoomOutClicked(); + return true; + case GDK_1: + iarea->imageArea->zoomPanel->zoom11Clicked(); + return true; + case GDK_f: + case GDK_F: + iarea->imageArea->zoomPanel->zoomFitClicked(); + return true; + } + } + else { + switch (event->keyval) { + case GDK_s: + saveAsPressed(); + return true; + case GDK_q: + queueImgPressed(); + return true; + case GDK_e: + sendToGimpPressed(); + return true; + case GDK_z: + history->undo (); + return true; + case GDK_Z: + history->redo (); + return true; + } + } + + if(tpc->getToolBar()->handleShortcutKey(event)) + return true; + + return false; +} + +void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { + + if (whoChangedIt!=EDITOR) + tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, M("PROGRESSDLG_PROFILECHANGEDINBROWSER")); +} + +bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, bool findNewNameIfNeeded){ + rtengine::IImage16* img = pc->returnValue(); + delete pc; + if( img ) + saveImage( img, fname, sf, findNewNameIfNeeded); + else{ + Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + + } + return false; +} + +BatchQueueEntry* EditorPanel::createBatchQueueEntry () { + + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + //rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType()==FT_Raw, pparams); + int prevh = options.maxThumbnailHeight; + int prevw = prevh; + guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh); + double tmpscale; + rtengine::IImage8* img = openThm->processThumbImage (pparams, options.maxThumbnailHeight, tmpscale); + if (img) { + prevw = img->getWidth (); + prevh = img->getHeight (); + prev = new guint8 [prevw*prevh*3]; + memcpy (prev, img->getData (), prevw*prevh*3); + img->free(); + } + return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm); +} + +int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) { + + Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + if (findNewNameIfNeeded) { + int tries = 1; + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { + fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); + tries++; + } + if (tries==1000) + return -1000; + } + ProgressConnector *ld = new ProgressConnector(); + img->setSaveProgressListener (parent->getProgressListener()); + if (sf.format=="tif") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + else if (sf.format=="png") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + else if (sf.format=="jpg") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + return 0; +} + +bool EditorPanel::idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf){ + img->free (); + if (! pc->returnValue() ) { + openThm->imageDeveloped (); + // save processing parameters, if needed + if (sf.saveParams) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + // We keep the extension to avoid overwriting the profile when we have + // the same output filename with different extension + //pparams.save (removeExtension (fname) + ".out" + paramFileExtension); + pparams.save (fname + ".out" + paramFileExtension); + } + }else{ + Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image saving\n"; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + } + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + parent->setProgressStr(""); + parent->setProgress(0.); + delete pc; + return false; +} + +void EditorPanel::saveAsPressed () { + + bool fnameOK = false; + Glib::ustring fname; + + saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName()))); + do { + saveAsDialog->run (); + fname = saveAsDialog->getFileName (); + if (fname=="") + return; + + options.lastSaveAsPath = saveAsDialog->getDirectory (); + options.saveAsDialogWidth = saveAsDialog->get_width(); + options.saveAsDialogHeight = saveAsDialog->get_height(); + + SaveFormat sf = saveAsDialog->getFormat (); + + options.saveFormat = sf; + options.autoSuffix = saveAsDialog->getAutoSuffix(); + + if (saveAsDialog->getImmediately ()) { + // separate filename and the path to the destination directory + Glib::ustring dstdir = Glib::path_get_dirname (fname); + Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fname)); + + if (saveAsDialog->getAutoSuffix()) { + + Glib::ustring fnameTemp; + for (int tries=0; tries<100; tries++) { + if (tries==0) + fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), sf.format); + else + fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, sf.format); + + if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { + fname = fnameTemp; + fnameOK = true; + break; + } + } + } + // check if it exists + if (!fnameOK) { + fname = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), sf.format); + if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) { + Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + ""; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); + int response = msgd.run (); + if (response==Gtk::RESPONSE_YES) + fnameOK = true; + } + else fnameOK = true; + } + + if (fnameOK) { + // save image + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + fname = removeExtension (fname); + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), + sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fname,sf,false )); + saveimgas->set_sensitive(false); + sendtogimp->set_sensitive(false); + } + } + else { + BatchQueueEntry* bqe = createBatchQueueEntry (); + bqe->outFileName = fname; + bqe->saveFormat = saveAsDialog->getFormat (); + parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); + fnameOK = true; + } + // ask parent to redraw file browser + // ... or does it automatically when the tab is switched to it + } while (!fnameOK); +} + +void EditorPanel::queueImgPressed () { + + saveProfile (); + parent->addBatchQueueJob (createBatchQueueEntry ()); +} + +void EditorPanel::sendToGimpPressed () { + // develop image + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), + sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_sendToGimp ),ld )); + saveimgas->set_sensitive(false); + sendtogimp->set_sensitive(false); +} + +bool EditorPanel::idle_sendToGimp( ProgressConnector *pc){ + + rtengine::IImage16* img = pc->returnValue(); + delete pc; + if (img) { + // get file name base + Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName())); + Glib::ustring dirname = Glib::get_tmp_dir (); + Glib::ustring fname = Glib::build_filename (dirname, shortname); + + SaveFormat sf; + sf.format = "tif"; + sf.tiffBits = 16; + + Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + + int tries = 1; + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { + fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); + tries++; + } + if (tries==1000){ + img->free (); + return false; + } + + ProgressConnector *ld = new ProgressConnector(); + img->setSaveProgressListener (parent->getProgressListener()); + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_sentToGimp), ld, img, fileName)); + }else{ + Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + } + return false; +} + +bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename){ + img->free (); + int errore = pc->returnValue(); + delete pc; + if (!errore) { + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + parent->setProgressStr(""); + parent->setProgress(0.); + bool success=false; + Glib::ustring cmdLine; + // start gimp + if (options.editorToSendTo==1) { +#ifdef _WIN32 + cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\""; +#else + cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + if (!success){ +#ifdef _WIN32 + int ver = 12; + while (!success && ver) { + cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\""; + ver--; + success = safe_spawn_command_line_async (cmdLine); + } +#elif defined __APPLE__ + cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; + success = safe_spawn_command_line_async (cmdLine); +#else + cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; + success = safe_spawn_command_line_async (cmdLine); +#endif + } + } + else if (options.editorToSendTo==2) { +#ifdef __APPLE__ + cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir,"Photoshop.app\' ") + "\'" + filename + "\'"; +#else + cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + } + else if (options.editorToSendTo==3) { +#ifdef __APPLE__ + cmdLine = Glib::ustring("") + options.customEditorProg + filename; +#else + cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + } + + if (!success) { + Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); + msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR")); + msgd->run (); + delete msgd; + } + + } + + return false; +} + +/* +void EditorPanel::saveOptions () { +} +*/ + +void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { + + if (beforeIpc) { + ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged); + *pparams = params; + beforeIpc->paramsUpdateReady (); + } +} + +void EditorPanel::beforeAfterToggled () { + + if(!ipc) + return; + + removeIfThere (beforeAfterBox, beforeBox, false); + removeIfThere (afterBox, afterLabel, false); + + if (beforeIarea) { + if (beforeIpc) + beforeIpc->stopProcessing (); + iarea->setBeforeAfterViews (NULL, iarea); + delete beforeIarea; + beforeIarea = NULL; + if (beforeIpc) + beforeIpc->setPreviewImageListener (NULL); + delete beforePreviewHandler; + beforePreviewHandler = NULL; + if (beforeIpc) + rtengine::StagedImageProcessor::destroy (beforeIpc); + beforeIpc = NULL; + } + + if (beforeAfter->get_active ()) { + + beforeIarea = new ImageAreaPanel (); + + beforeLabel = Gtk::manage (new Gtk::Label ()); + beforeLabel->set_markup (Glib::ustring("") + M("GENERAL_BEFORE") + ""); + beforeBox = Gtk::manage (new Gtk::VBox ()); + beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2); + beforeBox->pack_start (*beforeIarea); + + afterLabel = Gtk::manage (new Gtk::Label ()); + afterLabel->set_markup (Glib::ustring("") + M("GENERAL_AFTER") + ""); + afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2); + afterBox->reorder_child (*afterLabel, 0); + + beforeAfterBox->pack_start (*beforeBox); + beforeAfterBox->reorder_child (*beforeBox, 0); + beforeAfterBox->show_all (); + + beforePreviewHandler = new PreviewHandler (); + isrc->increaseRef (); + beforeIpc = rtengine::StagedImageProcessor::create (isrc); + beforeIpc->setPreviewScale (10); + beforeIpc->setPreviewImageListener (beforePreviewHandler); + beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler); + beforeIarea->imageArea->setImProcCoordinator (beforeIpc); + + iarea->setBeforeAfterViews (beforeIarea, iarea); + beforeIarea->setBeforeAfterViews (beforeIarea, iarea); + + rtengine::procparams::ProcParams params; + if (history->getBeforeLineParams (params)) + historyBeforeLineChanged (params); + } +} + +void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) { + + histogramPanel->histogramChanged (rh, gh, bh, lh); + tpc->updateCurveBackgroundHistogram (bcrgb, bcl); +} \ No newline at end of file diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index d870a7c33..211df5fd2 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -32,6 +32,7 @@ #include #include #include +#include class EditorPanel; struct EditorPanelIdleHelper { @@ -81,6 +82,9 @@ class EditorPanel : public Gtk::VBox, ToolPanelCoordinator* tpc; RTWindow* parent; SaveAsDialog* saveAsDialog; + BatchToolPanelCoordinator* btpCoordinator; + FilePanel* fPanel; + Thumbnail* openThm; rtengine::InitialImage* isrc; @@ -100,7 +104,7 @@ class EditorPanel : public Gtk::VBox, int err; public: - EditorPanel (); + EditorPanel (FilePanel* filePanel = NULL); virtual ~EditorPanel (); void open (Thumbnail* tmb, rtengine::InitialImage* isrc); @@ -143,6 +147,8 @@ class EditorPanel : public Gtk::VBox, bool handleShortcutKey (GdkEventKey* event); //void saveOptions (); + + Gtk::Paned *catalogPane; }; #endif diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index e2717a69a..69a3c1345 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -32,7 +32,7 @@ FileBrowser::FileBrowser () fbih->destroyed = false; fbih->pending = 0; - profileStore.parseProfiles (); + // profileStore.parseProfiles (); signal_style_changed().connect( sigc::mem_fun(*this, &FileBrowser::styleChanged) ); diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 2f62cf6fd..36cd269c2 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -1,971 +1,972 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CHECKTIME 2000 - -extern Glib::ustring argv0; - -#ifdef _WIN32 -int _directoryUpdater (void* cat) { - - ((FileCatalog*)cat)->checkCounter++; - if (((FileCatalog*)cat)->checkCounter==2) { - gdk_threads_enter (); - ((FileCatalog*)cat)->reparseDirectory (); - gdk_threads_leave (); - } - return 1; -} -#endif - -FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb) : listener(NULL), fslistener(NULL), hasValidCurrentEFS(false), filterPanel(NULL), coarsePanel(cp), toolBar(tb) { - - previewLoader.setPreviewLoaderListener (this); - - // construct and initialize thumbnail browsers - fileBrowser = new FileBrowser(); - fileBrowser->setFileBrowserListener (this); - fileBrowser->setArrangement (ThumbBrowserBase::TB_Vertical); - fileBrowser->show (); - - // construct trash panel with the extra "empty trash" button - trashButtonBox = new Gtk::VBox; - Gtk::Button* emptyT = new Gtk::Button (M("FILEBROWSER_EMPTYTRASH")); - emptyT->set_tooltip_markup (M("FILEBROWSER_EMPTYTRASHHINT")); - emptyT->set_image (*(new Gtk::Image (Gtk::StockID("gtk-delete"), Gtk::ICON_SIZE_BUTTON))); - emptyT->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::emptyTrash)); - trashButtonBox->pack_start (*emptyT, Gtk::PACK_SHRINK, 4); - emptyT->show (); - trashButtonBox->show (); - - // setup button bar - buttonBar = new Gtk::HBox (); - pack_start (*buttonBar, Gtk::PACK_SHRINK); - - buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); - bDir = new Gtk::ToggleButton (); - bDir->set_active (true); - bDir->set_image (*(new Gtk::Image (argv0+"/images/folder.png"))); - bDir->set_relief (Gtk::RELIEF_NONE); - bDir->set_tooltip_markup (M("FILEBROWSER_SHOWDIRHINT")); - bDir->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); - bCateg[0] = bDir->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bDir)); - buttonBar->pack_start (*bDir, Gtk::PACK_SHRINK); - buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); - - bUnRanked = new Gtk::ToggleButton (); - bUnRanked->set_active (false); - bUnRanked->set_image (*(new Gtk::Image (argv0+"/images/unrated.png"))); - bUnRanked->set_relief (Gtk::RELIEF_NONE); - bUnRanked->set_tooltip_markup (M("FILEBROWSER_SHOWUNRANKHINT")); - bCateg[1] = bUnRanked->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bUnRanked)); - buttonBar->pack_start (*bUnRanked, Gtk::PACK_SHRINK); - bUnRanked->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); - - for (int i=0; i<5; i++) { - iranked[i] = new Gtk::Image (argv0+"/images/rated.png"); - igranked[i] = new Gtk::Image (argv0+"/images/grayrated.png"); - iranked[i]->show (); - igranked[i]->show (); - bRank[i] = new Gtk::ToggleButton (); - bRank[i]->set_image (*igranked[i]); - bRank[i]->set_relief (Gtk::RELIEF_NONE); - buttonBar->pack_start (*bRank[i], Gtk::PACK_SHRINK); - bCateg[i+2] = bRank[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRank[i])); - bRank[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); - } - bRank[0]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK1HINT")); - bRank[1]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK2HINT")); - bRank[2]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK3HINT")); - bRank[3]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK4HINT")); - bRank[4]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK5HINT")); - buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); - - iTrashEmpty = new Gtk::Image(argv0+"/images/trash-show-empty.png"); - iTrashFull = new Gtk::Image(argv0+"/images/trash-show-full.png"); - - bTrash = new Gtk::ToggleButton (); - bTrash->set_image (*iTrashEmpty); - bTrash->set_relief (Gtk::RELIEF_NONE); - bTrash->set_tooltip_markup (M("FILEBROWSER_SHOWTRASHHINT")); - bCateg[7] = bTrash->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bTrash)); - bTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); - buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK); - buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); - fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) ); - - categoryButtons[0] = bDir; - categoryButtons[1] = bUnRanked; - for (int i=0; i<5; i++) - categoryButtons[i+2] = bRank[i]; - categoryButtons[7] = bTrash; - - exifInfo = Gtk::manage(new Gtk::ToggleButton ()); - exifInfo->set_image (*(new Gtk::Image (argv0+"/images/info.png"))); - exifInfo->set_relief (Gtk::RELIEF_NONE); - exifInfo->set_tooltip_markup (M("FILEBROWSER_SHOWEXIFINFO")); - exifInfo->set_active( options.showFileNames ); - exifInfo->signal_toggled().connect(sigc::mem_fun(*this, &FileCatalog::exifInfoButtonToggled)); - buttonBar->pack_start (*exifInfo, Gtk::PACK_SHRINK); - - // thumbnail zoom - Gtk::HBox* zoomBox = new Gtk::HBox (); - zoomInButton = new Gtk::Button (); - zoomInButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); - zoomInButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomIn)); - zoomInButton->set_relief (Gtk::RELIEF_NONE); - zoomInButton->set_tooltip_markup (M("FILEBROWSER_ZOOMINHINT")); - zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); - zoomOutButton = new Gtk::Button (); - zoomOutButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); - zoomOutButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomOut)); - zoomOutButton->set_relief (Gtk::RELIEF_NONE); - zoomOutButton->set_tooltip_markup (M("FILEBROWSER_ZOOMOUTHINT")); - zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); - - // add default panel - hBox = new Gtk::HBox (); - hBox->show (); - hBox->pack_end (*fileBrowser); - fileBrowser->applyFilter (getFilter()); - pack_start (*hBox); - - buttonBar2 = new Gtk::HBox (); - pack_end (*buttonBar2, Gtk::PACK_SHRINK); - progressBar = new Gtk::ProgressBar (); - buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4); - progressBar->set_size_request (-1, 16); - - buttonBar->pack_start (*zoomBox, Gtk::PACK_SHRINK); - - buttonBar->pack_end (*coarsePanel, Gtk::PACK_SHRINK); - buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - buttonBar->pack_end (*toolBar, Gtk::PACK_SHRINK); - buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - - enabled = true; - - lastScrollPos = 0; - for (int i=0; i<8; i++) { - hScrollPos[i] = 0; - vScrollPos[i] = 0; - } - - selectedDirectory = ""; -#ifdef _WIN32 - wdMonitor = NULL; - checkCounter = 2; - g_timeout_add (CHECKTIME, _directoryUpdater, this); -#endif -} - -bool FileCatalog::capture_event(GdkEventButton* event){ - // need to record modifiers on the button press, because signal_toggled does not pass the event. - modifierKey = event->state; - return false; -} - -void FileCatalog::exifInfoButtonToggled() -{ - options.showFileNames = exifInfo->get_active(); - fileBrowser->refreshThumbImages (); -} - -void FileCatalog::on_realize() { - - Gtk::VBox::on_realize(); - Pango::FontDescription fontd = get_pango_context()->get_font_description (); - fileBrowser->get_pango_context()->set_font_description (fontd); -// batchQueue->get_pango_context()->set_font_description (fontd); -} - -void FileCatalog::closeDir () { - - if (filterPanel) - filterPanel->set_sensitive (false); - -#ifndef _WIN32 - if (dirMonitor) - dirMonitor->cancel (); -#else - if (wdMonitor) { - delete wdMonitor; - wdMonitor = NULL; - } -#endif - // terminate thumbnail preview loading - previewLoader.terminate (); - - // terminate thumbnail updater - thumbImageUpdater.terminate (); - - // remove entries - fileBrowser->close (); - fileNameList.clear (); - - dirEFS.clear (); - hasValidCurrentEFS = false; - selectedDirectory = ""; - redrawAll (); -} - -std::vector FileCatalog::getFileList () { - - std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (selectedDirectory); - safe_build_file_list (dir, names, selectedDirectory); - return names; -} - -void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { - - try { - Glib::RefPtr dir = Gio::File::create_for_path (dirname); - - if (!dir) - return; - closeDir (); - previewsToLoad = 0; - previewsLoaded = 0; - // if openfile exists, we have to open it first (it is a command line argument) - if (openfile!="") - addAndOpenFile (openfile); - - selectedDirectory = dir->get_parse_name(); - fileNameList = getFileList (); - - for (unsigned int i=0; i f = Gio::File::create_for_path(fileNameList[i]); - if (f->get_parse_name() != openfile) // if we opened a file at the beginning don't add it again - checkAndAddFile (f); - } - - _refreshProgressBar (); - previewLoader.process (); - -#ifdef _WIN32 - wdMonitor = new WinDirMonitor (selectedDirectory, this); -#elif defined __APPLE__ - printf("TODO fix dir->monitor_directory () for OSX\n"); -#else - dirMonitor = dir->monitor_directory (); - dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false)); -#endif - } - catch (Glib::Exception& ex) { - std::cout << ex.what(); - } -} - -void FileCatalog::_refreshProgressBar () { - - // check if progress bar is visible -/* Glib::ListHandle list = buttonBar2->get_children (); - Glib::ListHandle::iterator i = list.begin (); - for (; i!=list.end() && *i!=progressBar; i++); - if (i==list.end()) { - buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4); - buttonBar2->reorder_child (*progressBar, 2); - } -*/ - progressBar->show (); - if (previewsToLoad>0) - progressBar->set_fraction ((double)previewsLoaded / previewsToLoad); - else - progressBar->set_fraction (1.0); -} - -int refreshpb (void* data) { - - gdk_threads_enter (); - ((FileCatalog*)data)->_refreshProgressBar (); - gdk_threads_leave (); - return 0; -} - -void FileCatalog::previewReady (FileBrowserEntry* fdn) { - - // put it into the "full directory" browser - fdn->setImageAreaToolListener (iatlistener); - fileBrowser->addEntry (fdn); - - // update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...) - const CacheImageData* cfs = fdn->thumbnail->getCacheImageData(); - if (cfs->exifValid) { - if (cfs->fnumber < dirEFS.fnumberFrom) - dirEFS.fnumberFrom = cfs->fnumber; - if (cfs->fnumber > dirEFS.fnumberTo) - dirEFS.fnumberTo = cfs->fnumber; - if (cfs->shutter < dirEFS.shutterFrom) - dirEFS.shutterFrom = cfs->shutter; - if (cfs->shutter > dirEFS.shutterTo) - dirEFS.shutterTo = cfs->shutter; - if (cfs->iso>0 && (int)cfs->iso < dirEFS.isoFrom) - dirEFS.isoFrom = (int)cfs->iso; - if (cfs->iso>0 && (int)cfs->iso > dirEFS.isoTo) - dirEFS.isoTo = (int)cfs->iso; - if (cfs->focalLen < dirEFS.focalFrom) - dirEFS.focalFrom = cfs->focalLen; - if (cfs->focalLen > dirEFS.focalTo) - dirEFS.focalTo = cfs->focalLen; - } - dirEFS.cameras.insert (cfs->camera); - dirEFS.lenses.insert (cfs->lens); - previewsLoaded++; - g_idle_add (refreshpb, this); -} - -int prevfinished (void* data) { - - gdk_threads_enter(); - ((FileCatalog*)data)->_previewsFinished (); - gdk_threads_leave(); - return 0; -} - -void FileCatalog::_previewsFinished () { - - redrawAll (); - previewsToLoad = 0; - previewsLoaded = 0; -// removeIfThere (buttonBar2, progressBar); - progressBar->hide (); - if (filterPanel) { - filterPanel->set_sensitive (true); - if ( !hasValidCurrentEFS ){ - currentEFS = dirEFS; - filterPanel->setFilter ( dirEFS,true ); - }else { - filterPanel->setFilter ( currentEFS,false ); - } - } -} - -void FileCatalog::previewsFinished () { - - if (!hasValidCurrentEFS) - currentEFS = dirEFS; - g_idle_add (prevfinished, this); -} - -void PreviewLoader::remove (Glib::ustring fname) { - std::list::iterator i; - for (i=jqueue.begin(); i!=jqueue.end(); i++) - if (i->fullName==fname) - break; - if (i!=jqueue.end()) - jqueue.erase (i); -} - -void PreviewLoader::start () { - - jqueue.sort (); -} - -void PreviewLoader::process (DirEntry& current) { - - if (Glib::file_test (current.fullName, Glib::FILE_TEST_EXISTS)) { - Thumbnail* tmb = cacheMgr.getEntry (current.fullName); - if (tmb && pl) - pl->previewReady (new FileBrowserEntry (tmb, current.fullName)); - } -} - -void PreviewLoader::end () { - - if (pl) - pl->previewsFinished (); -} - -void FileCatalog::setEnabled (bool e) { - - enabled = e; -} - -void FileCatalog::redrawAll () { - - fileBrowser->queue_draw (); -} - -void FileCatalog::refreshAll () { - - fileBrowser->refreshThumbImages (); -} - -void FileCatalog::_openImage (std::vector tmb) { - - if (enabled && listener!=NULL) { - previewLoader.stop (); - thumbImageUpdater.stop (); - for (size_t i=0; igetFileName())==editedFiles.end()) - listener->fileSelected (tmb[i]); - tmb[i]->decreaseRef (); - } - previewLoader.process (); - thumbImageUpdater.process (); - } -} - -struct FCOIParams { - FileCatalog* catalog; - std::vector tmb; -}; - -int fcopenimg (void* p) { - - gdk_threads_enter (); - FCOIParams* params = (FCOIParams*)p; - params->catalog->_openImage (params->tmb); - delete params; - gdk_threads_leave (); - return 0; -} - -void FileCatalog::openRequested (std::vector tmb) { - - FCOIParams* params = new FCOIParams; - params->catalog = this; - params->tmb = tmb; - for (size_t i=0; iincreaseRef (); - g_idle_add (fcopenimg, params); -} - -void FileCatalog::deleteRequested (std::vector tbe) { - - if (tbe.size()==0) - return; - - Gtk::MessageDialog msd (M("FILEBROWSER_DELETEDLGLABEL"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true); - msd.set_secondary_text(Glib::ustring::compose (M("FILEBROWSER_DELETEDLGMSG"), tbe.size())); - - if (msd.run()==Gtk::RESPONSE_YES) { - for (unsigned int i=0; ifilename; - // remove from browser - FileBrowserEntry* t = fileBrowser->delEntry (fname); -// t->thumbnail->decreaseRef (); - delete t; - // remove from cache - cacheMgr.deleteEntry (fname); - // delete from file system - ::g_remove (fname.c_str()); - // delete paramfile if found - ::g_remove (Glib::ustring(fname+paramFileExtension).c_str()); - ::g_remove (Glib::ustring(removeExtension(fname)+paramFileExtension).c_str()); - // delete .thm file - ::g_remove (Glib::ustring(removeExtension(fname)+".thm").c_str()); - ::g_remove (Glib::ustring(removeExtension(fname)+".THM").c_str()); - } - redrawAll (); - } -} - -void FileCatalog::developRequested (std::vector tbe) { - - if (listener) { - thumbImageUpdater.stop (); - for (size_t i=0; ithumbnail->getProcParams(); - rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (tbe[i]->filename, tbe[i]->thumbnail->getType()==FT_Raw, params); - double tmpscale; - rtengine::IImage8* img = tbe[i]->thumbnail->processThumbImage (params, options.maxThumbnailHeight, tmpscale); - if (img) { - int pw = img->getWidth (); - int ph = img->getHeight (); - guint8* prev = new guint8 [pw*ph*3]; - memcpy (prev, img->getData (), pw*ph*3); - img->free(); - listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, prev, pw, ph, tbe[i]->thumbnail)); - } - else { - int pw, ph; - tbe[i]->thumbnail->getThumbnailSize (pw, ph); - listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, NULL, pw, ph, tbe[i]->thumbnail)); - } - } - thumbImageUpdater.process (); - } -} - -void FileCatalog::renameRequested (std::vector tbe) { - - RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel()); - - for (size_t i=0; iinitName (Glib::path_get_basename (tbe[i]->filename), tbe[i]->thumbnail->getCacheImageData()); - - Glib::ustring ofname = tbe[i]->filename; - Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); - Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - - if (renameDlg->run ()== Gtk::RESPONSE_OK) { - Glib::ustring nBaseName = renameDlg->getNewName (); - // if path has directory components, exit - if (Glib::path_get_dirname (nBaseName) != ".") - continue; - // if no extension is given, concatenate the extension of the original file - Glib::ustring ext = getExtension (nBaseName); - if (ext=="") - nBaseName += "." + getExtension (baseName); - Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); - if (!::g_rename (ofname.c_str(), nfname.c_str())) { - cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - reparseDirectory (); - } - renameDlg->hide (); - } - } - delete renameDlg; -/* // ask for new file name - Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true); - - dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); - dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - - Gtk::Label l; - dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK); - - Gtk::Entry nfentry; - - dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK); - dialog.get_vbox()->show_all (); - - nfentry.set_activates_default (true); - dialog.set_default_response (Gtk::RESPONSE_OK); - - for (int i=0; ifilename; - Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); - Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - - l.set_markup (Glib::ustring("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); - nfentry.set_text (baseName); - nfentry.select_region (0, baseName.size()); - - if (dialog.run ()== Gtk::RESPONSE_OK) { - Glib::ustring nBaseName = nfentry.get_text (); - // if path has directory components, exit - if (Glib::path_get_dirname (nBaseName) != ".") - continue; - // if no extension is given, concatenate the extension of the original file - if (nBaseName.find ('.')==nBaseName.npos) { - int lastdot = baseName.find_last_of ('.'); - nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : ""); - } - Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); - if (!::g_rename (ofname.c_str(), nfname.c_str())) { - cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - // the remaining part (removing old and adding new entry) is done by the directory monitor - reparseDirectory (); -// on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true); - } - } - } - */ -} - -void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b) { - - //was control key pressed - bool control_down = modifierKey & GDK_CONTROL_MASK; - - //was shift key pressed - bool shift_down = modifierKey & GDK_SHIFT_MASK; - - for (int i=0; i<8; i++) - bCateg[i].block (true); - - //button is already toggled when entering this function, so we switch it back to its initial state - b->set_active(!b->get_active()); - - //if both control and shift keys were pressed, do nothing - if (!(control_down && shift_down)) { - - fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); - - //we look how many stars are already toggled on, if any - int toggled_stars_count=0, buttons=0, start_star=0, toggled_button=0; - - for (int i=0; i<8; i++) { - if (categoryButtons[i]->get_active()) { - if (i>0 && i<7) { - toggled_stars_count ++; - start_star = i; - } - buttons |= (1 << i); - } - if (categoryButtons[i] == b) toggled_button = i; - } - - //if no modifier key were pressed, we can switch-on the button, and clear all others - if (!(control_down || shift_down)) { - for (int i=0; i<8; i++) { - categoryButtons[i]->set_active (i==toggled_button); - } - } - //modifier key allowed only for stars - else if (toggled_button>0 && toggled_button<7) { - if (control_down) { - //control is pressed - if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) { - //we're deselecting the only star still active, so we activate the folder filter - categoryButtons[0]->set_active(true); - //and we deselect the toggled star - categoryButtons[toggled_button]->set_active (false); - } - else if (toggled_stars_count >= 1) { - //we toggle the state of a star (eventually another one than the only one selected) - categoryButtons[toggled_button]->set_active(!categoryButtons[toggled_button]->get_active()); - } - else { - //no star selected - //we deselect the 2 non star filters - if (buttons & 1 ) categoryButtons[0]->set_active(false); - if (buttons & (1 << 7)) categoryButtons[7]->set_active(false); - //and we toggle on the star - categoryButtons[toggled_button]->set_active (true); - } - } - else { - //shift is pressed, only allowed if 0 or 1 star is selected - if (!toggled_stars_count) { - //we deselect the 2 non star filters - if (buttons & 1 ) categoryButtons[0]->set_active(false); - if (buttons & (1 << 7)) categoryButtons[7]->set_active(false); - //and we set the start star to 1 (unrated images) - start_star = 1; - //we act as if one star were selected - toggled_stars_count = 1; - } - if (toggled_stars_count == 1) { - int current_star=MIN(start_star,toggled_button); - int last_star =MAX(start_star,toggled_button); - //we permute the start and the end star for the next loop - for (; current_star <= last_star; current_star++) { - //we toggle on all the star in the range - if (!(buttons & (1 << current_star))) categoryButtons[current_star]->set_active(true); - } - } - //if more than one star selected, do nothing - } - } - - //so set the right images - for (int i=0; i<5; i++) { - bool active_now, active_before; - active_now = bRank[i]->get_active(); - active_before = buttons & (1 << (i+2)); - if ( active_now && !active_before) bRank[i]->set_image (*iranked[i]); - else if (!active_now && active_before) bRank[i]->set_image (*igranked[i]); - } - - fileBrowser->applyFilter (getFilter ()); - - //rearrange panels according to the selected filter - removeIfThere (hBox, trashButtonBox); - if (bTrash->get_active ()) - hBox->pack_start (*trashButtonBox, Gtk::PACK_SHRINK, 4); - hBox->queue_draw (); - - fileBrowser->setScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); - } - - for (int i=0; i<8; i++) - bCateg[i].block (false); -} - -BrowserFilter FileCatalog::getFilter () { - - BrowserFilter filter; - filter.showRanked[0] = bDir->get_active() || bUnRanked->get_active () || bTrash->get_active (); - for (int i=1; i<=5; i++) - filter.showRanked[i] = bDir->get_active() || bRank[i-1]->get_active () || bTrash->get_active (); - filter.showTrash = bDir->get_active() || bTrash->get_active (); - filter.showNotTrash = !bTrash->get_active (); - if (!filterPanel) - filter.exifFilterEnabled = false; - else { - if (!hasValidCurrentEFS) - filter.exifFilter = dirEFS; - else - filter.exifFilter = currentEFS; - filter.exifFilterEnabled = filterPanel->isEnabled (); - } - return filter; -} - -void FileCatalog::filterChanged () { - - fileBrowser->applyFilter (getFilter()); -} - -int FileCatalog::reparseDirectory () { - - if (selectedDirectory=="") - return 0; - - if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { - closeDir (); - return 0; - } - - std::vector nfileNameList = getFileList (); - - // check if a thumbnailed file has been deleted - const std::vector& t = fileBrowser->getEntries (); - std::vector fileNamesToDel; - for (size_t i=0; ifilename, Glib::FILE_TEST_EXISTS)) - fileNamesToDel.push_back (t[i]->filename); - for (size_t i=0; idelEntry (fileNamesToDel[i]); - cacheMgr.deleteEntry (fileNamesToDel[i]); - } - - // check if a new file has been added - for (size_t i=0; i& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) { - - if (!internal) - gdk_threads_enter(); - - if (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED) - reparseDirectory (); - - if (!internal) - gdk_threads_leave(); -} - -void FileCatalog::checkAndAddFile (Glib::RefPtr file) { - - if (!file ) - return; - if( !file->query_exists()) - return; - Glib::RefPtr info = safe_query_file_info(file); - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - int lastdot = info->get_name().find_last_of ('.'); - if (options.is_extention_enabled(lastdot!=(int)Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){ - previewLoader.add (DirEntry (file->get_parse_name())); - previewsToLoad++; - } - } -} - -void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { - - Glib::RefPtr file = Gio::File::create_for_path (fname); - if (!file ) - return; - if( !file->query_exists()) - return; - Glib::RefPtr info = safe_query_file_info(file); - if( !info ) - return; - int lastdot = info->get_name().find_last_of ('.'); - if (options.is_extention_enabled(lastdot!=(int)Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){ - // if supported, load thumbnail first - Thumbnail* tmb = cacheMgr.getEntry (file->get_parse_name()); - if (tmb) { - FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name()); - previewReady (entry); - // open the file - FCOIParams* params = new FCOIParams; - params->catalog = this; - params->tmb.push_back (tmb); - tmb->increaseRef (); - g_idle_add (fcopenimg, params); - } - } -} - -void FileCatalog::emptyTrash () { - - const std::vector t = fileBrowser->getEntries (); - std::vector toDel; - for (size_t i=0; ithumbnail->getStage()==1) - toDel.push_back (((FileBrowserEntry*)t[i])); - deleteRequested (toDel); - trashChanged(); -} - -bool FileCatalog::trashIsEmpty () { - const std::vector t = fileBrowser->getEntries (); - for (size_t i=0; ithumbnail->getStage()==1) - return false; - - return true; -} - -void FileCatalog::zoomIn () { - - bool pLoad = previewLoader.runs(); - if (pLoad) - previewLoader.stop (); - - fileBrowser->zoomIn (); - - if (pLoad) - previewLoader.process (); -} -void FileCatalog::zoomOut () { - - bool pLoad = previewLoader.runs(); - if (pLoad) - previewLoader.stop (); - - fileBrowser->zoomOut (); - - if (pLoad) - previewLoader.process (); -} -void FileCatalog::refreshEditedState (const std::set& efiles) { - - editedFiles = efiles; - fileBrowser->refreshEditedState (efiles); -} - -void FileCatalog::selectionChanged (std::vector tbe) { - - if (fslistener) - fslistener->selectionChanged (tbe); -} - -void FileCatalog::exifFilterChanged () { - - currentEFS = filterPanel->getFilter (); - hasValidCurrentEFS = true; - fileBrowser->applyFilter (getFilter ()); -} - -void FileCatalog::setFilterPanel (FilterPanel* fpanel) { - - filterPanel = fpanel; - filterPanel->set_sensitive (false); - filterPanel->setFilterPanelListener (this); -} -void FileCatalog::trashChanged () { - if (trashIsEmpty()) { - bTrash->set_image(*iTrashEmpty); - } - else { - bTrash->set_image(*iTrashFull); - } -} - -bool FileCatalog::handleShortcutKey (GdkEventKey* event) { - - bool ctrl = event->state & GDK_CONTROL_MASK; - bool shift = event->state & GDK_SHIFT_MASK; - - modifierKey = event->state; - - switch(event->keyval) { - case GDK_1: - categoryButtonToggled(bRank[0]); - return true; - case GDK_2: - categoryButtonToggled(bRank[1]); - return true; - case GDK_3: - categoryButtonToggled(bRank[2]); - return true; - case GDK_4: - categoryButtonToggled(bRank[3]); - return true; - case GDK_5: - categoryButtonToggled(bRank[4]); - return true; - case GDK_grave: - categoryButtonToggled(bUnRanked); - return true; - case GDK_d: - case GDK_D: - categoryButtonToggled(bDir); - return true; - case GDK_t: - case GDK_T: - categoryButtonToggled(bTrash); - return true; - } - - if (!ctrl) { - switch(event->keyval) { - case GDK_i: - case GDK_I: - exifInfo->set_active (!exifInfo->get_active()); - return true; - case GDK_plus: - case GDK_equal: - zoomIn(); - return true; - case GDK_minus: - case GDK_underscore: - zoomOut(); - return true; - } - } - else { - switch (event->keyval) { - } - } - - return false; -} - +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHECKTIME 2000 + +extern Glib::ustring argv0; + +#ifdef _WIN32 +int _directoryUpdater (void* cat) { + + ((FileCatalog*)cat)->checkCounter++; + if (((FileCatalog*)cat)->checkCounter==2) { + gdk_threads_enter (); + ((FileCatalog*)cat)->reparseDirectory (); + gdk_threads_leave (); + } + return 1; +} +#endif + +FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb) : listener(NULL), fslistener(NULL), hasValidCurrentEFS(false), filterPanel(NULL), coarsePanel(cp), toolBar(tb) { + + previewLoader.setPreviewLoaderListener (this); + + // construct and initialize thumbnail browsers + fileBrowser = new FileBrowser(); + fileBrowser->setFileBrowserListener (this); + fileBrowser->setArrangement (ThumbBrowserBase::TB_Vertical); + fileBrowser->show (); + + set_size_request(0,250); + // construct trash panel with the extra "empty trash" button + trashButtonBox = new Gtk::VBox; + Gtk::Button* emptyT = new Gtk::Button (M("FILEBROWSER_EMPTYTRASH")); + emptyT->set_tooltip_markup (M("FILEBROWSER_EMPTYTRASHHINT")); + emptyT->set_image (*(new Gtk::Image (Gtk::StockID("gtk-delete"), Gtk::ICON_SIZE_BUTTON))); + emptyT->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::emptyTrash)); + trashButtonBox->pack_start (*emptyT, Gtk::PACK_SHRINK, 4); + emptyT->show (); + trashButtonBox->show (); + + // setup button bar + buttonBar = new Gtk::HBox (); + pack_start (*buttonBar, Gtk::PACK_SHRINK); + + buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); + bDir = new Gtk::ToggleButton (); + bDir->set_active (true); + bDir->set_image (*(new Gtk::Image (argv0+"/images/folder.png"))); + bDir->set_relief (Gtk::RELIEF_NONE); + bDir->set_tooltip_markup (M("FILEBROWSER_SHOWDIRHINT")); + bDir->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bCateg[0] = bDir->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bDir)); + buttonBar->pack_start (*bDir, Gtk::PACK_SHRINK); + buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); + + bUnRanked = new Gtk::ToggleButton (); + bUnRanked->set_active (false); + bUnRanked->set_image (*(new Gtk::Image (argv0+"/images/unrated.png"))); + bUnRanked->set_relief (Gtk::RELIEF_NONE); + bUnRanked->set_tooltip_markup (M("FILEBROWSER_SHOWUNRANKHINT")); + bCateg[1] = bUnRanked->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bUnRanked)); + buttonBar->pack_start (*bUnRanked, Gtk::PACK_SHRINK); + bUnRanked->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + + for (int i=0; i<5; i++) { + iranked[i] = new Gtk::Image (argv0+"/images/rated.png"); + igranked[i] = new Gtk::Image (argv0+"/images/grayrated.png"); + iranked[i]->show (); + igranked[i]->show (); + bRank[i] = new Gtk::ToggleButton (); + bRank[i]->set_image (*igranked[i]); + bRank[i]->set_relief (Gtk::RELIEF_NONE); + buttonBar->pack_start (*bRank[i], Gtk::PACK_SHRINK); + bCateg[i+2] = bRank[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRank[i])); + bRank[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + } + bRank[0]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK1HINT")); + bRank[1]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK2HINT")); + bRank[2]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK3HINT")); + bRank[3]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK4HINT")); + bRank[4]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK5HINT")); + buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); + + iTrashEmpty = new Gtk::Image(argv0+"/images/trash-show-empty.png"); + iTrashFull = new Gtk::Image(argv0+"/images/trash-show-full.png"); + + bTrash = new Gtk::ToggleButton (); + bTrash->set_image (*iTrashEmpty); + bTrash->set_relief (Gtk::RELIEF_NONE); + bTrash->set_tooltip_markup (M("FILEBROWSER_SHOWTRASHHINT")); + bCateg[7] = bTrash->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bTrash)); + bTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK); + buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK); + fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) ); + + categoryButtons[0] = bDir; + categoryButtons[1] = bUnRanked; + for (int i=0; i<5; i++) + categoryButtons[i+2] = bRank[i]; + categoryButtons[7] = bTrash; + + exifInfo = Gtk::manage(new Gtk::ToggleButton ()); + exifInfo->set_image (*(new Gtk::Image (argv0+"/images/info.png"))); + exifInfo->set_relief (Gtk::RELIEF_NONE); + exifInfo->set_tooltip_markup (M("FILEBROWSER_SHOWEXIFINFO")); + exifInfo->set_active( options.showFileNames ); + exifInfo->signal_toggled().connect(sigc::mem_fun(*this, &FileCatalog::exifInfoButtonToggled)); + buttonBar->pack_start (*exifInfo, Gtk::PACK_SHRINK); + + // thumbnail zoom + Gtk::HBox* zoomBox = new Gtk::HBox (); + zoomInButton = new Gtk::Button (); + zoomInButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); + zoomInButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomIn)); + zoomInButton->set_relief (Gtk::RELIEF_NONE); + zoomInButton->set_tooltip_markup (M("FILEBROWSER_ZOOMINHINT")); + zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); + zoomOutButton = new Gtk::Button (); + zoomOutButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); + zoomOutButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomOut)); + zoomOutButton->set_relief (Gtk::RELIEF_NONE); + zoomOutButton->set_tooltip_markup (M("FILEBROWSER_ZOOMOUTHINT")); + zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); + + // add default panel + hBox = new Gtk::HBox (); + hBox->show (); + hBox->pack_end (*fileBrowser); + fileBrowser->applyFilter (getFilter()); + pack_start (*hBox); + + buttonBar2 = new Gtk::HBox (); + pack_end (*buttonBar2, Gtk::PACK_SHRINK); + progressBar = new Gtk::ProgressBar (); + buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4); + progressBar->set_size_request (-1, 16); + + buttonBar->pack_start (*zoomBox, Gtk::PACK_SHRINK); + + buttonBar->pack_end (*coarsePanel, Gtk::PACK_SHRINK); + buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); + buttonBar->pack_end (*toolBar, Gtk::PACK_SHRINK); + buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); + + enabled = true; + + lastScrollPos = 0; + for (int i=0; i<8; i++) { + hScrollPos[i] = 0; + vScrollPos[i] = 0; + } + + selectedDirectory = ""; +#ifdef _WIN32 + wdMonitor = NULL; + checkCounter = 2; + g_timeout_add (CHECKTIME, _directoryUpdater, this); +#endif +} + +bool FileCatalog::capture_event(GdkEventButton* event){ + // need to record modifiers on the button press, because signal_toggled does not pass the event. + modifierKey = event->state; + return false; +} + +void FileCatalog::exifInfoButtonToggled() +{ + options.showFileNames = exifInfo->get_active(); + fileBrowser->refreshThumbImages (); +} + +void FileCatalog::on_realize() { + + Gtk::VBox::on_realize(); + Pango::FontDescription fontd = get_pango_context()->get_font_description (); + fileBrowser->get_pango_context()->set_font_description (fontd); +// batchQueue->get_pango_context()->set_font_description (fontd); +} + +void FileCatalog::closeDir () { + + if (filterPanel) + filterPanel->set_sensitive (false); + +#ifndef _WIN32 + if (dirMonitor) + dirMonitor->cancel (); +#else + if (wdMonitor) { + delete wdMonitor; + wdMonitor = NULL; + } +#endif + // terminate thumbnail preview loading + previewLoader.terminate (); + + // terminate thumbnail updater + thumbImageUpdater.terminate (); + + // remove entries + fileBrowser->close (); + fileNameList.clear (); + + dirEFS.clear (); + hasValidCurrentEFS = false; + selectedDirectory = ""; + redrawAll (); +} + +std::vector FileCatalog::getFileList () { + + std::vector names; + Glib::RefPtr dir = Gio::File::create_for_path (selectedDirectory); + safe_build_file_list (dir, names, selectedDirectory); + return names; +} + +void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { + + try { + Glib::RefPtr dir = Gio::File::create_for_path (dirname); + + if (!dir) + return; + closeDir (); + previewsToLoad = 0; + previewsLoaded = 0; + // if openfile exists, we have to open it first (it is a command line argument) + if (openfile!="") + addAndOpenFile (openfile); + + selectedDirectory = dir->get_parse_name(); + fileNameList = getFileList (); + + for (unsigned int i=0; i f = Gio::File::create_for_path(fileNameList[i]); + if (f->get_parse_name() != openfile) // if we opened a file at the beginning don't add it again + checkAndAddFile (f); + } + + _refreshProgressBar (); + previewLoader.process (); + +#ifdef _WIN32 + wdMonitor = new WinDirMonitor (selectedDirectory, this); +#elif defined __APPLE__ + printf("TODO fix dir->monitor_directory () for OSX\n"); +#else + dirMonitor = dir->monitor_directory (); + dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false)); +#endif + } + catch (Glib::Exception& ex) { + std::cout << ex.what(); + } +} + +void FileCatalog::_refreshProgressBar () { + + // check if progress bar is visible +/* Glib::ListHandle list = buttonBar2->get_children (); + Glib::ListHandle::iterator i = list.begin (); + for (; i!=list.end() && *i!=progressBar; i++); + if (i==list.end()) { + buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4); + buttonBar2->reorder_child (*progressBar, 2); + } +*/ + progressBar->show (); + if (previewsToLoad>0) + progressBar->set_fraction ((double)previewsLoaded / previewsToLoad); + else + progressBar->set_fraction (1.0); +} + +int refreshpb (void* data) { + + gdk_threads_enter (); + ((FileCatalog*)data)->_refreshProgressBar (); + gdk_threads_leave (); + return 0; +} + +void FileCatalog::previewReady (FileBrowserEntry* fdn) { + + // put it into the "full directory" browser + fdn->setImageAreaToolListener (iatlistener); + fileBrowser->addEntry (fdn); + + // update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...) + const CacheImageData* cfs = fdn->thumbnail->getCacheImageData(); + if (cfs->exifValid) { + if (cfs->fnumber < dirEFS.fnumberFrom) + dirEFS.fnumberFrom = cfs->fnumber; + if (cfs->fnumber > dirEFS.fnumberTo) + dirEFS.fnumberTo = cfs->fnumber; + if (cfs->shutter < dirEFS.shutterFrom) + dirEFS.shutterFrom = cfs->shutter; + if (cfs->shutter > dirEFS.shutterTo) + dirEFS.shutterTo = cfs->shutter; + if (cfs->iso>0 && (int)cfs->iso < dirEFS.isoFrom) + dirEFS.isoFrom = (int)cfs->iso; + if (cfs->iso>0 && (int)cfs->iso > dirEFS.isoTo) + dirEFS.isoTo = (int)cfs->iso; + if (cfs->focalLen < dirEFS.focalFrom) + dirEFS.focalFrom = cfs->focalLen; + if (cfs->focalLen > dirEFS.focalTo) + dirEFS.focalTo = cfs->focalLen; + } + dirEFS.cameras.insert (cfs->camera); + dirEFS.lenses.insert (cfs->lens); + previewsLoaded++; + g_idle_add (refreshpb, this); +} + +int prevfinished (void* data) { + + gdk_threads_enter(); + ((FileCatalog*)data)->_previewsFinished (); + gdk_threads_leave(); + return 0; +} + +void FileCatalog::_previewsFinished () { + + redrawAll (); + previewsToLoad = 0; + previewsLoaded = 0; +// removeIfThere (buttonBar2, progressBar); + progressBar->hide (); + if (filterPanel) { + filterPanel->set_sensitive (true); + if ( !hasValidCurrentEFS ){ + currentEFS = dirEFS; + filterPanel->setFilter ( dirEFS,true ); + }else { + filterPanel->setFilter ( currentEFS,false ); + } + } +} + +void FileCatalog::previewsFinished () { + + if (!hasValidCurrentEFS) + currentEFS = dirEFS; + g_idle_add (prevfinished, this); +} + +void PreviewLoader::remove (Glib::ustring fname) { + std::list::iterator i; + for (i=jqueue.begin(); i!=jqueue.end(); i++) + if (i->fullName==fname) + break; + if (i!=jqueue.end()) + jqueue.erase (i); +} + +void PreviewLoader::start () { + + jqueue.sort (); +} + +void PreviewLoader::process (DirEntry& current) { + + if (Glib::file_test (current.fullName, Glib::FILE_TEST_EXISTS)) { + Thumbnail* tmb = cacheMgr.getEntry (current.fullName); + if (tmb && pl) + pl->previewReady (new FileBrowserEntry (tmb, current.fullName)); + } +} + +void PreviewLoader::end () { + + if (pl) + pl->previewsFinished (); +} + +void FileCatalog::setEnabled (bool e) { + + enabled = e; +} + +void FileCatalog::redrawAll () { + + fileBrowser->queue_draw (); +} + +void FileCatalog::refreshAll () { + + fileBrowser->refreshThumbImages (); +} + +void FileCatalog::_openImage (std::vector tmb) { + + if (enabled && listener!=NULL) { + previewLoader.stop (); + thumbImageUpdater.stop (); + for (size_t i=0; igetFileName())==editedFiles.end()) + listener->fileSelected (tmb[i]); + tmb[i]->decreaseRef (); + } + previewLoader.process (); + thumbImageUpdater.process (); + } +} + +struct FCOIParams { + FileCatalog* catalog; + std::vector tmb; +}; + +int fcopenimg (void* p) { + + gdk_threads_enter (); + FCOIParams* params = (FCOIParams*)p; + params->catalog->_openImage (params->tmb); + delete params; + gdk_threads_leave (); + return 0; +} + +void FileCatalog::openRequested (std::vector tmb) { + + FCOIParams* params = new FCOIParams; + params->catalog = this; + params->tmb = tmb; + for (size_t i=0; iincreaseRef (); + g_idle_add (fcopenimg, params); +} + +void FileCatalog::deleteRequested (std::vector tbe) { + + if (tbe.size()==0) + return; + + Gtk::MessageDialog msd (M("FILEBROWSER_DELETEDLGLABEL"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true); + msd.set_secondary_text(Glib::ustring::compose (M("FILEBROWSER_DELETEDLGMSG"), tbe.size())); + + if (msd.run()==Gtk::RESPONSE_YES) { + for (unsigned int i=0; ifilename; + // remove from browser + FileBrowserEntry* t = fileBrowser->delEntry (fname); +// t->thumbnail->decreaseRef (); + delete t; + // remove from cache + cacheMgr.deleteEntry (fname); + // delete from file system + ::g_remove (fname.c_str()); + // delete paramfile if found + ::g_remove (Glib::ustring(fname+paramFileExtension).c_str()); + ::g_remove (Glib::ustring(removeExtension(fname)+paramFileExtension).c_str()); + // delete .thm file + ::g_remove (Glib::ustring(removeExtension(fname)+".thm").c_str()); + ::g_remove (Glib::ustring(removeExtension(fname)+".THM").c_str()); + } + redrawAll (); + } +} + +void FileCatalog::developRequested (std::vector tbe) { + + if (listener) { + thumbImageUpdater.stop (); + for (size_t i=0; ithumbnail->getProcParams(); + rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (tbe[i]->filename, tbe[i]->thumbnail->getType()==FT_Raw, params); + double tmpscale; + rtengine::IImage8* img = tbe[i]->thumbnail->processThumbImage (params, options.maxThumbnailHeight, tmpscale); + if (img) { + int pw = img->getWidth (); + int ph = img->getHeight (); + guint8* prev = new guint8 [pw*ph*3]; + memcpy (prev, img->getData (), pw*ph*3); + img->free(); + listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, prev, pw, ph, tbe[i]->thumbnail)); + } + else { + int pw, ph; + tbe[i]->thumbnail->getThumbnailSize (pw, ph); + listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, NULL, pw, ph, tbe[i]->thumbnail)); + } + } + thumbImageUpdater.process (); + } +} + +void FileCatalog::renameRequested (std::vector tbe) { + + RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel()); + + for (size_t i=0; iinitName (Glib::path_get_basename (tbe[i]->filename), tbe[i]->thumbnail->getCacheImageData()); + + Glib::ustring ofname = tbe[i]->filename; + Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); + Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); + + if (renameDlg->run ()== Gtk::RESPONSE_OK) { + Glib::ustring nBaseName = renameDlg->getNewName (); + // if path has directory components, exit + if (Glib::path_get_dirname (nBaseName) != ".") + continue; + // if no extension is given, concatenate the extension of the original file + Glib::ustring ext = getExtension (nBaseName); + if (ext=="") + nBaseName += "." + getExtension (baseName); + Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); + if (!::g_rename (ofname.c_str(), nfname.c_str())) { + cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); + reparseDirectory (); + } + renameDlg->hide (); + } + } + delete renameDlg; +/* // ask for new file name + Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true); + + dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + + Gtk::Label l; + dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK); + + Gtk::Entry nfentry; + + dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK); + dialog.get_vbox()->show_all (); + + nfentry.set_activates_default (true); + dialog.set_default_response (Gtk::RESPONSE_OK); + + for (int i=0; ifilename; + Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); + Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); + + l.set_markup (Glib::ustring("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); + nfentry.set_text (baseName); + nfentry.select_region (0, baseName.size()); + + if (dialog.run ()== Gtk::RESPONSE_OK) { + Glib::ustring nBaseName = nfentry.get_text (); + // if path has directory components, exit + if (Glib::path_get_dirname (nBaseName) != ".") + continue; + // if no extension is given, concatenate the extension of the original file + if (nBaseName.find ('.')==nBaseName.npos) { + int lastdot = baseName.find_last_of ('.'); + nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : ""); + } + Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); + if (!::g_rename (ofname.c_str(), nfname.c_str())) { + cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); + // the remaining part (removing old and adding new entry) is done by the directory monitor + reparseDirectory (); +// on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true); + } + } + } + */ +} + +void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b) { + + //was control key pressed + bool control_down = modifierKey & GDK_CONTROL_MASK; + + //was shift key pressed + bool shift_down = modifierKey & GDK_SHIFT_MASK; + + for (int i=0; i<8; i++) + bCateg[i].block (true); + + //button is already toggled when entering this function, so we switch it back to its initial state + b->set_active(!b->get_active()); + + //if both control and shift keys were pressed, do nothing + if (!(control_down && shift_down)) { + + fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); + + //we look how many stars are already toggled on, if any + int toggled_stars_count=0, buttons=0, start_star=0, toggled_button=0; + + for (int i=0; i<8; i++) { + if (categoryButtons[i]->get_active()) { + if (i>0 && i<7) { + toggled_stars_count ++; + start_star = i; + } + buttons |= (1 << i); + } + if (categoryButtons[i] == b) toggled_button = i; + } + + //if no modifier key were pressed, we can switch-on the button, and clear all others + if (!(control_down || shift_down)) { + for (int i=0; i<8; i++) { + categoryButtons[i]->set_active (i==toggled_button); + } + } + //modifier key allowed only for stars + else if (toggled_button>0 && toggled_button<7) { + if (control_down) { + //control is pressed + if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) { + //we're deselecting the only star still active, so we activate the folder filter + categoryButtons[0]->set_active(true); + //and we deselect the toggled star + categoryButtons[toggled_button]->set_active (false); + } + else if (toggled_stars_count >= 1) { + //we toggle the state of a star (eventually another one than the only one selected) + categoryButtons[toggled_button]->set_active(!categoryButtons[toggled_button]->get_active()); + } + else { + //no star selected + //we deselect the 2 non star filters + if (buttons & 1 ) categoryButtons[0]->set_active(false); + if (buttons & (1 << 7)) categoryButtons[7]->set_active(false); + //and we toggle on the star + categoryButtons[toggled_button]->set_active (true); + } + } + else { + //shift is pressed, only allowed if 0 or 1 star is selected + if (!toggled_stars_count) { + //we deselect the 2 non star filters + if (buttons & 1 ) categoryButtons[0]->set_active(false); + if (buttons & (1 << 7)) categoryButtons[7]->set_active(false); + //and we set the start star to 1 (unrated images) + start_star = 1; + //we act as if one star were selected + toggled_stars_count = 1; + } + if (toggled_stars_count == 1) { + int current_star=MIN(start_star,toggled_button); + int last_star =MAX(start_star,toggled_button); + //we permute the start and the end star for the next loop + for (; current_star <= last_star; current_star++) { + //we toggle on all the star in the range + if (!(buttons & (1 << current_star))) categoryButtons[current_star]->set_active(true); + } + } + //if more than one star selected, do nothing + } + } + + //so set the right images + for (int i=0; i<5; i++) { + bool active_now, active_before; + active_now = bRank[i]->get_active(); + active_before = buttons & (1 << (i+2)); + if ( active_now && !active_before) bRank[i]->set_image (*iranked[i]); + else if (!active_now && active_before) bRank[i]->set_image (*igranked[i]); + } + + fileBrowser->applyFilter (getFilter ()); + + //rearrange panels according to the selected filter + removeIfThere (hBox, trashButtonBox); + if (bTrash->get_active ()) + hBox->pack_start (*trashButtonBox, Gtk::PACK_SHRINK, 4); + hBox->queue_draw (); + + fileBrowser->setScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); + } + + for (int i=0; i<8; i++) + bCateg[i].block (false); +} + +BrowserFilter FileCatalog::getFilter () { + + BrowserFilter filter; + filter.showRanked[0] = bDir->get_active() || bUnRanked->get_active () || bTrash->get_active (); + for (int i=1; i<=5; i++) + filter.showRanked[i] = bDir->get_active() || bRank[i-1]->get_active () || bTrash->get_active (); + filter.showTrash = bDir->get_active() || bTrash->get_active (); + filter.showNotTrash = !bTrash->get_active (); + if (!filterPanel) + filter.exifFilterEnabled = false; + else { + if (!hasValidCurrentEFS) + filter.exifFilter = dirEFS; + else + filter.exifFilter = currentEFS; + filter.exifFilterEnabled = filterPanel->isEnabled (); + } + return filter; +} + +void FileCatalog::filterChanged () { + + fileBrowser->applyFilter (getFilter()); +} + +int FileCatalog::reparseDirectory () { + + if (selectedDirectory=="") + return 0; + + if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { + closeDir (); + return 0; + } + + std::vector nfileNameList = getFileList (); + + // check if a thumbnailed file has been deleted + const std::vector& t = fileBrowser->getEntries (); + std::vector fileNamesToDel; + for (size_t i=0; ifilename, Glib::FILE_TEST_EXISTS)) + fileNamesToDel.push_back (t[i]->filename); + for (size_t i=0; idelEntry (fileNamesToDel[i]); + cacheMgr.deleteEntry (fileNamesToDel[i]); + } + + // check if a new file has been added + for (size_t i=0; i& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) { + + if (!internal) + gdk_threads_enter(); + + if (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED) + reparseDirectory (); + + if (!internal) + gdk_threads_leave(); +} + +void FileCatalog::checkAndAddFile (Glib::RefPtr file) { + + if (!file ) + return; + if( !file->query_exists()) + return; + Glib::RefPtr info = safe_query_file_info(file); + if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { + int lastdot = info->get_name().find_last_of ('.'); + if (options.is_extention_enabled(lastdot!=(int)Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){ + previewLoader.add (DirEntry (file->get_parse_name())); + previewsToLoad++; + } + } +} + +void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { + + Glib::RefPtr file = Gio::File::create_for_path (fname); + if (!file ) + return; + if( !file->query_exists()) + return; + Glib::RefPtr info = safe_query_file_info(file); + if( !info ) + return; + int lastdot = info->get_name().find_last_of ('.'); + if (options.is_extention_enabled(lastdot!=(int)Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){ + // if supported, load thumbnail first + Thumbnail* tmb = cacheMgr.getEntry (file->get_parse_name()); + if (tmb) { + FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name()); + previewReady (entry); + // open the file + FCOIParams* params = new FCOIParams; + params->catalog = this; + params->tmb.push_back (tmb); + tmb->increaseRef (); + g_idle_add (fcopenimg, params); + } + } +} + +void FileCatalog::emptyTrash () { + + const std::vector t = fileBrowser->getEntries (); + std::vector toDel; + for (size_t i=0; ithumbnail->getStage()==1) + toDel.push_back (((FileBrowserEntry*)t[i])); + deleteRequested (toDel); + trashChanged(); +} + +bool FileCatalog::trashIsEmpty () { + const std::vector t = fileBrowser->getEntries (); + for (size_t i=0; ithumbnail->getStage()==1) + return false; + + return true; +} + +void FileCatalog::zoomIn () { + + bool pLoad = previewLoader.runs(); + if (pLoad) + previewLoader.stop (); + + fileBrowser->zoomIn (); + + if (pLoad) + previewLoader.process (); +} +void FileCatalog::zoomOut () { + + bool pLoad = previewLoader.runs(); + if (pLoad) + previewLoader.stop (); + + fileBrowser->zoomOut (); + + if (pLoad) + previewLoader.process (); +} +void FileCatalog::refreshEditedState (const std::set& efiles) { + + editedFiles = efiles; + fileBrowser->refreshEditedState (efiles); +} + +void FileCatalog::selectionChanged (std::vector tbe) { + + if (fslistener) + fslistener->selectionChanged (tbe); +} + +void FileCatalog::exifFilterChanged () { + + currentEFS = filterPanel->getFilter (); + hasValidCurrentEFS = true; + fileBrowser->applyFilter (getFilter ()); +} + +void FileCatalog::setFilterPanel (FilterPanel* fpanel) { + + filterPanel = fpanel; + filterPanel->set_sensitive (false); + filterPanel->setFilterPanelListener (this); +} +void FileCatalog::trashChanged () { + if (trashIsEmpty()) { + bTrash->set_image(*iTrashEmpty); + } + else { + bTrash->set_image(*iTrashFull); + } +} + +bool FileCatalog::handleShortcutKey (GdkEventKey* event) { + + bool ctrl = event->state & GDK_CONTROL_MASK; + bool shift = event->state & GDK_SHIFT_MASK; + + modifierKey = event->state; + + switch(event->keyval) { + case GDK_1: + categoryButtonToggled(bRank[0]); + return true; + case GDK_2: + categoryButtonToggled(bRank[1]); + return true; + case GDK_3: + categoryButtonToggled(bRank[2]); + return true; + case GDK_4: + categoryButtonToggled(bRank[3]); + return true; + case GDK_5: + categoryButtonToggled(bRank[4]); + return true; + case GDK_grave: + categoryButtonToggled(bUnRanked); + return true; + case GDK_d: + case GDK_D: + categoryButtonToggled(bDir); + return true; + case GDK_t: + case GDK_T: + categoryButtonToggled(bTrash); + return true; + } + + if (!ctrl) { + switch(event->keyval) { + case GDK_i: + case GDK_I: + exifInfo->set_active (!exifInfo->get_active()); + return true; + case GDK_plus: + case GDK_equal: + zoomIn(); + return true; + case GDK_minus: + case GDK_underscore: + zoomOut(); + return true; + } + } + else { + switch (event->keyval) { + } + } + + return false; +} + diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index a23e5b893..f7e95ac4f 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -67,7 +67,7 @@ class PreviewLoader : public ProcessingThread { void end (); }; -class FileCatalog : public Gtk::VBox, +class FileCatalog : public Gtk::VBox, public DirSelectionListener, public PreviewLoaderListener, public FilterPanelListener, @@ -77,9 +77,7 @@ class FileCatalog : public Gtk::VBox, #endif { - // thumbnail browsers - FileBrowser* fileBrowser; - + Gtk::HBox* hBox; Glib::ustring selectedDirectory; bool enabled; @@ -141,6 +139,9 @@ class FileCatalog : public Gtk::VBox, void trashChanged (); public: + // thumbnail browsers + FileBrowser* fileBrowser; + CoarsePanel* coarsePanel; ToolBar* toolBar; diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index dfe67ac77..c3d0edd9b 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -1,228 +1,244 @@ -/* - * 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 -#include - -int fbinit (void* data) { - - gdk_threads_enter (); - ((FilePanel*)data)->init (); - gdk_threads_leave (); - - return 0; -} - -FilePanel::FilePanel () : parent(NULL) { - - dirpaned = new Gtk::HPaned (); - dirpaned->set_position (options.dirBrowserWidth); - - dirBrowser = new DirBrowser (); - placesBrowser = new PlacesBrowser (); - recentBrowser = new RecentBrowser (); - - placespaned = new Gtk::VPaned (); - placespaned->set_size_request(50,100); - placespaned->set_position (options.dirBrowserHeight); - - Gtk::VBox* obox = Gtk::manage (new Gtk::VBox ()); - obox->pack_start (*recentBrowser, Gtk::PACK_SHRINK, 4); - obox->pack_start (*dirBrowser); - - placespaned->pack1 (*placesBrowser, false, true); - placespaned->pack2 (*obox, true, true); - - dirpaned->pack1 (*placespaned, false, true); - - tpc = new BatchToolPanelCoordinator (this); - fileCatalog = new FileCatalog (tpc->coarse, tpc->getToolBar()); - fileCatalog->set_size_request(50,150); - dirpaned->pack2 (*fileCatalog, true, true); - - placesBrowser->setDirBrowserRemoteInterface (dirBrowser); - recentBrowser->setDirBrowserRemoteInterface (dirBrowser); - dirBrowser->addDirSelectionListener (fileCatalog); - dirBrowser->addDirSelectionListener (recentBrowser); - dirBrowser->addDirSelectionListener (placesBrowser); - fileCatalog->setFileSelectionListener (this); - - rightBox = new Gtk::HBox (); - rightBox->set_size_request(50,100); - rightNotebook = new Gtk::Notebook (); - Gtk::VBox* taggingBox = new Gtk::VBox (); - - history = new History (false); - - tpc->addPParamsChangeListener (history); - history->setProfileChangeListener (tpc); - - Gtk::ScrolledWindow* sFilterPanel = new Gtk::ScrolledWindow(); - filterPanel = new FilterPanel (); - sFilterPanel->add (*filterPanel); - sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); - - fileCatalog->setFilterPanel (filterPanel); - fileCatalog->setImageAreaToolListener (tpc); - - //------------------ - - rightNotebook->set_tab_pos (Gtk::POS_LEFT); - - Gtk::Label* devLab = new Gtk::Label (M("MAIN_TAB_DEVELOP")); - devLab->set_angle (90); - Gtk::Label* filtLab = new Gtk::Label (M("MAIN_TAB_FILTER")); - filtLab->set_angle (90); - Gtk::Label* tagLab = new Gtk::Label (M("MAIN_TAB_TAGGING")); - tagLab->set_angle (90); - - tpcPaned = new Gtk::VPaned (); - tpcPaned->pack1 (*tpc->toolPanelNotebook, false, true); - tpcPaned->pack2 (*history, true, true); - - rightNotebook->append_page (*tpcPaned, *devLab); - rightNotebook->append_page (*sFilterPanel, *filtLab); - rightNotebook->append_page (*taggingBox, *tagLab); - - rightBox->pack_start (*rightNotebook); - - pack1(*dirpaned, true, true); - pack2(*rightBox, false, true); - - fileCatalog->setFileSelectionChangeListener (tpc); - - fileCatalog->setFileSelectionListener (this); - g_idle_add (fbinit, this); - - show_all (); -} - -void FilePanel::setAspect () { - int winW, winH; - parent->get_size(winW, winH); - placespaned->set_position(options.dirBrowserHeight); - dirpaned->set_position(options.dirBrowserWidth); - tpcPaned->set_position(options.browserToolPanelHeight); - set_position(winW - options.browserToolPanelWidth); -} - -void FilePanel::init () { - - dirBrowser->fillDirTree (); - placesBrowser->refreshPlacesList (); - - if (argv1!="") - dirBrowser->open (argv1); - else { - if (options.startupDir==STARTUPDIR_HOME) - dirBrowser->open (Glib::get_home_dir()); - else if (options.startupDir==STARTUPDIR_CURRENT) - dirBrowser->open (argv0); - else if (options.startupDir==STARTUPDIR_CUSTOM || options.startupDir==STARTUPDIR_LAST) - dirBrowser->open (options.startupPath); - } -} - -bool FilePanel::fileSelected (Thumbnail* thm) { - - if (!parent) - return false; - - // try to open the file - fileCatalog->setEnabled (false); - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), thm->getFileName (), thm->getType()==FT_Raw, &error, parent->getProgressListener()), - sigc::bind(sigc::mem_fun(*this,&FilePanel::imageLoaded), thm, ld) ); - return true; -} -bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector *pc ){ - - if (pc->returnValue() && thm) { - EditorPanel* epanel = Gtk::manage (new EditorPanel ()); - parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName())); - epanel->open(thm, pc->returnValue() ); - }else { - Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n"; - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - } - delete pc; - - parent->setProgress(0.); - parent->setProgressStr(""); - fileCatalog->setEnabled (true); - return false; // MUST return false from idle function -} - -void FilePanel::saveOptions () { - - int winW, winH; - parent->get_size(winW, winH); - options.dirBrowserWidth = dirpaned->get_position (); - options.dirBrowserHeight = placespaned->get_position (); - options.browserToolPanelWidth = winW - get_position(); - options.browserToolPanelHeight = tpcPaned->get_position (); - if (options.startupDir==STARTUPDIR_LAST && fileCatalog->lastSelectedDir ()!="") - options.startupPath = fileCatalog->lastSelectedDir (); - fileCatalog->closeDir (); -} - -void FilePanel::open (const Glib::ustring& d) { - - if (Glib::file_test (d, Glib::FILE_TEST_IS_DIR)) - dirBrowser->open (d.c_str()); - else if (Glib::file_test (d, Glib::FILE_TEST_EXISTS)) - dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d)); -} - -bool FilePanel::addBatchQueueJob (BatchQueueEntry* bqe) { - - if (parent) - parent->addBatchQueueJob (bqe); - return true; -} - -void FilePanel::optionsChanged () { - - tpc->optionsChanged (); - fileCatalog->refreshAll (); -} - -bool FilePanel::handleShortcutKey (GdkEventKey* event) { - - bool ctrl = event->state & GDK_CONTROL_MASK; - bool shift = event->state & GDK_SHIFT_MASK; - - if (!ctrl) { - switch(event->keyval) { - } - } - else { - switch (event->keyval) { - } - } - - if(tpc->getToolBar()->handleShortcutKey(event)) - return true; - - if(fileCatalog->handleShortcutKey(event)) - return true; - - return false; -} - +/* + * 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 +#include + +int fbinit (void* data) { + + gdk_threads_enter (); + ((FilePanel*)data)->init (); + gdk_threads_leave (); + + return 0; +} + +FilePanel::FilePanel () : parent(NULL) { + + isloading = false; + dirpaned = new Gtk::HPaned (); + dirpaned->set_position (options.dirBrowserWidth); + + dirBrowser = new DirBrowser (); + placesBrowser = new PlacesBrowser (); + recentBrowser = new RecentBrowser (); + + placespaned = new Gtk::VPaned (); + placespaned->set_size_request(50,100); + placespaned->set_position (options.dirBrowserHeight); + + Gtk::VBox* obox = Gtk::manage (new Gtk::VBox ()); + obox->pack_start (*recentBrowser, Gtk::PACK_SHRINK, 4); + obox->pack_start (*dirBrowser); + + placespaned->pack1 (*placesBrowser, false, true); + placespaned->pack2 (*obox, true, true); + + dirpaned->pack1 (*placespaned, false, true); + + tpc = new BatchToolPanelCoordinator (this); + fileCatalog = new FileCatalog (tpc->coarse, tpc->getToolBar()); + ribbonPane = new Gtk::Paned(); + ribbonPane->add(*fileCatalog); + ribbonPane->set_size_request(50,150); + dirpaned->pack2 (*ribbonPane, true, true); + + placesBrowser->setDirBrowserRemoteInterface (dirBrowser); + recentBrowser->setDirBrowserRemoteInterface (dirBrowser); + dirBrowser->addDirSelectionListener (fileCatalog); + dirBrowser->addDirSelectionListener (recentBrowser); + dirBrowser->addDirSelectionListener (placesBrowser); + fileCatalog->setFileSelectionListener (this); + + rightBox = new Gtk::HBox (); + rightBox->set_size_request(50,100); + rightNotebook = new Gtk::Notebook (); + Gtk::VBox* taggingBox = new Gtk::VBox (); + + history = new History (false); + + tpc->addPParamsChangeListener (history); + history->setProfileChangeListener (tpc); + + Gtk::ScrolledWindow* sFilterPanel = new Gtk::ScrolledWindow(); + filterPanel = new FilterPanel (); + sFilterPanel->add (*filterPanel); + sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + + fileCatalog->setFilterPanel (filterPanel); + fileCatalog->setImageAreaToolListener (tpc); + + //------------------ + + rightNotebook->set_tab_pos (Gtk::POS_LEFT); + + Gtk::Label* devLab = new Gtk::Label (M("MAIN_TAB_DEVELOP")); + devLab->set_angle (90); + Gtk::Label* filtLab = new Gtk::Label (M("MAIN_TAB_FILTER")); + filtLab->set_angle (90); + Gtk::Label* tagLab = new Gtk::Label (M("MAIN_TAB_TAGGING")); + tagLab->set_angle (90); + + tpcPaned = new Gtk::VPaned (); + tpcPaned->pack1 (*tpc->toolPanelNotebook, false, true); + tpcPaned->pack2 (*history, true, true); + + rightNotebook->append_page (*tpcPaned, *devLab); + rightNotebook->append_page (*sFilterPanel, *filtLab); + rightNotebook->append_page (*taggingBox, *tagLab); + + rightBox->pack_start (*rightNotebook); + + pack1(*dirpaned, true, true); + pack2(*rightBox, false, true); + + fileCatalog->setFileSelectionChangeListener (tpc); + + fileCatalog->setFileSelectionListener (this); + g_idle_add (fbinit, this); + + show_all (); +} + +void FilePanel::setAspect () { + int winW, winH; + parent->get_size(winW, winH); + placespaned->set_position(options.dirBrowserHeight); + dirpaned->set_position(options.dirBrowserWidth); + tpcPaned->set_position(options.browserToolPanelHeight); + set_position(winW - options.browserToolPanelWidth); +} + +void FilePanel::init () { + + dirBrowser->fillDirTree (); + placesBrowser->refreshPlacesList (); + + if (argv1!="") + dirBrowser->open (argv1); + else { + if (options.startupDir==STARTUPDIR_HOME) + dirBrowser->open (Glib::get_home_dir()); + else if (options.startupDir==STARTUPDIR_CURRENT) + dirBrowser->open (argv0); + else if (options.startupDir==STARTUPDIR_CUSTOM || options.startupDir==STARTUPDIR_LAST) + dirBrowser->open (options.startupPath); + } +} + +bool FilePanel::fileSelected (Thumbnail* thm) { + + if (!parent) + return false; + + // try to open the file + // fileCatalog->setEnabled (false); + if (isloading) + return false; + + isloading = true; + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), thm->getFileName (), thm->getType()==FT_Raw, &error, parent->getProgressListener()), + sigc::bind(sigc::mem_fun(*this,&FilePanel::imageLoaded), thm, ld) ); + return true; +} +bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector *pc ){ + + if (pc->returnValue() && thm) { + + if (options.tabbedUI){ + EditorPanel* epanel = Gtk::manage (new EditorPanel ()); + parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName())); + epanel->open(thm, pc->returnValue() ); + } + else{ + parent->SetEditorCurrent(); + parent->epanel->open(thm, pc->returnValue() ); + } + + + }else { + Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n"; + Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + } + delete pc; + + parent->setProgress(0.); + parent->setProgressStr(""); + isloading = false; + + return false; // MUST return false from idle function +} + +void FilePanel::saveOptions () { + + int winW, winH; + parent->get_size(winW, winH); + options.dirBrowserWidth = dirpaned->get_position (); + options.dirBrowserHeight = placespaned->get_position (); + options.browserToolPanelWidth = winW - get_position(); + options.browserToolPanelHeight = tpcPaned->get_position (); + if (options.startupDir==STARTUPDIR_LAST && fileCatalog->lastSelectedDir ()!="") + options.startupPath = fileCatalog->lastSelectedDir (); + fileCatalog->closeDir (); +} + +void FilePanel::open (const Glib::ustring& d) { + + if (Glib::file_test (d, Glib::FILE_TEST_IS_DIR)) + dirBrowser->open (d.c_str()); + else if (Glib::file_test (d, Glib::FILE_TEST_EXISTS)) + dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d)); +} + +bool FilePanel::addBatchQueueJob (BatchQueueEntry* bqe) { + + if (parent) + parent->addBatchQueueJob (bqe); + return true; +} + +void FilePanel::optionsChanged () { + + tpc->optionsChanged (); + fileCatalog->refreshAll (); +} + +bool FilePanel::handleShortcutKey (GdkEventKey* event) { + + bool ctrl = event->state & GDK_CONTROL_MASK; + bool shift = event->state & GDK_SHIFT_MASK; + + if (!ctrl) { + switch(event->keyval) { + } + } + else { + switch (event->keyval) { + } + } + + if(tpc->getToolBar()->handleShortcutKey(event)) + return true; + + if(fileCatalog->handleShortcutKey(event)) + return true; + + return false; +} \ No newline at end of file diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index bfdf38cf4..0cef8b289 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -1,80 +1,85 @@ -/* - * 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 _FILEPANEL_ -#define _FILEPANEL_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class RTWindow; -class FilePanel : public Gtk::HPaned, - public FileSelectionListener, - public PParamsChangeListener -{ - - protected: - Gtk::VPaned* placespaned; - Gtk::HPaned* dirpaned; - DirBrowser* dirBrowser; - PlacesBrowser* placesBrowser; - RecentBrowser* recentBrowser; - FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it - Gtk::HBox* rightBox; - Gtk::VPaned* tpcPaned; - BatchToolPanelCoordinator* tpc; - History* history; - FilterPanel* filterPanel; - RTWindow* parent; - Gtk::Notebook* rightNotebook; - - int error; - - public: - FilePanel (); - - void setParent (RTWindow* p) { parent = p; } - void init (); // dont call it directly, the constructor calls it as idle source - void setAspect(); - void open (const Glib::ustring& d); // open a file or a directory - void refreshEditedState (const std::set& efiles) { fileCatalog->refreshEditedState (efiles); } - - // call this before closeing rt: it saves file browser relating things into options - void saveOptions (); - - // interface fileselectionlistener - bool fileSelected (Thumbnail* thm); - bool addBatchQueueJob (BatchQueueEntry* bqe); - - void optionsChanged (); - bool imageLoaded( Thumbnail* thm, ProgressConnector * ); - - bool handleShortcutKey (GdkEventKey* event); -}; - -#endif - +/* + * 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 _FILEPANEL_ +#define _FILEPANEL_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RTWindow; +class FilePanel : public Gtk::HPaned, + public FileSelectionListener, + public PParamsChangeListener +{ + + protected: + Gtk::Paned* placespaned; + Gtk::HPaned* dirpaned; + //DirBrowser* dirBrowser; + PlacesBrowser* placesBrowser; + RecentBrowser* recentBrowser; + // FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it + Gtk::HBox* rightBox; + Gtk::VPaned* tpcPaned; + BatchToolPanelCoordinator* tpc; + History* history; + //FilterPanel* filterPanel; + RTWindow* parent; + Gtk::Notebook* rightNotebook; + + int error; + bool isloading; + public: + FilePanel (); + + DirBrowser* dirBrowser; + FilterPanel* filterPanel; + FileCatalog* fileCatalog; + Gtk::Paned *ribbonPane; + + void setParent (RTWindow* p) { parent = p; } + void init (); // dont call it directly, the constructor calls it as idle source + void setAspect(); + void open (const Glib::ustring& d); // open a file or a directory + void refreshEditedState (const std::set& efiles) { fileCatalog->refreshEditedState (efiles); } + + // call this before closeing rt: it saves file browser relating things into options + void saveOptions (); + + // interface fileselectionlistener + bool fileSelected (Thumbnail* thm); + bool addBatchQueueJob (BatchQueueEntry* bqe); + + void optionsChanged (); + bool imageLoaded( Thumbnail* thm, ProgressConnector * ); + + bool handleShortcutKey (GdkEventKey* event); +}; + +#endif + diff --git a/rtgui/filterpanel.cc.orig b/rtgui/filterpanel.cc.orig new file mode 100644 index 000000000..2c7efe0c9 --- /dev/null +++ b/rtgui/filterpanel.cc.orig @@ -0,0 +1,243 @@ +/* + * 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 +#include +#include + +using namespace rtengine; + +FilterPanel::FilterPanel () : listener (NULL) { + + set_border_width (4); + + enabled = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_METADATAFILTER"))); + pack_start (*enabled, Gtk::PACK_SHRINK, 2); + pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2); + + enaFNumber = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_APERTURE")+":")); + Gtk::VBox* fnvb = Gtk::manage(new Gtk::VBox ()); + Gtk::HBox* fnhb = Gtk::manage(new Gtk::HBox ()); + fnvb->pack_start (*enaFNumber, Gtk::PACK_SHRINK, 0); + fnumberFrom = Gtk::manage(new Gtk::Entry ()); + fnumberTo = Gtk::manage(new Gtk::Entry ()); + fnhb->pack_start (*fnumberFrom, true, true, 2); + fnhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); + fnhb->pack_start (*fnumberTo, true, true, 2); + fnvb->pack_start (*fnhb, Gtk::PACK_SHRINK, 0); + pack_start (*fnvb, Gtk::PACK_SHRINK, 4); + + enaShutter = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_SHUTTER")+":")); + Gtk::VBox* svb = Gtk::manage(new Gtk::VBox ()); + Gtk::HBox* shb = Gtk::manage(new Gtk::HBox ()); + svb->pack_start (*enaShutter, Gtk::PACK_SHRINK, 0); + shutterFrom = Gtk::manage(new Gtk::Entry ()); + shutterTo = Gtk::manage(new Gtk::Entry ()); + shb->pack_start (*shutterFrom, true, true, 2); + shb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); + shb->pack_start (*shutterTo, true, true, 2); + svb->pack_start (*shb, Gtk::PACK_SHRINK, 0); + pack_start (*svb, Gtk::PACK_SHRINK, 4); + + enaISO = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_ISO")+":")); + Gtk::VBox* ivb = Gtk::manage(new Gtk::VBox ()); + Gtk::HBox* ihb = Gtk::manage(new Gtk::HBox ()); + ivb->pack_start (*enaISO, Gtk::PACK_SHRINK, 0); + isoFrom = Gtk::manage(new Gtk::Entry ()); + isoTo = Gtk::manage(new Gtk::Entry ()); + ihb->pack_start (*isoFrom, true, true, 2); + ihb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); + ihb->pack_start (*isoTo, true, true, 2); + ivb->pack_start (*ihb, Gtk::PACK_SHRINK, 0); + pack_start (*ivb, Gtk::PACK_SHRINK, 4); + + enaFocalLen = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FOCALLEN")+":")); + Gtk::VBox* fvb = Gtk::manage(new Gtk::VBox ()); + Gtk::HBox* fhb = Gtk::manage(new Gtk::HBox ()); + fvb->pack_start (*enaFocalLen, Gtk::PACK_SHRINK, 0); + focalFrom = Gtk::manage(new Gtk::Entry ()); + focalTo = Gtk::manage(new Gtk::Entry ()); + fhb->pack_start (*focalFrom, true, true, 2); + fhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); + fhb->pack_start (*focalTo, true, true, 2); + fvb->pack_start (*fhb, Gtk::PACK_SHRINK, 0); + pack_start (*fvb, Gtk::PACK_SHRINK, 4); + + enaCamera = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_CAMERA")+":")); + Gtk::VBox* cvb = Gtk::manage(new Gtk::VBox ()); + cvb->pack_start (*enaCamera, Gtk::PACK_SHRINK, 0); + camera = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); + camera->set_headers_visible (false); + Gtk::ScrolledWindow* scamera = Gtk::manage(new Gtk::ScrolledWindow()); + scamera->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + scamera->add(*camera); + cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0); + pack_start (*cvb, Gtk::PACK_SHRINK, 4); + + enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS")+":")); + Gtk::VBox* lvb = Gtk::manage(new Gtk::VBox ()); + lvb->pack_start (*enaLens, Gtk::PACK_SHRINK, 0); + lens = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); + lens->set_headers_visible (false); + Gtk::ScrolledWindow* slens = Gtk::manage(new Gtk::ScrolledWindow()); + slens->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + slens->add(*lens); + lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0); + pack_start (*lvb, Gtk::PACK_SHRINK, 4); + + conns = 0; + sChange[conns++] = fnumberFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = fnumberTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = shutterFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = shutterTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = isoFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = isoTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = focalFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = focalTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = camera->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = lens->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FilterPanel::valueChanged)); + sChange[conns++] = enaFNumber->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enaShutter->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enaFocalLen->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enaISO->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enaCamera->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enaLens->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + sChange[conns++] = enabled->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); + + set_size_request (0, -1); + + show_all (); +} + +void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) { + + + for (int i=0; iset_active (curefs.filterFNumber); + fnumberFrom->set_text (ImageMetaData::apertureToString (defefs.fnumberFrom)); + curefs.fnumberFrom = defefs.fnumberFrom; + fnumberTo->set_text (ImageMetaData::apertureToString (defefs.fnumberTo)); + curefs.fnumberTo = defefs.fnumberTo; + +// enaShutter->set_active (curefs.filterShutter); + shutterFrom->set_text (ImageMetaData::shutterToString (defefs.shutterFrom)); + curefs.shutterFrom = defefs.shutterFrom; + shutterTo->set_text (ImageMetaData::shutterToString (defefs.shutterTo)); + curefs.shutterTo = defefs.shutterTo; + +// enaISO->set_active (curefs.filterISO); + std::stringstream out; + out << defefs.isoFrom; + isoFrom->set_text ( out.str() ); + curefs.isoFrom = defefs.isoFrom; + isoTo->set_text (Glib::ustring::format ((double)defefs.isoTo)); + curefs.isoTo = defefs.isoTo; + +// enaFocalLen->set_active (curefs.filterFocalLen); + focalFrom->set_text (Glib::ustring::format (defefs.focalFrom)); + curefs.focalFrom = defefs.focalFrom; + focalTo->set_text (Glib::ustring::format (defefs.focalTo)); + curefs.focalTo = defefs.focalTo; + +// enaCamera->set_active (curefs.filterCamera); + Glib::RefPtr cselection = camera->get_selection (); + +// enaLens->set_active (curefs.filterLens); + Glib::RefPtr lselection = lens->get_selection (); + if( updateLists ){ + lens->clear_items(); + curefs.lenses.clear(); + for (std::set::iterator i = defefs.lenses.begin(); i!=defefs.lenses.end(); i++) { + lens->append_text (*i); + curefs.lenses.insert(*i); + } + lselection->select_all(); + + camera->clear_items(); + curefs.cameras.clear(); + for (std::set::iterator i = defefs.cameras.begin(); i!=defefs.cameras.end(); i++) { + camera->append_text(*i); + curefs.cameras.insert(*i); + } + cselection->select_all(); + }else{ + for( Gtk::TreeModel::Children::iterator iter = lens->get_model()->children().begin(); iter != lens->get_model()->children().end();iter++){ + Glib::ustring v; + iter->get_value(0,v); + if( defefs.lenses.find( v ) != defefs.lenses.end() ) + lselection->select( iter ); + else + lselection->unselect( iter ); + } + for( Gtk::TreeModel::Children::iterator iter = camera->get_model()->children().begin(); iter != camera->get_model()->children().end();iter++){ + Glib::ustring v; + iter->get_value(0,v); + if( defefs.cameras.find( v ) != defefs.cameras.end() ) + cselection->select(iter); + else + cselection->unselect(iter); + } + } + + curefs = defefs; + + for (int i=0; iget_active () && is_sensitive(); +} + +ExifFilterSettings FilterPanel::getFilter () { + + ExifFilterSettings efs; + efs.fnumberFrom = atof (fnumberFrom->get_text().c_str()); + efs.fnumberTo = atof (fnumberTo->get_text().c_str()); + efs.focalFrom = atof (focalFrom->get_text().c_str()); + efs.focalTo = atof (focalTo->get_text().c_str()); + efs.isoFrom = atoi (isoFrom->get_text().c_str()); + efs.isoTo = atoi (isoTo->get_text().c_str()); + efs.shutterFrom = ImageMetaData::shutterFromString (shutterFrom->get_text()); + efs.shutterTo = ImageMetaData::shutterFromString (shutterTo->get_text()); + + efs.filterFNumber = enaFNumber->get_active (); + efs.filterShutter = enaShutter->get_active (); + efs.filterFocalLen = enaFocalLen->get_active (); + efs.filterISO = enaISO->get_active (); + efs.filterCamera = enaCamera->get_active (); + efs.filterLens = enaLens->get_active (); + + std::vector sel = camera->get_selected (); + for (int i=0; iget_text (sel[i])); + sel = lens->get_selected (); + for (int i=0; iget_text (sel[i])); + + return efs; +} + +void FilterPanel::valueChanged () { + + if (listener) + listener->exifFilterChanged (); +} diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 7fcf536dd..ede4567a4 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -44,6 +44,7 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) { signal_size_allocate().connect( sigc::mem_fun(*this, &ImageArea::on_resized) ); dirty = false; + ipc = NULL; } void ImageArea::on_realize() diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index 08e1386fc..cbf489c60 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -44,7 +44,7 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener { bool showClippedH, showClippedS; ImageAreaPanel* parent; - CropWindow* mainCropWindow; + std::list cropWins; PreviewHandler* previewHandler; rtengine::StagedImageProcessor* ipc; @@ -60,7 +60,7 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener { CropWindow* getCropWindow (int x, int y); public: - + CropWindow* mainCropWindow; ZoomPanel* zoomPanel; IndicateClippedPanel* indClippedPanel; diff --git a/rtgui/options.cc b/rtgui/options.cc index 1b1973815..3128aaa11 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -118,12 +118,14 @@ void Options::setDefaults () { thumbnailZoomRatios.push_back (1.0); overlayedFileNames = true; showFileNames = true; + tabbedUI = false; int babehav[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}; baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); rtSettings.dualThreadEnabled = true; - rtSettings.demosaicMethod = "amaze";//Emil's code for AMaZE + rtSettings.demosaicMethod = "hphd"; + rtSettings.demosaicMethodBatch = "hphd"; rtSettings.ca_autocorrect = false;//Emil's CA correction rtSettings.hotdeadpix_filt = true;//Emil's hot/dead pixel filter @@ -161,8 +163,8 @@ int Options::readFromFile (Glib::ustring fname) { setDefaults (); -if (keyFile.has_group ("General")) { - Glib::ustring stup; +if (keyFile.has_group ("General")) { + if (keyFile.has_key ("General", "TabbedEditor")) tabbedUI= keyFile.get_boolean ("General", "TabbedEditor"); if (keyFile.has_key ("General", "StartupDirectory") && keyFile.get_string ("General", "StartupDirectory") == "home") startupDir = STARTUPDIR_HOME; else if (keyFile.has_key ("General", "StartupDirectory") && keyFile.get_string ("General", "StartupDirectory") == "current") @@ -272,6 +274,7 @@ if (keyFile.has_group ("GUI")) { if (keyFile.has_group ("Algorithms")) { if (keyFile.has_key ("Algorithms", "DemosaicMethod")) rtSettings.demosaicMethod = keyFile.get_string ("Algorithms", "DemosaicMethod"); + if (keyFile.has_key ("Algorithms", "DemosaicMethodBatch")) rtSettings.demosaicMethodBatch = keyFile.get_string ("Algorithms", "DemosaicMethodBatch"); if (keyFile.has_key ("Algorithms", "ColorCorrection")) rtSettings.colorCorrectionSteps = keyFile.get_integer ("Algorithms", "ColorCorrection"); if (keyFile.has_key ("Algorithms", "DCBIterations")) rtSettings.dcb_iterations = keyFile.get_integer("Algorithms", "DCBIterations"); if (keyFile.has_key ("Algorithms", "DCBEnhance")) rtSettings.dcb_enhance = keyFile.get_boolean("Algorithms", "DCBEnhance"); @@ -301,7 +304,8 @@ if (keyFile.has_group ("Batch Processing")) { int Options::saveToFile (Glib::ustring fname) { rtengine::SafeKeyFile keyFile; - + keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); + keyFile.set_boolean ("General", "StoreLastProfile", savesParamsAtExit); if (startupDir==STARTUPDIR_HOME) keyFile.set_string ("General", "StartupDirectory", "home"); @@ -403,6 +407,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); keyFile.set_string ("Algorithms", "DemosaicMethod", rtSettings.demosaicMethod); + keyFile.set_string ("Algorithms", "DemosaicMethodBatch", rtSettings.demosaicMethodBatch); keyFile.set_integer ("Algorithms", "ColorCorrection", rtSettings.colorCorrectionSteps); keyFile.set_integer ("Algorithms", "DCBIterations", rtSettings.dcb_iterations); keyFile.set_boolean ("Algorithms", "DCBEnhance", rtSettings.dcb_enhance); diff --git a/rtgui/options.h b/rtgui/options.h index f6a72c11b..8cd43b0cb 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -126,6 +126,7 @@ class Options { std::vector thumbnailZoomRatios; bool overlayedFileNames; bool showFileNames; + bool tabbedUI; Options (); diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index abf2cf129..8e04a9ea6 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -26,7 +26,7 @@ extern Options options; extern Glib::ustring argv0; -Preferences::Preferences (int initialPage) { +Preferences::Preferences (RTWindow *rtwindow):parent(rtwindow) { set_title (M("MAIN_BUTTON_PREFERENCES")); @@ -77,7 +77,7 @@ Preferences::Preferences (int initialPage) { 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->set_current_page (initialPage); + nb->set_current_page (0); fillPreferences (); @@ -255,6 +255,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { Gtk::VBox* fdb = Gtk::manage (new Gtk::VBox ()); fdb->set_border_width (4); fdem->add (*fdb); + Gtk::Label* dmlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_DMETHOD")+":")); dmethod = Gtk::manage (new Gtk::ComboBoxText ()); Gtk::HBox* hb11 = Gtk::manage (new Gtk::HBox ()); @@ -268,6 +269,21 @@ Gtk::Widget* Preferences::getProcParamsPanel () { dmethod->append_text ("DCB"); dmethod->append_text ("Fast Demosaic");//("AHD"); dmethod->append_text ("Bilinear"); + + Gtk::Label* dmlab2 = Gtk::manage (new Gtk::Label (M("PREFERENCES_DMETHODBATCH")+": ")); + dmethodBatch = Gtk::manage (new Gtk::ComboBoxText ()); + Gtk::HBox* hb111 = Gtk::manage (new Gtk::HBox ()); + hb111->pack_start (*dmlab2, Gtk::PACK_SHRINK, 4); + hb111->pack_start (*dmethodBatch); + dmethodBatch->append_text ("EAHD"); + dmethodBatch->append_text ("HPHD"); + dmethodBatch->append_text ("VNG-4"); + //dmethod->append_text ("PPG"); + dmethodBatch->append_text ("AMaZE");//Emil's code for AMaZE + dmethodBatch->append_text ("DCB"); + dmethodBatch->append_text ("Fast Demosaic");//("AHD"); + dmethodBatch->append_text ("Bilinear"); + Gtk::Label* cclab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FALSECOLOR")+":")); ccSteps = Gtk::manage (new Gtk::SpinButton ()); ccSteps->set_digits (0); @@ -316,6 +332,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% fdb->pack_start (*hb11, Gtk::PACK_SHRINK, 4); + fdb->pack_start (*hb111, Gtk::PACK_SHRINK, 4); fdb->pack_start (*hb12, Gtk::PACK_SHRINK, 4); fdb->pack_start (*hb13, Gtk::PACK_SHRINK, 4); fdb->pack_start (*dcbEnhance, Gtk::PACK_SHRINK, 4); @@ -338,6 +355,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { } dmconn = dmethod->signal_changed().connect( sigc::mem_fun(*this, &Preferences::dmethodChanged) ); + dmconnBatch = dmethod->signal_changed().connect( sigc::mem_fun(*this, &Preferences::dmethodBatchChanged) ); return mvbpp; } @@ -377,6 +395,21 @@ Gtk::Widget* Preferences::getGeneralPanel () { Gtk::VBox* mvbsd = new Gtk::VBox (); + Gtk::Frame* fworklflow = new Gtk::Frame (M("PREFERENCES_WORKFLOW")); + Gtk::HBox* hbworkflow = new Gtk::HBox (); + hbworkflow->set_border_width (4); + Gtk::Label* flayoutlab = new Gtk::Label (M("PREFERENCES_EDITORLAYOUT")+":"); + editorLayout = new Gtk::ComboBoxText (); + + editorLayout->append_text (M("PREFERENCES_SINGLETAB")); + editorLayout->append_text (M("PREFERENCES_MULTITAB")); + editorLayout->set_active (1); + + hbworkflow->pack_start (*flayoutlab, Gtk::PACK_SHRINK, 4); + hbworkflow->pack_start (*editorLayout); + fworklflow->add (*hbworkflow); + mvbsd->pack_start (*fworklflow, Gtk::PACK_SHRINK, 4); + Gtk::Frame* flang = new Gtk::Frame (M("PREFERENCES_DEFAULTLANG")); Gtk::HBox* hblang = new Gtk::HBox (); hblang->set_border_width (4); @@ -384,7 +417,6 @@ Gtk::Widget* Preferences::getGeneralPanel () { languages = new Gtk::ComboBoxText (); std::vector langs; - parseDir (argv0 + "/languages", langs, ""); for (int i=0; iappend_text (langs[i]); @@ -532,7 +564,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { tconn = theme->signal_changed().connect( sigc::mem_fun(*this, &Preferences::themeChanged) ); fconn = fontbutton->signal_font_set().connect( sigc::mem_fun(*this, &Preferences::fontChanged) ); - + return mvbsd; } @@ -764,6 +796,21 @@ void Preferences::storePreferences () { moptions.rtSettings.demosaicMethod = "ahd"; else if (dmethod->get_active_row_number()==6) moptions.rtSettings.demosaicMethod = "bilinear"; + + if (dmethodBatch->get_active_row_number()==0) + moptions.rtSettings.demosaicMethodBatch = "eahd"; + else if (dmethodBatch->get_active_row_number()==1) + moptions.rtSettings.demosaicMethodBatch = "hphd"; + else if (dmethodBatch->get_active_row_number()==2) + moptions.rtSettings.demosaicMethodBatch = "vng4"; + else if (dmethodBatch->get_active_row_number()==3) + moptions.rtSettings.demosaicMethodBatch = "amaze"; + else if (dmethodBatch->get_active_row_number()==4) + moptions.rtSettings.demosaicMethodBatch = "dcb"; + else if (dmethodBatch->get_active_row_number()==5) + moptions.rtSettings.demosaicMethodBatch = "ahd"; + else if (dmethodBatch->get_active_row_number()==6) + moptions.rtSettings.demosaicMethodBatch = "bilinear"; moptions.rtSettings.dcb_iterations=(int)dcbIterations->get_value(); moptions.rtSettings.dcb_enhance=dcbEnhance->get_active(); moptions.rtSettings.ca_autocorrect=caAutoCorrect->get_active();//Emil's CA correction @@ -811,11 +858,14 @@ void Preferences::storePreferences () { for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++) for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) moptions.baBehav[adjs->get_value (behavColumns.addsetid)] = adjs->get_value (behavColumns.badd); + + moptions.tabbedUI = (bool)editorLayout->get_active_row_number(); } void Preferences::fillPreferences () { dmconn.block (true); + dmconnBatch.block(true); tconn.block (true); fconn.block (true); @@ -836,7 +886,7 @@ void Preferences::fillPreferences () { blinkClipped->set_active (moptions.blinkClipped); hlThresh->set_value (moptions.highlightThreshold); shThresh->set_value (moptions.shadowThreshold); - + edGimp->set_active (moptions.editorToSendTo==1); edOther->set_active (moptions.editorToSendTo==3); #ifdef _WIN32 @@ -868,6 +918,22 @@ void Preferences::fillPreferences () { dmethod->set_active (5); else if (moptions.rtSettings.demosaicMethod=="bilinear") dmethod->set_active (6); + + if (moptions.rtSettings.demosaicMethodBatch=="eahd") + dmethodBatch->set_active (0); + else if (moptions.rtSettings.demosaicMethodBatch=="hphd") + dmethodBatch->set_active (1); + else if (moptions.rtSettings.demosaicMethodBatch=="vng4") + dmethodBatch->set_active (2); + else if (moptions.rtSettings.demosaicMethodBatch=="amaze")//Emil's code for AMaZE + dmethodBatch->set_active (3); + else if (moptions.rtSettings.demosaicMethodBatch=="dcb") + dmethodBatch->set_active (4); + else if (moptions.rtSettings.demosaicMethodBatch=="ahd") + dmethodBatch->set_active (5); + else if (moptions.rtSettings.demosaicMethodBatch=="bilinear") + dmethodBatch->set_active (6); + dcbEnhance->set_active(moptions.rtSettings.dcb_enhance); dcbIterations->set_value(moptions.rtSettings.dcb_iterations); dcbEnhance->set_sensitive(moptions.rtSettings.demosaicMethod=="dcb"); @@ -913,6 +979,7 @@ void Preferences::fillPreferences () { saveParamsCache->set_active (moptions.saveParamsCache); loadParamsPreference->set_active (moptions.paramsLoadLocation); + editorLayout->set_active(moptions.tabbedUI); addc.block (true); setc.block (true); if (moptions.baBehav.size() == ADDSET_PARAM_NUM) { @@ -929,6 +996,7 @@ void Preferences::fillPreferences () { setc.block (false); dmconn.block (false); + dmconnBatch.block(false); tconn.block (false); fconn.block (false); } @@ -950,6 +1018,7 @@ void Preferences::okPressed () { storePreferences (); options.copyFrom (&moptions); + workflowUpdate(); hide (); } @@ -1000,6 +1069,26 @@ void Preferences::dmethodChanged () { } } +void Preferences::dmethodBatchChanged () { + + if (dmethod->get_active_row_number()==0) + ccSteps->set_value (2); + else if (dmethod->get_active_row_number()==1) + ccSteps->set_value (1); + else if (dmethod->get_active_row_number()==2) + ccSteps->set_value (2); + + if (dmethod->get_active_row_number()==4) { + dcbEnhance->set_sensitive(true); + dcbIterations->set_sensitive(true); + dcbIterationsLabel->set_sensitive(true); + } else { + dcbEnhance->set_sensitive(false); + dcbIterations->set_sensitive(false); + dcbIterationsLabel->set_sensitive(false); + } +} + void Preferences::aboutPressed () { Splash* splash = new Splash (-1); @@ -1028,6 +1117,14 @@ void Preferences::switchThemeTo(Glib::ustring newTheme) { gdk_event_send_clientmessage_toall ((GdkEvent*)&event); } +void Preferences::workflowUpdate (){ + + if(moptions.tabbedUI) + parent->epanel->hide_all(); + else + parent->epanel->show_all(); +} + void Preferences::switchFontTo(Glib::ustring newFont) { Gtk::RC::parse_string (Glib::ustring::compose( @@ -1037,6 +1134,7 @@ void Preferences::switchFontTo(Glib::ustring newFont) { gdk_event_send_clientmessage_toall ((GdkEvent*)&event); } + void Preferences::addExtPressed () { Gtk::TreeNodeChildren c = extensionModel->children (); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 9c26ca45c..223fd4351 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -1,158 +1,163 @@ -/* - * 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 __PREFERENCES_H__ -#define __PREFERENCES_H__ - -#include -#include -#include -#include - -class Preferences : public Gtk::Dialog { - - class ExtensionColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn enabled; - Gtk::TreeModelColumn ext; - ExtensionColumns() { add(enabled); add(ext); } - }; - ExtensionColumns extensionColumns; - Glib::RefPtr extensionModel; - - - class BehavColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn label; - Gtk::TreeModelColumn badd; - Gtk::TreeModelColumn bset; - Gtk::TreeModelColumn visible; - Gtk::TreeModelColumn addsetid; - BehavColumns() { add(label); add(badd); add(bset); add(visible); add(addsetid); } - }; - Glib::RefPtr behModel; - BehavColumns behavColumns; - - - protected: - Gtk::ComboBoxText* rprofiles; - Gtk::ComboBoxText* iprofiles; - Gtk::ComboBoxText* dmethod; - Gtk::ComboBoxText* languages; - Gtk::Entry* dateformat; - Gtk::Entry* startupdir; - Gtk::RadioButton* sdcurrent; - Gtk::RadioButton* sdlast; - Gtk::RadioButton* sdhome; - Gtk::RadioButton* sdother; - Gtk::FileChooserButton* gimpDir; - Gtk::FileChooserButton* psDir; - Gtk::Entry* editorToSendTo; - Gtk::RadioButton* edGimp; - Gtk::RadioButton* edPS; - Gtk::RadioButton* edOther; - - - Gtk::CheckButton* showDateTime; - Gtk::CheckButton* showBasicExif; - - Gtk::SpinButton* ccSteps; - Gtk::Label* dcbIterationsLabel; - Gtk::SpinButton* dcbIterations; - Gtk::CheckButton* dcbEnhance; - Gtk::CheckButton* caAutoCorrect;//Emil's CA correction - Gtk::CheckButton* HotDeadPixFilt;//Emil's hot/dead pixel filter - Gtk::Label* LineDenoiseLabel;//Emil's line denoise - Gtk::SpinButton* LineDenoise; - Gtk::Label* GreenEquilLabel;//Emil's Green equilibration - Gtk::SpinButton* GreenEquil; - - Gtk::FileChooserButton* iccDir; - Gtk::FileChooserButton* monProfile; - - Gtk::CheckButton* blinkClipped; - Gtk::SpinButton* hlThresh; - Gtk::SpinButton* shThresh; - - Gtk::ComboBoxText* intent; - - Gtk::ComboBoxText* theme; - Gtk::FontButton* fontbutton; - - Gtk::ComboBoxText* cformat; - Gtk::SpinButton* maxThumbSize; - Gtk::SpinButton* maxCacheEntries; - Gtk::Button* clearThumbnails; - Gtk::Button* clearProfiles; - Gtk::Button* clearAll; - Gtk::Entry* extension; - Gtk::TreeView* extensions; - Gtk::Button* addExt; - Gtk::Button* delExt; - Gtk::CheckButton* overlayedFileNames; - - Gtk::CheckButton* saveParamsFile; - Gtk::CheckButton* saveParamsCache; - Gtk::ComboBoxText* loadParamsPreference; - - Options moptions; - Glib::ustring initialTheme; - Glib::ustring initialFont; - sigc::connection dmconn, tconn, fconn, addc, setc; - - void fillPreferences (); - void storePreferences (); - void parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext); - void dmethodChanged (); - - void themeChanged (); - void fontChanged (); - void switchThemeTo (Glib::ustring newTheme); - void switchFontTo (Glib::ustring newFont); - - void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set); - - Gtk::Widget* getProcParamsPanel (); - Gtk::Widget* getColorManagementPanel (); - Gtk::Widget* getFileBrowserPanel (); - Gtk::Widget* getGeneralPanel (); - Gtk::Widget* getBatchProcPanel (); - - public: - Preferences (int initialPage=0); - - void savePressed (); - void loadPressed (); - void okPressed (); - void cancelPressed (); - void aboutPressed (); - - void selectStartupDir (); - void addExtPressed (); - void delExtPressed (); - - void clearProfilesPressed (); - void clearThumbImagesPressed (); - void clearAllPressed (); - void behAddRadioToggled (const Glib::ustring& path); - void behSetRadioToggled (const Glib::ustring& path); -// void selectICCProfileDir (); -// void selectMonitorProfile (); -}; - -#endif +/* + * 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 __PREFERENCES_H__ +#define __PREFERENCES_H__ + +#include +#include +#include +#include +#include "rtwindow.h" + +class Preferences : public Gtk::Dialog { + + class ExtensionColumns : public Gtk::TreeModel::ColumnRecord { + public: + Gtk::TreeModelColumn enabled; + Gtk::TreeModelColumn ext; + ExtensionColumns() { add(enabled); add(ext); } + }; + ExtensionColumns extensionColumns; + Glib::RefPtr extensionModel; + + + class BehavColumns : public Gtk::TreeModel::ColumnRecord { + public: + Gtk::TreeModelColumn label; + Gtk::TreeModelColumn badd; + Gtk::TreeModelColumn bset; + Gtk::TreeModelColumn visible; + Gtk::TreeModelColumn addsetid; + BehavColumns() { add(label); add(badd); add(bset); add(visible); add(addsetid); } + }; + Glib::RefPtr behModel; + BehavColumns behavColumns; + + + protected: + Gtk::ComboBoxText* rprofiles; + Gtk::ComboBoxText* iprofiles; + Gtk::ComboBoxText* dmethod; + Gtk::ComboBoxText* dmethodBatch; + Gtk::ComboBoxText* languages; + Gtk::Entry* dateformat; + Gtk::Entry* startupdir; + Gtk::RadioButton* sdcurrent; + Gtk::RadioButton* sdlast; + Gtk::RadioButton* sdhome; + Gtk::RadioButton* sdother; + Gtk::FileChooserButton* gimpDir; + Gtk::FileChooserButton* psDir; + Gtk::Entry* editorToSendTo; + Gtk::RadioButton* edGimp; + Gtk::RadioButton* edPS; + Gtk::RadioButton* edOther; + + + Gtk::CheckButton* showDateTime; + Gtk::CheckButton* showBasicExif; + + Gtk::SpinButton* ccSteps; + Gtk::Label* dcbIterationsLabel; + Gtk::SpinButton* dcbIterations; + Gtk::CheckButton* dcbEnhance; + Gtk::CheckButton* caAutoCorrect;//Emil's CA correction + Gtk::CheckButton* HotDeadPixFilt;//Emil's hot/dead pixel filter + Gtk::Label* LineDenoiseLabel;//Emil's line denoise + Gtk::SpinButton* LineDenoise; + Gtk::Label* GreenEquilLabel;//Emil's Green equilibration + Gtk::SpinButton* GreenEquil; + + Gtk::FileChooserButton* iccDir; + Gtk::FileChooserButton* monProfile; + + Gtk::CheckButton* blinkClipped; + Gtk::SpinButton* hlThresh; + Gtk::SpinButton* shThresh; + + Gtk::ComboBoxText* intent; + + Gtk::ComboBoxText* theme; + Gtk::FontButton* fontbutton; + + Gtk::ComboBoxText* cformat; + Gtk::SpinButton* maxThumbSize; + Gtk::SpinButton* maxCacheEntries; + Gtk::Button* clearThumbnails; + Gtk::Button* clearProfiles; + Gtk::Button* clearAll; + Gtk::Entry* extension; + Gtk::TreeView* extensions; + Gtk::Button* addExt; + Gtk::Button* delExt; + Gtk::CheckButton* overlayedFileNames; + + Gtk::CheckButton* saveParamsFile; + Gtk::CheckButton* saveParamsCache; + Gtk::ComboBoxText* loadParamsPreference; + Gtk::ComboBoxText* editorLayout; + RTWindow* parent; + + Options moptions; + sigc::connection dmconn, dmconnBatch, tconn, addc, setc; + Glib::ustring initialTheme; + Glib::ustring initialFont; + + void fillPreferences (); + void storePreferences (); + void parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext); + void dmethodChanged (); + void dmethodBatchChanged (); + void workflowUpdate(); + void themeChanged (); + void fontChanged (); + void switchThemeTo (Glib::ustring newTheme); + void switchFontTo (Glib::ustring newFont); + + void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set); + + Gtk::Widget* getProcParamsPanel (); + Gtk::Widget* getColorManagementPanel (); + Gtk::Widget* getFileBrowserPanel (); + Gtk::Widget* getGeneralPanel (); + Gtk::Widget* getBatchProcPanel (); + + public: + Preferences (RTWindow *rtwindow); + + void savePressed (); + void loadPressed (); + void okPressed (); + void cancelPressed (); + void aboutPressed (); + + void selectStartupDir (); + void addExtPressed (); + void delExtPressed (); + + void clearProfilesPressed (); + void clearThumbImagesPressed (); + void clearAllPressed (); + void behAddRadioToggled (const Glib::ustring& path); + void behSetRadioToggled (const Glib::ustring& path); +// void selectICCProfileDir (); +// void selectMonitorProfile (); +}; + +#endif diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index 5d6f0a99d..f3f4c4a7b 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -1,214 +1,215 @@ -/* - * 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 -#include -#include - -PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL),cCropMoving(NULL),cNormal(NULL), isMoving(false) { - - rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); -} - -PreviewWindow::~PreviewWindow () { - - if( cCropMoving ) - delete cCropMoving; - if( cNormal ) - delete cNormal; - -} - -void PreviewWindow::on_realize () { - - Gtk::DrawingArea::on_realize (); - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); - cCropMoving = new Gdk::Cursor (Gdk::FLEUR); - cNormal = new Gdk::Cursor (Gdk::ARROW); -} - -void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { - - if (mainCropWin) { - int cropX, cropY, cropW, cropH; - mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); - // translate it to screen coordinates - x = imgX + cropX*zoom; - y = imgY + cropY*zoom; - w = cropW * zoom; - h = cropH * zoom; - } -} - -void PreviewWindow::updatePreviewImage () { - - int W = get_width(), H = get_height(); - Glib::RefPtr wind = get_window(); - if( ! wind ) - return; - backBuffer = Gdk::Pixmap::create (wind, W, H, -1); - backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); - if (previewHandler) { - Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); - if (resPixbuf) { - imgW = resPixbuf->get_width(); - imgH = resPixbuf->get_height(); - imgX = (W-imgW)/2; - imgY = (H-imgH)/2; - backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); - Cairo::RefPtr cr = backBuffer->create_cairo_context(); - if (previewHandler->getCropParams().enabled) - drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams()); - } - } -} - -void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { - - previewHandler = ph; - previewHandler->addPreviewImageListener (this); -} - -void PreviewWindow::on_resized (Gtk::Allocation& req) { - - updatePreviewImage (); - queue_draw (); -} - -bool PreviewWindow::on_expose_event (GdkEventExpose* event) { - - if (backBuffer) { - Glib::RefPtr window = get_window(); - - int bufferW, bufferH; - backBuffer->get_size (bufferW, bufferH); - - if (!mainCropWin) { - mainCropWin = imageArea->getMainCropWindow (); - if (mainCropWin) - mainCropWin->addCropWindowListener (this); - } - - if (get_width()!=bufferW && get_height()!=bufferH) - updatePreviewImage (); - - window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); - - if (mainCropWin) { - Cairo::RefPtr cr = get_window()->create_cairo_context(); - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - cr->set_source_rgb (1.0, 1.0, 1.0); - cr->set_line_width (3); - cr->rectangle (x-1.5, y-1.5, w+2, h+2); - cr->stroke (); - cr->set_source_rgb (1.0, 0.0, 0.0); - cr->set_line_width (1); - cr->rectangle (x-1.5, y-1.5, w+2, h+2); - cr->stroke (); - } - } - return true; -} - -void PreviewWindow::previewImageChanged () { - - updatePreviewImage (); - queue_draw (); -} - -void PreviewWindow::setImageArea (ImageArea* ia) { - - imageArea = ia; - mainCropWin = ia->getMainCropWindow (); - if (mainCropWin) - mainCropWin->addCropWindowListener (this); -} - -void PreviewWindow::cropPositionChanged (CropWindow* w) { - - queue_draw (); -} - -void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { - - queue_draw (); -} - -void PreviewWindow::cropZoomChanged (CropWindow* w) { - - queue_draw (); -} - -bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { - - if (!mainCropWin) - return true; - - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; - - if (isMoving) - mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); - else if (inside && !moreInside) - get_window()->set_cursor (*cCropMoving); - else - get_window()->set_cursor (*cNormal); - return true; -} - -bool PreviewWindow::on_button_press_event (GdkEventButton* event) { - - if (!mainCropWin) - return true; - - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; - - if (!isMoving) { - isMoving = true; - if (!inside || moreInside) { - mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); - press_x = x+w/2; - press_y = y+h/2; - } - else { - press_x = event->x; - press_y = event->y; - } - get_window()->set_cursor (*cCropMoving); - } - return true; -} - -bool PreviewWindow::on_button_release_event (GdkEventButton* event) { - - if (!mainCropWin) - return true; - - if (isMoving) { - isMoving = false; - get_window()->set_cursor (*cNormal); - mainCropWin->remoteMoveReady (); - } - return true; -} +/* + * 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 +#include +#include + +PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL),cCropMoving(NULL),cNormal(NULL), isMoving(false), imageArea(NULL) { + + rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); +} + +PreviewWindow::~PreviewWindow () { + + if( cCropMoving ) + delete cCropMoving; + if( cNormal ) + delete cNormal; + +} + +void PreviewWindow::on_realize () { + + Gtk::DrawingArea::on_realize (); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + cCropMoving = new Gdk::Cursor (Gdk::FLEUR); + cNormal = new Gdk::Cursor (Gdk::ARROW); +} + +void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { + + if (mainCropWin) { + int cropX, cropY, cropW, cropH; + mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); + // translate it to screen coordinates + x = imgX + cropX*zoom; + y = imgY + cropY*zoom; + w = cropW * zoom; + h = cropH * zoom; + } +} + +void PreviewWindow::updatePreviewImage () { + + int W = get_width(), H = get_height(); + Glib::RefPtr wind = get_window(); + if( ! wind ) + return; + backBuffer = Gdk::Pixmap::create (wind, W, H, -1); + backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); + if (previewHandler) { + Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); + if (resPixbuf) { + imgW = resPixbuf->get_width(); + imgH = resPixbuf->get_height(); + imgX = (W-imgW)/2; + imgY = (H-imgH)/2; + backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + Cairo::RefPtr cr = backBuffer->create_cairo_context(); + if (previewHandler->getCropParams().enabled) + drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams()); + } + } +} + +void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { + + previewHandler = ph; + if (previewHandler) + previewHandler->addPreviewImageListener (this); +} + +void PreviewWindow::on_resized (Gtk::Allocation& req) { + + updatePreviewImage (); + queue_draw (); +} + +bool PreviewWindow::on_expose_event (GdkEventExpose* event) { + + if (backBuffer) { + Glib::RefPtr window = get_window(); + + int bufferW, bufferH; + backBuffer->get_size (bufferW, bufferH); + + if (!mainCropWin && imageArea) { + mainCropWin = imageArea->getMainCropWindow (); + if (mainCropWin) + mainCropWin->addCropWindowListener (this); + } + + if (get_width()!=bufferW && get_height()!=bufferH) + updatePreviewImage (); + + window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); + + if (mainCropWin) { + Cairo::RefPtr cr = get_window()->create_cairo_context(); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + cr->set_source_rgb (1.0, 1.0, 1.0); + cr->set_line_width (3); + cr->rectangle (x-1.5, y-1.5, w+2, h+2); + cr->stroke (); + cr->set_source_rgb (1.0, 0.0, 0.0); + cr->set_line_width (1); + cr->rectangle (x-1.5, y-1.5, w+2, h+2); + cr->stroke (); + } + } + return true; +} + +void PreviewWindow::previewImageChanged () { + + updatePreviewImage (); + queue_draw (); +} + +void PreviewWindow::setImageArea (ImageArea* ia) { + + imageArea = ia; + mainCropWin = ia->getMainCropWindow (); + if (mainCropWin) + mainCropWin->addCropWindowListener (this); +} + +void PreviewWindow::cropPositionChanged (CropWindow* w) { + + queue_draw (); +} + +void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { + + queue_draw (); +} + +void PreviewWindow::cropZoomChanged (CropWindow* w) { + + queue_draw (); +} + +bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { + + if (!mainCropWin) + return true; + + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; + bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + + if (isMoving) + mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); + else if (inside && !moreInside) + get_window()->set_cursor (*cCropMoving); + else + get_window()->set_cursor (*cNormal); + return true; +} + +bool PreviewWindow::on_button_press_event (GdkEventButton* event) { + + if (!mainCropWin) + return true; + + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; + bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + + if (!isMoving) { + isMoving = true; + if (!inside || moreInside) { + mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); + press_x = x+w/2; + press_y = y+h/2; + } + else { + press_x = event->x; + press_y = event->y; + } + get_window()->set_cursor (*cCropMoving); + } + return true; +} + +bool PreviewWindow::on_button_release_event (GdkEventButton* event) { + + if (!mainCropWin) + return true; + + if (isMoving) { + isMoving = false; + get_window()->set_cursor (*cNormal); + mainCropWin->remoteMoveReady (); + } + return true; +} diff --git a/rtgui/procthread.h b/rtgui/procthread.h index c025bd028..fe0d0a90f 100644 --- a/rtgui/procthread.h +++ b/rtgui/procthread.h @@ -44,9 +44,10 @@ class ProcessingThread { virtual void end () {} void process () { - if (stopped) + if (stopped){ #undef THREAD_PRIORITY_NORMAL thread = Glib::Thread::create(sigc::mem_fun(*this, &ProcessingThread::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); + } } void process_ () { stopped = false; diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index c36049925..53333b088 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -37,6 +37,7 @@ RTWindow::RTWindow () { set_title("RawTherapee "+versionString); property_allow_shrink() = true; set_default_size(options.windowWidth, options.windowHeight); + maximize(); set_modal(false); set_resizable(true); if (options.windowMaximized) @@ -60,6 +61,7 @@ RTWindow::RTWindow () { hbf->set_spacing (2); hbf->show_all (); mainNB->append_page (*fpanel, *hbf); + fpanel->signal_expose_event().connect( sigc::mem_fun(*this, &RTWindow::on_expose_event_fpanel) ); bpanel = new BatchQueuePanel (); bpanel->setParent (this); @@ -71,6 +73,20 @@ RTWindow::RTWindow () { hbb->set_spacing (2); hbb->show_all (); mainNB->append_page (*bpanel, *hbb); + + + epanel = new EditorPanel (fpanel); + epanel->setParent (this); + // decorate tab + Gtk::HBox* hbe = Gtk::manage (new Gtk::HBox ()); + hbe->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::EXECUTE, Gtk::ICON_SIZE_MENU))); + hbe->pack_start (*Gtk::manage (new Gtk::Label("Editor"))); + hbe->set_spacing (2); + hbe->show_all (); + mainNB->append_page (*epanel, *hbe); + mainNB->set_current_page (mainNB->page_num (*fpanel)); + epanel->signal_expose_event().connect( sigc::mem_fun(*this, &RTWindow::on_expose_event_epanel) ); + signal_key_press_event().connect( sigc::mem_fun(*this, &RTWindow::keyPressed) ); @@ -104,6 +120,9 @@ RTWindow::RTWindow () { add (*mainBox); show_all (); + + if(options.tabbedUI) + epanel->hide_all(); } void RTWindow::on_realize () { @@ -164,7 +183,7 @@ void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { epanels[ name ] = ep; filesEdited.insert ( name ); - fpanel->refreshEditedState (filesEdited); + fpanel->refreshEditedState (filesEdited); } void RTWindow::remEditorPanel (EditorPanel* ep) { @@ -212,8 +231,10 @@ void RTWindow::addBatchQueueJob (BatchQueueEntry* bqe, bool head) { bool RTWindow::on_delete_event(GdkEventAny* event) { + fpanel->saveOptions (); bpanel->saveOptions (); + // epanel->saveOptions(); /* if (fileBrowser->getFileCatalog()->getBatchQueue()->hasJobs()) { Gtk::MessageDialog msgd (M("MAIN_MSG_EXITJOBSINQUEUEQUEST"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true); @@ -259,7 +280,7 @@ bool RTWindow::on_delete_event(GdkEventAny* event) { void RTWindow::showPreferences () { - Preferences *pref = new Preferences (); + Preferences *pref = new Preferences (this); pref->run (); delete pref; @@ -297,3 +318,36 @@ void RTWindow::toggle_fullscreen () { void RTWindow::error (Glib::ustring descr){ prLabel.set_text ( descr ); } + +void RTWindow::SetEditorCurrent() +{ + mainNB->set_current_page (mainNB->page_num (*epanel)); +} + +bool RTWindow::on_expose_event_epanel(GdkEventExpose* event) +{ + + if(!options.tabbedUI && epanel->catalogPane->get_children().size() ==0 ){ + FileCatalog *fCatalog = fpanel->fileCatalog; + fpanel->ribbonPane->remove(*fCatalog); + epanel->catalogPane->add(*fCatalog); + fCatalog->fileBrowser->setArrangement(ThumbBrowserBase::TB_Horizontal); + fCatalog->redrawAll(); + } + return false; // Gtk::VBox::on_expose_event(event); +} + + +bool RTWindow::on_expose_event_fpanel(GdkEventExpose* event) +{ + + if(!options.tabbedUI && fpanel->ribbonPane->get_children().size() ==0 ){ + FileCatalog *fCatalog = fpanel->fileCatalog; + epanel->catalogPane->remove(*fCatalog); + //dirpaned->pack2(*fileCatalog,true,true); + fpanel->ribbonPane->add(*fCatalog); + fCatalog->fileBrowser->setArrangement(ThumbBrowserBase::TB_Vertical); + fCatalog->redrawAll(); + } + return false; // Gtk::HPaned::on_expose_event(event); +} \ No newline at end of file diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index 68e072ac9..0e293513d 100644 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -30,7 +30,7 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ private: Gtk::Notebook* mainNB; - FilePanel* fpanel; + FilePanel* fpanel; BatchQueuePanel* bpanel; std::set filesEdited; std::map epanels; @@ -41,7 +41,8 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ bool is_fullscreen; Gtk::Button * btn_fullscreen; - + bool on_expose_event_epanel(GdkEventExpose* event); + bool on_expose_event_fpanel(GdkEventExpose* event); public: RTWindow (); @@ -64,6 +65,8 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ void setProgressState (int state); void error (Glib::ustring descr); rtengine::ProgressListener* getProgressListener () { return pldBridge; } + EditorPanel* epanel; + void SetEditorCurrent(); }; #endif diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index 4038c346e..861d4a12c 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -138,11 +138,11 @@ void ThumbBrowserBase::arrangeFiles () { if (arrangement==TB_Horizontal) { int numOfRows = 1; - if (rowHeight>0) { - numOfRows = (internal.get_height()+rowHeight/2)/rowHeight; - if (numOfRows<1) - numOfRows = 1; - } +// if (rowHeight>0) { +// numOfRows = (internal.get_height()+rowHeight/2)/rowHeight; +// if (numOfRows<1) +// numOfRows = 1; +// } int ct = 0; int currx = 0; int curry = 0; @@ -401,7 +401,7 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { dirty = false; - Glib::RefPtr window = get_window(); + Glib::RefPtr window = get_window(); int w = get_width(); int h = get_height(); @@ -411,14 +411,14 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { Glib::RefPtr context = get_pango_context (); context->set_font_description (get_style()->get_font()); for (int i=0; ifd.size(); i++) { - if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) + if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) parent->fd[i]->updatepriority = false; else { parent->fd[i]->updatepriority = true; parent->fd[i]->draw (); } } - + return true; } @@ -480,7 +480,7 @@ void ThumbBrowserBase::zoomChanged (bool zoomIn) { #ifdef _WIN32 gdk_window_process_updates (get_window()->gobj(), true); #endif -} +} void ThumbBrowserBase::refreshThumbImages () { for (int i=0; i& efiles void ThumbBrowserBase::setArrangement (Arrangement a) { - arrangement = a; + arrangement = a; redraw (); } diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index 2dc38e8b7..e8ffe4b53 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -91,7 +91,7 @@ class ThumbBrowserBase : public Gtk::VBox { void zoomIn () { zoomChanged (true); } void zoomOut () { zoomChanged (false); } - const std::vector& getEntries () { return fd; } + const std::vector& getEntries () { return fd; } void styleChanged (const Glib::RefPtr& style); void redraw (); // arrange files and draw area void refreshThumbImages (); // refresh thumbnail sizes, re-generate thumbnail images, arrange and draw diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 8e9039d31..e94f2605b 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -344,8 +344,8 @@ void ThumbBrowserEntryBase::draw () { Glib::RefPtr gc_ = Gdk::GC::create (w->get_window()); - Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); - Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); + // Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); + // Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); Gdk::Color bgn = w->get_style()->get_bg(Gtk::STATE_NORMAL); Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED); diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index df6bee8bf..cbe7a9121 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -1,175 +1,165 @@ -/* - * 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 -#include - -#define threadNum 4 // IF LCMS GETS THREAD SAFETY WE CAN ENABLE MORE THREADS -ThumbImageUpdater thumbImageUpdater; - -ThumbImageUpdater::ThumbImageUpdater () - : tostop(false), stopped(true), qMutex(NULL), startMutex(NULL) { - - threadPool = new Glib::Thread* [threadNum]; - -} - -ThumbImageUpdater::~ThumbImageUpdater () -{ - delete [] threadPool; -} - -void ThumbImageUpdater::add (Thumbnail* t, const rtengine::procparams::ProcParams& params, int height, bool* priority, ThumbImageUpdateListener* l) { - - if (!qMutex) - qMutex = new Glib::Mutex (); - if (!startMutex) - startMutex = new Glib::Mutex (); - - qMutex->lock (); - // look up if an older version is in the queue - std::list::iterator i; - for (i=jqueue.begin(); i!=jqueue.end(); i++) - if (i->thumbnail==t && i->listener==l) { - i->pparams = params; - i->height = height; - i->priority = priority; - break; - } - // not found, create and append new job - if (i==jqueue.end ()) { - Job j; - j.thumbnail = t; - j.pparams = params; - j.height = height; - j.listener = l; - j.priority = priority; - jqueue.push_back (j); - } - qMutex->unlock (); -} - -void ThumbImageUpdater::process () { - - if (stopped) { - #undef THREAD_PRIORITY_LOW - stopped = false; - thread = Glib::Thread::create(sigc::mem_fun(*this, &ThumbImageUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); - } -} - -void ThumbImageUpdater::process_ () { - - stopped = false; - tostop = false; - - - while (!tostop && !jqueue.empty ()) { - - qMutex->lock (); - int threads = 0; - for (; threads::iterator i; - for (i=jqueue.begin (); i!=jqueue.end(); i++) - if (*(i->priority)) - break; - if (i==jqueue.end()) - i = jqueue.begin(); - Job current = *i; - jqueue.erase (i); - if (current.listener) - threadPool[threads] = Glib::Thread::create(sigc::bind(sigc::mem_fun(*this, &ThumbImageUpdater::processJob), current), 0, true, true, Glib::THREAD_PRIORITY_LOW); - //else - // threadPool[threads] = NULL; - } - qMutex->unlock (); - - for (int j=0; jjoin (); - - for(int j =0; j processThumbImage (current.pparams, current.height, scale); - if (img) - current.listener->updateImage (img, scale, current.pparams.crop); - } - -} - -void ThumbImageUpdater::stop () { - - if (stopped) { - tostop = true; - return; } - - gdk_threads_leave(); - tostop = true; - Glib::Thread::self()->yield(); - if (!stopped) - thread->join (); - gdk_threads_enter(); -} - -void ThumbImageUpdater::removeJobs () { - - if (!qMutex) - return; - - qMutex->lock (); - while (!jqueue.empty()) - jqueue.pop_front (); - qMutex->unlock (); -} - -void ThumbImageUpdater::removeJobs (ThumbImageUpdateListener* listener) { - - if (!qMutex) - return; - - qMutex->lock (); - bool ready = false; - while (!ready) { - ready = true; - std::list::iterator i; - for (i=jqueue.begin(); i!=jqueue.end(); i++) - if (i->listener == listener) { - jqueue.erase (i); - ready = false; - break; - } - } - qMutex->unlock (); -} - -void ThumbImageUpdater::terminate () { - - stop (); - removeJobs (); -} - - +/* + * 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 +#include + +#define threadNum 8 +ThumbImageUpdater thumbImageUpdater; + +ThumbImageUpdater::ThumbImageUpdater () + : tostop(false), stopped(true), qMutex(NULL), startMutex(NULL), threadPool(NULL) { + +} + +ThumbImageUpdater::~ThumbImageUpdater () +{ + delete threadPool; +} + +void ThumbImageUpdater::add (Thumbnail* t, const rtengine::procparams::ProcParams& params, int height, bool* priority, ThumbImageUpdateListener* l) { + + if (!qMutex) + qMutex = new Glib::Mutex (); + if (!startMutex) + startMutex = new Glib::Mutex (); + + qMutex->lock (); + // look up if an older version is in the queue + std::list::iterator i; + for (i=jqueue.begin(); i!=jqueue.end(); i++) + if (i->thumbnail==t && i->listener==l) { + i->pparams = params; + i->height = height; + i->priority = priority; + break; + } + // not found, create and append new job + if (i==jqueue.end ()) { + Job j; + j.thumbnail = t; + j.pparams = params; + j.height = height; + j.listener = l; + j.priority = priority; + jqueue.push_back (j); + } + qMutex->unlock (); +} + +void ThumbImageUpdater::process () { + + if (stopped) { + stopped = false; + + if(!threadPool) + threadPool = new Glib::ThreadPool(threadNum,0); + + //thread = Glib::Thread::create (sigc::mem_fun(*this, &ThumbImageUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); + process_(); + } +} + +void ThumbImageUpdater::process_ () { + + stopped = false; + tostop = false; + + while (!tostop && !jqueue.empty ()) { + + std::list::iterator i; + for (i=jqueue.begin (); i!=jqueue.end(); i++) + if (*(i->priority)) + break; + + if (i==jqueue.end()) + i = jqueue.begin(); + + Job current = *i; + if (current.listener) + threadPool->push(sigc::bind(sigc::mem_fun(*this, &ThumbImageUpdater::processJob), current)); + + jqueue.erase (i); + } + + stopped = true; + //printf("Threads # %d \n", threadPool->get_num_threads()); + +} + +void ThumbImageUpdater::processJob (Job current) { + + if (current.listener) { + double scale = 1.0; + rtengine::IImage8* img = current.thumbnail->processThumbImage (current.pparams, current.height, scale); + if (img) + current.listener->updateImage (img, scale, current.pparams.crop); + } + +} + +void ThumbImageUpdater::stop () { + + gdk_threads_leave(); + tostop = true; + + if (threadPool) { + threadPool->shutdown(TRUE); + threadPool = NULL; + } + gdk_threads_enter(); +} + +void ThumbImageUpdater::removeJobs () { + + if (!qMutex) + return; + + qMutex->lock (); + while (!jqueue.empty()) + jqueue.pop_front (); + qMutex->unlock (); +} + +void ThumbImageUpdater::removeJobs (ThumbImageUpdateListener* listener) { + + if (!qMutex) + return; + + qMutex->lock (); + bool ready = false; + while (!ready) { + ready = true; + std::list::iterator i; + for (i=jqueue.begin(); i!=jqueue.end(); i++) + if (i->listener == listener) { + jqueue.erase (i); + ready = false; + break; + } + } + qMutex->unlock (); +} + +void ThumbImageUpdater::terminate () { + + stop (); + removeJobs (); +} + + diff --git a/rtgui/thumbimageupdater.h b/rtgui/thumbimageupdater.h index 16bc8ec50..909b90754 100644 --- a/rtgui/thumbimageupdater.h +++ b/rtgui/thumbimageupdater.h @@ -1,68 +1,70 @@ -/* - * 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 _THUMBIMAGEUPDATER_ -#define _THUMBIMAGEUPDATER_ - -#include -#include -#include - -class ThumbImageUpdateListener { - - public: - virtual void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {} -}; - -class ThumbImageUpdater { - - struct Job { - Thumbnail* thumbnail; - rtengine::procparams::ProcParams pparams; - int height; - bool* priority; - ThumbImageUpdateListener* listener; - }; - - protected: - bool tostop; - bool stopped; - std::list jqueue; - Glib::Thread* thread; - Glib::Mutex* qMutex; - Glib::Mutex* startMutex; - Glib::Thread **threadPool; - - public: - ThumbImageUpdater (); - ~ThumbImageUpdater (); - - void add (Thumbnail* t, const rtengine::procparams::ProcParams& params, int height, bool* priority, ThumbImageUpdateListener* l); - void process (); - void stop (); - void removeJobs (); - void removeJobs (ThumbImageUpdateListener* listener); - void terminate (); - - void process_ (); - void processJob (Job current); -}; - -extern ThumbImageUpdater thumbImageUpdater; - -#endif +/* + * 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 _THUMBIMAGEUPDATER_ +#define _THUMBIMAGEUPDATER_ + +#include +#include +#include +#include + +class ThumbImageUpdateListener { + + public: + virtual void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {} +}; + +class ThumbImageUpdater { + + struct Job { + Thumbnail* thumbnail; + rtengine::procparams::ProcParams pparams; + int height; + bool* priority; + ThumbImageUpdateListener* listener; + }; + + protected: + bool tostop; + bool stopped; + std::list jqueue; + Glib::Thread* thread; + Glib::Mutex* qMutex; + Glib::Mutex* startMutex; + //Glib::Thread **threadPool; + Glib::ThreadPool * threadPool; + + public: + ThumbImageUpdater (); + ~ThumbImageUpdater (); + + void add (Thumbnail* t, const rtengine::procparams::ProcParams& params, int height, bool* priority, ThumbImageUpdateListener* l); + void process (); + void stop (); + void removeJobs (); + void removeJobs (ThumbImageUpdateListener* listener); + void terminate (); + + void process_ (); + void processJob (Job current); +}; + +extern ThumbImageUpdater thumbImageUpdater; + +#endif diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index e1f7059b4..51837a727 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -254,7 +254,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool void ToolPanelCoordinator::closeImage () { if (ipc) { - ipc->stopProcessing (); + ipc->stopProcessing (); ipc = NULL; } } diff --git a/tools/generateTranslationDiffs.sh b/tools/generateTranslationDiffs.sh old mode 100755 new mode 100644