Partially solving issue 1788: "Crashing during processing of queue"
It also correct a bug of wrong image orientation (was wrong in the File Browser while good in the Editor tab) This patch also introduce several speed optimizations like: - switch between File Browser and Editor tab in Single Editor mode - asynchronous computation of the Batch Queue's thumbnails - quick start of RT even with a huge queue - less GUI overhead when applying a profile to multiple thumbs in the File Browser
This commit is contained in:
@@ -72,7 +72,9 @@ option (BUILD_SHARED "Build rawtherapee with shared libraries" OFF)
|
|||||||
option (WITH_BZIP "Build with Bzip2 support" ON)
|
option (WITH_BZIP "Build with Bzip2 support" ON)
|
||||||
option (WITH_MYFILE_MMAP "Build using memory mapped file" ON)
|
option (WITH_MYFILE_MMAP "Build using memory mapped file" ON)
|
||||||
option (OPTION_OMP "Build with OpenMP support" ON)
|
option (OPTION_OMP "Build with OpenMP support" ON)
|
||||||
option (BUILD_BUNDLE "Self-contained build" OFF)
|
option (PROTECT_VECTORS "Protect critical vectors by custom R/W Mutex, recommanded even if your std::vector is thread safe" ON)
|
||||||
|
option (TRACE_MYRWMUTEX "Trace RT's custom R/W Mutex (Debug builds only); redirecting std::out to a file is strongly recommended!" OFF)
|
||||||
|
option (AUTO_GDK_FLUSH "Use gdk_flush on all gdk_thread_leave other than the GUI thread; set it ON if you experience X Server warning/errors" OFF)
|
||||||
|
|
||||||
# set install directories
|
# set install directories
|
||||||
if (WIN32 OR APPLE)
|
if (WIN32 OR APPLE)
|
||||||
@@ -160,6 +162,25 @@ if (NOT BUILD_BUNDLE AND
|
|||||||
message (FATAL_ERROR "The paths has to be absolute or use -DBUILD_BUNDLE=ON")
|
message (FATAL_ERROR "The paths has to be absolute or use -DBUILD_BUNDLE=ON")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# MyRWMutex
|
||||||
|
if (PROTECT_VECTORS)
|
||||||
|
add_definitions (-DPROTECT_VECTORS=1)
|
||||||
|
else (PROTECT_VECTORS)
|
||||||
|
add_definitions (-DPROTECT_VECTORS=0)
|
||||||
|
endif (PROTECT_VECTORS)
|
||||||
|
if (TRACE_MYRWMUTEX)
|
||||||
|
# Note: it will be set to 0 for Debug builds (rtgui/guiutils.h)
|
||||||
|
add_definitions (-DTRACE_MYRWMUTEX=1)
|
||||||
|
else (TRACE_MYRWMUTEX)
|
||||||
|
add_definitions (-DTRACE_MYRWMUTEX=0)
|
||||||
|
endif (TRACE_MYRWMUTEX)
|
||||||
|
|
||||||
|
if (AUTO_GDK_FLUSH)
|
||||||
|
add_definitions (-DAUTO_GDK_FLUSH=1)
|
||||||
|
else (AUTO_GDK_FLUSH)
|
||||||
|
add_definitions (-DAUTO_GDK_FLUSH=0)
|
||||||
|
endif (AUTO_GDK_FLUSH)
|
||||||
|
|
||||||
# check for libraries
|
# check for libraries
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules (GTK REQUIRED gtk+-2.0>=2.12)
|
pkg_check_modules (GTK REQUIRED gtk+-2.0>=2.12)
|
||||||
|
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
namespace rtengine {
|
namespace rtengine {
|
||||||
|
|
||||||
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, int deg) {
|
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh) {
|
||||||
|
|
||||||
StdImageSource imgSrc;
|
StdImageSource imgSrc;
|
||||||
if (imgSrc.load(fname)) {
|
if (imgSrc.load(fname)) {
|
||||||
@@ -48,10 +48,6 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageIO* img = imgSrc.getImageIO();
|
ImageIO* img = imgSrc.getImageIO();
|
||||||
|
|
||||||
if (deg) {
|
|
||||||
img->rotate(deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thumbnail* tpp = new Thumbnail ();
|
Thumbnail* tpp = new Thumbnail ();
|
||||||
|
|
||||||
@@ -607,10 +603,10 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
|||||||
int rwidth;
|
int rwidth;
|
||||||
if (params.coarse.rotate==90 || params.coarse.rotate==270) {
|
if (params.coarse.rotate==90 || params.coarse.rotate==270) {
|
||||||
rwidth = rheight;
|
rwidth = rheight;
|
||||||
rheight = thumbImg->height * rwidth / thumbImg->width;
|
rheight = int(size_t(thumbImg->height) * size_t(rwidth) / size_t(thumbImg->width));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rwidth = thumbImg->width * rheight / thumbImg->height;
|
rwidth = int(size_t(thumbImg->width) * size_t(rheight) / size_t(thumbImg->height));
|
||||||
|
|
||||||
Imagefloat* baseImg = resizeTo<Imagefloat>(rwidth, rheight, interp, thumbImg);
|
Imagefloat* baseImg = resizeTo<Imagefloat>(rwidth, rheight, interp, thumbImg);
|
||||||
|
|
||||||
|
@@ -81,7 +81,7 @@ namespace rtengine {
|
|||||||
|
|
||||||
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
|
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
|
||||||
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
|
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
|
||||||
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, int deg=0);
|
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh);
|
||||||
|
|
||||||
void getCamWB (double& temp, double& green);
|
void getCamWB (double& temp, double& green);
|
||||||
void getAutoWB (double& temp, double& green);
|
void getAutoWB (double& temp, double& green);
|
||||||
|
@@ -65,6 +65,17 @@ BatchQueue::~BatchQueue ()
|
|||||||
delete pmenu;
|
delete pmenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BatchQueue::resizeLoadedQueue() {
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t i=0; i<fd.size(); i++) {
|
||||||
|
fd.at(i)->resize(getThumbnailHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reduce the max size of a thumb, since thumb is processed synchronously on adding to queue
|
// Reduce the max size of a thumb, since thumb is processed synchronously on adding to queue
|
||||||
// leading to very long waiting when adding more images
|
// leading to very long waiting when adding more images
|
||||||
int BatchQueue::calcMaxThumbnailHeight() {
|
int BatchQueue::calcMaxThumbnailHeight() {
|
||||||
@@ -76,23 +87,37 @@ int BatchQueue::getMaxThumbnailHeight() const {
|
|||||||
return calcMaxThumbnailHeight();
|
return calcMaxThumbnailHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BatchQueue::saveThumbnailHeight (int height) {
|
||||||
|
options.thumbSizeQueue = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BatchQueue::getThumbnailHeight () {
|
||||||
|
// The user could have manually forced the option to a too big value
|
||||||
|
return std::max(std::min(options.thumbSizeQueue, 200), 10);
|
||||||
|
}
|
||||||
|
|
||||||
void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) {
|
void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) {
|
||||||
|
|
||||||
pmenu->popup (3, this->eventTime);
|
pmenu->popup (3, this->eventTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::addEntries ( std::vector<BatchQueueEntry*> &entries, bool head)
|
void BatchQueue::addEntries ( std::vector<BatchQueueEntry*> &entries, bool head, bool save)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for( std::vector<BatchQueueEntry*>::iterator entry = entries.begin(); entry != entries.end();entry++ ){
|
for( std::vector<BatchQueueEntry*>::iterator entry = entries.begin(); entry != entries.end();entry++ ){
|
||||||
(*entry)->setParent (this);
|
(*entry)->setParent (this);
|
||||||
(*entry)->resize (std::min(options.thumbSize, getMaxThumbnailHeight())); // batch queue might have smaller, restricted size
|
|
||||||
|
// BatchQueueButtonSet HAVE TO be added before resizing to take them into account
|
||||||
|
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (*entry);
|
||||||
|
bqbs->setButtonListener (this);
|
||||||
|
(*entry)->addButtonSet (bqbs);
|
||||||
|
|
||||||
|
(*entry)->resize (getThumbnailHeight()); // batch queue might have smaller, restricted size
|
||||||
Glib::ustring tempFile = getTempFilenameForParams( (*entry)->filename );
|
Glib::ustring tempFile = getTempFilenameForParams( (*entry)->filename );
|
||||||
|
|
||||||
// recovery save
|
// recovery save
|
||||||
@@ -114,13 +139,11 @@ void BatchQueue::addEntries ( std::vector<BatchQueueEntry*> &entries, bool head)
|
|||||||
}
|
}
|
||||||
if ((*entry)->thumbnail)
|
if ((*entry)->thumbnail)
|
||||||
(*entry)->thumbnail->imageEnqueued ();
|
(*entry)->thumbnail->imageEnqueued ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (*entry);
|
if (save)
|
||||||
bqbs->setButtonListener (this);
|
saveBatchQueue( );
|
||||||
(*entry)->addButtonSet (bqbs);
|
|
||||||
}
|
|
||||||
saveBatchQueue( );
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
notifyListener (false);
|
notifyListener (false);
|
||||||
@@ -135,6 +158,12 @@ bool BatchQueue::saveBatchQueue( )
|
|||||||
if (f==NULL)
|
if (f==NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (fd.size())
|
if (fd.size())
|
||||||
// The column's header is mandatory (the first line will be skipped when loaded)
|
// The column's header is mandatory (the first line will be skipped when loaded)
|
||||||
fprintf(f,"input image full path|param file full path|output image full path|file format|jpeg quality|jpeg subsampling|"
|
fprintf(f,"input image full path|param file full path|output image full path|file format|jpeg quality|jpeg subsampling|"
|
||||||
@@ -152,186 +181,186 @@ bool BatchQueue::saveBatchQueue( )
|
|||||||
bqe->saveFormat.saveParams, bqe->forceFormatOpts
|
bqe->saveFormat.saveParams, bqe->forceFormatOpts
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fclose (f);
|
fclose (f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::loadBatchQueue( )
|
bool BatchQueue::loadBatchQueue( )
|
||||||
{
|
{
|
||||||
{
|
Glib::ustring savedQueueFile;
|
||||||
|
savedQueueFile = options.rtdir+"/batch/queue.csv";
|
||||||
|
FILE *f = safe_g_fopen (savedQueueFile, "rt");
|
||||||
|
|
||||||
|
if (f!=NULL) {
|
||||||
|
char *buffer = new char[1024];
|
||||||
|
unsigned numLoaded=0;
|
||||||
|
// skipping the first line
|
||||||
|
bool firstLine=true;
|
||||||
|
|
||||||
|
// Yes, it's better to get the lock for the whole file reading,
|
||||||
|
// to update the list in one shot without any other concurrent access!
|
||||||
|
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Glib::ustring savedQueueFile;
|
while (fgets (buffer, 1024, f)){
|
||||||
savedQueueFile = options.rtdir+"/batch/queue.csv";
|
|
||||||
FILE *f = safe_g_fopen (savedQueueFile, "rt");
|
|
||||||
|
|
||||||
if (f!=NULL) {
|
if (firstLine) {
|
||||||
char *buffer = new char[1024];
|
// skipping the column's title line
|
||||||
unsigned numLoaded=0;
|
firstLine=false;
|
||||||
// skipping the first line
|
continue;
|
||||||
bool firstLine=true;
|
}
|
||||||
while (fgets (buffer, 1024, f)){
|
|
||||||
|
|
||||||
if (firstLine) {
|
size_t pos;
|
||||||
// skipping the column's title line
|
Glib::ustring source;
|
||||||
firstLine=false;
|
Glib::ustring paramsFile;
|
||||||
continue;
|
Glib::ustring outputFile;
|
||||||
}
|
Glib::ustring saveFmt(options.saveFormat.format);
|
||||||
|
int jpegQuality=options.saveFormat.jpegQuality, jpegSubSamp =options.saveFormat.jpegSubSamp;
|
||||||
|
int pngBits =options.saveFormat.pngBits, pngCompression =options.saveFormat.pngCompression;
|
||||||
|
int tiffBits =options.saveFormat.tiffBits, tiffUncompressed=options.saveFormat.tiffUncompressed;
|
||||||
|
int saveParams =options.saveFormat.saveParams;
|
||||||
|
int forceFormatOpts =options.forceFormatOpts;
|
||||||
|
|
||||||
size_t pos;
|
Glib::ustring currLine(buffer);
|
||||||
Glib::ustring source;
|
int a = 0;
|
||||||
Glib::ustring paramsFile;
|
if (currLine.rfind('\n') != Glib::ustring::npos) a++;
|
||||||
Glib::ustring outputFile;
|
if (currLine.rfind('\r') != Glib::ustring::npos) a++;
|
||||||
Glib::ustring saveFmt(options.saveFormat.format);
|
if (a)
|
||||||
int jpegQuality=options.saveFormat.jpegQuality, jpegSubSamp =options.saveFormat.jpegSubSamp;
|
currLine = currLine.substr(0, currLine.length()-a);
|
||||||
int pngBits =options.saveFormat.pngBits, pngCompression =options.saveFormat.pngCompression;
|
|
||||||
int tiffBits =options.saveFormat.tiffBits, tiffUncompressed=options.saveFormat.tiffUncompressed;
|
|
||||||
int saveParams =options.saveFormat.saveParams;
|
|
||||||
int forceFormatOpts =options.forceFormatOpts;
|
|
||||||
|
|
||||||
Glib::ustring currLine(buffer);
|
// Looking for the image's full path
|
||||||
int a = 0;
|
pos = currLine.find('|');
|
||||||
if (currLine.rfind('\n') != Glib::ustring::npos) a++;
|
if (pos != Glib::ustring::npos) {
|
||||||
if (currLine.rfind('\r') != Glib::ustring::npos) a++;
|
source = currLine.substr(0, pos);
|
||||||
if (a)
|
currLine = currLine.substr(pos+1);
|
||||||
currLine = currLine.substr(0, currLine.length()-a);
|
|
||||||
|
|
||||||
// Looking for the image's full path
|
// Looking for the procparams' full path
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
source = currLine.substr(0, pos);
|
paramsFile = currLine.substr(0, pos);
|
||||||
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
|
// Looking for the full output path; if empty, it'll use the template string
|
||||||
|
pos = currLine.find('|');
|
||||||
|
if (pos != Glib::ustring::npos) {
|
||||||
|
outputFile = currLine.substr(0, pos);
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the procparams' full path
|
// No need to bother reading the last options, they will be ignored if outputFile is empty!
|
||||||
pos = currLine.find('|');
|
if (!outputFile.empty()) {
|
||||||
if (pos != Glib::ustring::npos) {
|
|
||||||
paramsFile = currLine.substr(0, pos);
|
|
||||||
currLine = currLine.substr(pos+1);
|
|
||||||
|
|
||||||
// Looking for the full output path; if empty, it'll use the template string
|
// Looking for the saving format
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
outputFile = currLine.substr(0, pos);
|
saveFmt = currLine.substr(0, pos);
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// No need to bother reading the last options, they will be ignored if outputFile is empty!
|
// Looking for the jpeg quality
|
||||||
if (!outputFile.empty()) {
|
pos = currLine.find('|');
|
||||||
|
if (pos != Glib::ustring::npos) {
|
||||||
|
jpegQuality = atoi(currLine.substr(0, pos).c_str());
|
||||||
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the saving format
|
// Looking for the jpeg subsampling
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
saveFmt = currLine.substr(0, pos);
|
jpegSubSamp = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the jpeg quality
|
// Looking for the png bit depth
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
jpegQuality = atoi(currLine.substr(0, pos).c_str());
|
pngBits = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the jpeg subsampling
|
// Looking for the png compression
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
jpegSubSamp = atoi(currLine.substr(0, pos).c_str());
|
pngCompression = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the png bit depth
|
// Looking for the tiff bit depth
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
pngBits = atoi(currLine.substr(0, pos).c_str());
|
tiffBits = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the png compression
|
// Looking for the tiff uncompression
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
pngCompression = atoi(currLine.substr(0, pos).c_str());
|
tiffUncompressed = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the tiff bit depth
|
// Looking out if we have to save the procparams
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
tiffBits = atoi(currLine.substr(0, pos).c_str());
|
saveParams = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking for the tiff uncompression
|
// Looking out if we have to to use the format options
|
||||||
pos = currLine.find('|');
|
pos = currLine.find('|');
|
||||||
if (pos != Glib::ustring::npos) {
|
if (pos != Glib::ustring::npos) {
|
||||||
tiffUncompressed = atoi(currLine.substr(0, pos).c_str());
|
forceFormatOpts = atoi(currLine.substr(0, pos).c_str());
|
||||||
currLine = currLine.substr(pos+1);
|
// currLine = currLine.substr(pos+1);
|
||||||
|
|
||||||
// Looking out if we have to save the procparams
|
}}}}}}}}}}}}}
|
||||||
pos = currLine.find('|');
|
|
||||||
if (pos != Glib::ustring::npos) {
|
|
||||||
saveParams = atoi(currLine.substr(0, pos).c_str());
|
|
||||||
currLine = currLine.substr(pos+1);
|
|
||||||
|
|
||||||
// Looking out if we have to to use the format options
|
if( !source.empty() && !paramsFile.empty() ){
|
||||||
pos = currLine.find('|');
|
rtengine::procparams::ProcParams pparams;
|
||||||
if (pos != Glib::ustring::npos) {
|
if( pparams.load( paramsFile ) )
|
||||||
forceFormatOpts = atoi(currLine.substr(0, pos).c_str());
|
continue;
|
||||||
// currLine = currLine.substr(pos+1);
|
|
||||||
|
|
||||||
}}}}}}}}}}}}}
|
::Thumbnail *thumb = cacheMgr->getEntry( source, &pparams );
|
||||||
|
if( thumb ){
|
||||||
|
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create(source, thumb->getType() == FT_Raw, pparams);
|
||||||
|
|
||||||
if( !source.empty() && !paramsFile.empty() ){
|
int prevh = getMaxThumbnailHeight();
|
||||||
rtengine::procparams::ProcParams pparams;
|
int prevw = prevh;
|
||||||
if( pparams.load( paramsFile ) )
|
thumb->getThumbnailSize (prevw, prevh);
|
||||||
continue;
|
|
||||||
|
|
||||||
::Thumbnail *thumb = cacheMgr->getEntry( source );
|
BatchQueueEntry *entry = new BatchQueueEntry(job, pparams,source, prevw, prevh, thumb);
|
||||||
if( thumb ){
|
entry->setParent(this);
|
||||||
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create(source, thumb->getType() == FT_Raw, pparams);
|
|
||||||
|
|
||||||
int prevh = getMaxThumbnailHeight();
|
// BatchQueueButtonSet HAVE TO be added before resizing to take them into account
|
||||||
int prevw = prevh;
|
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet(entry);
|
||||||
guint8* prev = NULL;
|
bqbs->setButtonListener(this);
|
||||||
double tmpscale;
|
entry->addButtonSet(bqbs);
|
||||||
rtengine::IImage8* img = thumb->processThumbImage(pparams, prevh, tmpscale);
|
|
||||||
if (img) {
|
|
||||||
prevw = img->getWidth();
|
|
||||||
prevh = img->getHeight();
|
|
||||||
prev = new guint8[prevw * prevh * 3];
|
|
||||||
memcpy(prev, img->getData(), prevw * prevh * 3);
|
|
||||||
img->free();
|
|
||||||
}
|
|
||||||
BatchQueueEntry *entry = new BatchQueueEntry(job, pparams,source, prev, prevw, prevh, thumb);
|
|
||||||
entry->setParent(this);
|
|
||||||
entry->resize(options.thumbSize);
|
|
||||||
entry->savedParamsFile = paramsFile;
|
|
||||||
entry->selected = false;
|
|
||||||
entry->outFileName = outputFile;
|
|
||||||
if (!outputFile.empty()) {
|
|
||||||
entry->saveFormat.format = saveFmt;
|
|
||||||
entry->saveFormat.jpegQuality = jpegQuality;
|
|
||||||
entry->saveFormat.jpegSubSamp = jpegSubSamp;
|
|
||||||
entry->saveFormat.pngBits = pngBits;
|
|
||||||
entry->saveFormat.pngCompression = pngCompression;
|
|
||||||
entry->saveFormat.tiffBits = tiffBits;
|
|
||||||
entry->saveFormat.tiffUncompressed = tiffUncompressed!=0;
|
|
||||||
entry->saveFormat.saveParams = saveParams!=0;
|
|
||||||
entry->forceFormatOpts = forceFormatOpts!=0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
entry->forceFormatOpts = false;
|
|
||||||
fd.push_back(entry);
|
|
||||||
|
|
||||||
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet(entry);
|
//entry->resize(getThumbnailHeight());
|
||||||
bqbs->setButtonListener(this);
|
entry->savedParamsFile = paramsFile;
|
||||||
entry->addButtonSet(bqbs);
|
entry->selected = false;
|
||||||
numLoaded++;
|
entry->outFileName = outputFile;
|
||||||
|
if (!outputFile.empty()) {
|
||||||
|
entry->saveFormat.format = saveFmt;
|
||||||
|
entry->saveFormat.jpegQuality = jpegQuality;
|
||||||
|
entry->saveFormat.jpegSubSamp = jpegSubSamp;
|
||||||
|
entry->saveFormat.pngBits = pngBits;
|
||||||
|
entry->saveFormat.pngCompression = pngCompression;
|
||||||
|
entry->saveFormat.tiffBits = tiffBits;
|
||||||
|
entry->saveFormat.tiffUncompressed = tiffUncompressed!=0;
|
||||||
|
entry->saveFormat.saveParams = saveParams!=0;
|
||||||
|
entry->forceFormatOpts = forceFormatOpts!=0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
entry->forceFormatOpts = false;
|
||||||
|
fd.push_back(entry);
|
||||||
|
|
||||||
|
numLoaded++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete [] buffer;
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
delete [] buffer;
|
||||||
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
notifyListener(false);
|
notifyListener(false);
|
||||||
|
|
||||||
|
return !fd.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename )
|
Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename )
|
||||||
@@ -359,13 +388,13 @@ int cancelItemUI (void* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<items->size(); i++) {
|
for (size_t i=0; i<items->size(); i++) {
|
||||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||||
if (entry->processing)
|
if (entry->processing)
|
||||||
continue;
|
continue;
|
||||||
@@ -382,59 +411,61 @@ void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
|||||||
fd[i]->selected = false;
|
fd[i]->selected = false;
|
||||||
lastClicked = NULL;
|
lastClicked = NULL;
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
|
|
||||||
saveBatchQueue( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveBatchQueue( );
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
notifyListener (false);
|
notifyListener (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::headItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
void BatchQueue::headItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
for (int i=items->size()-1; i>=0; i--) {
|
|
||||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
for (int i=items->size()-1; i>=0; i--) {
|
||||||
if (entry->processing)
|
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||||
continue;
|
if (entry->processing)
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
continue;
|
||||||
if (pos!=fd.end() && pos!=fd.begin()) {
|
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
||||||
fd.erase (pos);
|
if (pos!=fd.end() && pos!=fd.begin()) {
|
||||||
// find the first item that is not under processing
|
fd.erase (pos);
|
||||||
for (pos=fd.begin(); pos!=fd.end(); pos++)
|
// find the first item that is not under processing
|
||||||
if (!(*pos)->processing) {
|
for (pos=fd.begin(); pos!=fd.end(); pos++)
|
||||||
fd.insert (pos, entry);
|
if (!(*pos)->processing) {
|
||||||
break;
|
fd.insert (pos, entry);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveBatchQueue( );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
saveBatchQueue( );
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
for (size_t i=0; i<items->size(); i++) {
|
|
||||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
for (size_t i=0; i<items->size(); i++) {
|
||||||
if (entry->processing)
|
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||||
continue;
|
if (entry->processing)
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
continue;
|
||||||
if (pos!=fd.end()) {
|
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
||||||
fd.erase (pos);
|
if (pos!=fd.end()) {
|
||||||
fd.push_back (entry);
|
fd.erase (pos);
|
||||||
}
|
fd.push_back (entry);
|
||||||
}
|
}
|
||||||
saveBatchQueue( );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
saveBatchQueue( );
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
}
|
}
|
||||||
@@ -442,13 +473,13 @@ void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
|||||||
void BatchQueue::selectAll () {
|
void BatchQueue::selectAll () {
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lastClicked = NULL;
|
lastClicked = NULL;
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
for (size_t i=0; i<fd.size(); i++) {
|
for (size_t i=0; i<fd.size(); i++) {
|
||||||
if (fd[i]->processing)
|
if (fd[i]->processing)
|
||||||
continue;
|
continue;
|
||||||
fd[i]->selected = true;
|
fd[i]->selected = true;
|
||||||
@@ -459,17 +490,18 @@ void BatchQueue::selectAll () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::startProcessing () {
|
void BatchQueue::startProcessing () {
|
||||||
if (!processing && !fd.empty()) {
|
|
||||||
BatchQueueEntry* next;
|
|
||||||
|
|
||||||
{
|
if (!processing) {
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
next = static_cast<BatchQueueEntry*>(fd[0]);
|
if (!fd.empty()) {
|
||||||
// tag it as processing
|
BatchQueueEntry* next;
|
||||||
|
|
||||||
|
next = static_cast<BatchQueueEntry*>(fd[0]);
|
||||||
|
// tag it as processing
|
||||||
next->processing = true;
|
next->processing = true;
|
||||||
processing = next;
|
processing = next;
|
||||||
// remove from selection
|
// remove from selection
|
||||||
@@ -480,13 +512,17 @@ void BatchQueue::startProcessing () {
|
|||||||
processing->selected = false;
|
processing->selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// remove button set
|
// remove button set
|
||||||
next->removeButtonSet ();
|
next->removeButtonSet ();
|
||||||
}
|
|
||||||
|
|
||||||
// start batch processing
|
// start batch processing
|
||||||
rtengine::startBatchProcessing (next->job, this, options.tunnelMetaData);
|
rtengine::startBatchProcessing (next->job, this, options.tunnelMetaData);
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,11 +558,11 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
|
|||||||
err = img->saveAsJPEG (fname, saveFormat.jpegQuality, saveFormat.jpegSubSamp);
|
err = img->saveAsJPEG (fname, saveFormat.jpegQuality, saveFormat.jpegSubSamp);
|
||||||
img->free ();
|
img->free ();
|
||||||
|
|
||||||
if (err) throw "Unable to save output file";
|
if (err) throw "Unable to save output file";
|
||||||
|
|
||||||
if (saveFormat.saveParams) {
|
if (saveFormat.saveParams) {
|
||||||
// We keep the extension to avoid overwriting the profile when we have
|
// We keep the extension to avoid overwriting the profile when we have
|
||||||
// the same output filename with different extension
|
// the same output filename with different extension
|
||||||
//processing->params.save (removeExtension(fname) + paramFileExtension);
|
//processing->params.save (removeExtension(fname) + paramFileExtension);
|
||||||
processing->params.save (fname + ".out" + paramFileExtension);
|
processing->params.save (fname + ".out" + paramFileExtension);
|
||||||
}
|
}
|
||||||
@@ -542,11 +578,11 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
|
|||||||
// delete from the queue
|
// delete from the queue
|
||||||
delete processing; processing = NULL;
|
delete processing; processing = NULL;
|
||||||
bool queueEmptied=false;
|
bool queueEmptied=false;
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fd.erase (fd.begin());
|
fd.erase (fd.begin());
|
||||||
|
|
||||||
@@ -555,8 +591,8 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
|
|||||||
queueEmptied=true;
|
queueEmptied=true;
|
||||||
}
|
}
|
||||||
else if (listener && listener->canStartNext ()) {
|
else if (listener && listener->canStartNext ()) {
|
||||||
BatchQueueEntry* next = static_cast<BatchQueueEntry*>(fd[0]);
|
BatchQueueEntry* next = static_cast<BatchQueueEntry*>(fd[0]);
|
||||||
// tag it as selected
|
// tag it as selected
|
||||||
next->processing = true;
|
next->processing = true;
|
||||||
processing = next;
|
processing = next;
|
||||||
// remove from selection
|
// remove from selection
|
||||||
@@ -567,21 +603,34 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
|
|||||||
processing->selected = false;
|
processing->selected = false;
|
||||||
}
|
}
|
||||||
// remove button set
|
// remove button set
|
||||||
|
{
|
||||||
|
// ButtonSet have Cairo::Surface which might be rendered while we're trying to delete them
|
||||||
|
GThreadLock lock;
|
||||||
next->removeButtonSet ();
|
next->removeButtonSet ();
|
||||||
}
|
|
||||||
if (saveBatchQueue( )) {
|
|
||||||
safe_g_remove( processedParams );
|
|
||||||
// Delete all files in directory \batch when finished, just to be sure to remove zombies
|
|
||||||
if( fd.empty() ){
|
|
||||||
std::vector<Glib::ustring> names;
|
|
||||||
Glib::ustring batchdir = options.rtdir+"/batch/";
|
|
||||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (batchdir);
|
|
||||||
safe_build_file_list (dir, names, batchdir);
|
|
||||||
for(std::vector<Glib::ustring>::iterator iter=names.begin(); iter != names.end();iter++ )
|
|
||||||
safe_g_remove( *iter );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (saveBatchQueue( )) {
|
||||||
|
safe_g_remove( processedParams );
|
||||||
|
// Delete all files in directory \batch when finished, just to be sure to remove zombies
|
||||||
|
|
||||||
|
// Not sure that locking is necessary, but it should be safer
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
if( fd.empty() ){
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
std::vector<Glib::ustring> names;
|
||||||
|
Glib::ustring batchdir = options.rtdir+"/batch/";
|
||||||
|
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (batchdir);
|
||||||
|
safe_build_file_list (dir, names, batchdir);
|
||||||
|
for(std::vector<Glib::ustring>::iterator iter=names.begin(); iter != names.end();iter++ )
|
||||||
|
safe_g_remove( *iter );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
notifyListener (queueEmptied);
|
notifyListener (queueEmptied);
|
||||||
@@ -728,6 +777,7 @@ void BatchQueue::setProgress (double p) {
|
|||||||
if (processing)
|
if (processing)
|
||||||
processing->progress = p;
|
processing->progress = p;
|
||||||
|
|
||||||
|
// No need to acquire the GUI, setProgressUI will do it
|
||||||
g_idle_add (setProgressUI, this);
|
g_idle_add (setProgressUI, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,6 +801,7 @@ struct NLParams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int bqnotifylistenerUI (void* data) {
|
int bqnotifylistenerUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
NLParams* params = static_cast<NLParams*>(data);
|
NLParams* params = static_cast<NLParams*>(data);
|
||||||
params->listener->queueSizeChanged (params->qsize, params->queueEmptied);
|
params->listener->queueSizeChanged (params->qsize, params->queueEmptied);
|
||||||
delete params;
|
delete params;
|
||||||
@@ -762,13 +813,19 @@ void BatchQueue::notifyListener (bool queueEmptied) {
|
|||||||
if (listener) {
|
if (listener) {
|
||||||
NLParams* params = new NLParams;
|
NLParams* params = new NLParams;
|
||||||
params->listener = listener;
|
params->listener = listener;
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
params->qsize = fd.size();
|
params->qsize = fd.size();
|
||||||
|
}
|
||||||
params->queueEmptied = queueEmptied;
|
params->queueEmptied = queueEmptied;
|
||||||
g_idle_add (bqnotifylistenerUI, params);
|
g_idle_add (bqnotifylistenerUI, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueue::redrawNeeded (LWButton* button) {
|
void BatchQueue::redrawNeeded (LWButton* button) {
|
||||||
|
GThreadLock lock;
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
class BatchQueueListener {
|
class BatchQueueListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~BatchQueueListener () {}
|
||||||
virtual void queueSizeChanged (int qsize, bool queueEmptied) =0;
|
virtual void queueSizeChanged (int qsize, bool queueEmptied) =0;
|
||||||
virtual bool canStartNext () =0;
|
virtual bool canStartNext () =0;
|
||||||
};
|
};
|
||||||
@@ -39,6 +40,8 @@ class BatchQueue : public ThumbBrowserBase,
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
int getMaxThumbnailHeight() const;
|
int getMaxThumbnailHeight() const;
|
||||||
|
void saveThumbnailHeight (int height);
|
||||||
|
int getThumbnailHeight ();
|
||||||
|
|
||||||
BatchQueueEntry* processing; // holds the currently processed image
|
BatchQueueEntry* processing; // holds the currently processed image
|
||||||
|
|
||||||
@@ -61,15 +64,22 @@ class BatchQueue : public ThumbBrowserBase,
|
|||||||
BatchQueue ();
|
BatchQueue ();
|
||||||
~BatchQueue ();
|
~BatchQueue ();
|
||||||
|
|
||||||
void addEntries (std::vector<BatchQueueEntry*> &entries, bool head=false);
|
void addEntries (std::vector<BatchQueueEntry*> &entries, bool head=false, bool save=true);
|
||||||
void cancelItems (std::vector<ThumbBrowserEntryBase*>* items);
|
void cancelItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||||
void headItems (std::vector<ThumbBrowserEntryBase*>* items);
|
void headItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||||
void tailItems (std::vector<ThumbBrowserEntryBase*>* items);
|
void tailItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||||
void selectAll ();
|
void selectAll ();
|
||||||
|
|
||||||
void startProcessing ();
|
void startProcessing ();
|
||||||
|
|
||||||
bool hasJobs () { return (!fd.empty()); }
|
bool hasJobs () {
|
||||||
|
// not sure that this lock is necessary, but it's safer to keep it...
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
return (!fd.empty());
|
||||||
|
}
|
||||||
|
|
||||||
rtengine::ProcessingJob* imageReady (rtengine::IImage16* img);
|
rtengine::ProcessingJob* imageReady (rtengine::IImage16* img);
|
||||||
void setProgress (double p);
|
void setProgress (double p);
|
||||||
@@ -79,7 +89,8 @@ class BatchQueue : public ThumbBrowserBase,
|
|||||||
|
|
||||||
void setBatchQueueListener (BatchQueueListener* l) { listener = l; }
|
void setBatchQueueListener (BatchQueueListener* l) { listener = l; }
|
||||||
|
|
||||||
void loadBatchQueue ();
|
bool loadBatchQueue ();
|
||||||
|
void resizeLoadedQueue();
|
||||||
|
|
||||||
static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName);
|
static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName);
|
||||||
static int calcMaxThumbnailHeight();
|
static int calcMaxThumbnailHeight();
|
||||||
|
@@ -27,16 +27,16 @@
|
|||||||
bool BatchQueueEntry::iconsLoaded(false);
|
bool BatchQueueEntry::iconsLoaded(false);
|
||||||
Glib::RefPtr<Gdk::Pixbuf> BatchQueueEntry::savedAsIcon;
|
Glib::RefPtr<Gdk::Pixbuf> BatchQueueEntry::savedAsIcon;
|
||||||
|
|
||||||
BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, guint8* previmg, int prevw, int prevh, Thumbnail* thm)
|
BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm)
|
||||||
: ThumbBrowserEntryBase(fname),
|
: ThumbBrowserEntryBase(fname),
|
||||||
opreview(previmg), origpw(prevw), origph(prevh),
|
opreview(NULL), origpw(prevw), origph(prevh), opreviewDone(false),
|
||||||
job(pjob), progress(0), outFileName(""), forceFormatOpts(false) {
|
job(pjob), progress(0), outFileName(""), forceFormatOpts(false) {
|
||||||
|
|
||||||
thumbnail=thm;
|
thumbnail=thm;
|
||||||
params = pparams;
|
params = pparams;
|
||||||
|
|
||||||
#ifndef WIN32
|
#if 1 //ndef WIN32
|
||||||
// The BatchQueueEntryIdleHelper tracks if an entry has been deleted while it was sitting wating for "idle"
|
// The BatchQueueEntryIdleHelper tracks if an entry has been deleted while it was sitting waiting for "idle"
|
||||||
bqih = new BatchQueueEntryIdleHelper;
|
bqih = new BatchQueueEntryIdleHelper;
|
||||||
bqih->bqentry = this;
|
bqih->bqentry = this;
|
||||||
bqih->destroyed = false;
|
bqih->destroyed = false;
|
||||||
@@ -55,24 +55,28 @@ BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine:
|
|||||||
BatchQueueEntry::~BatchQueueEntry () {
|
BatchQueueEntry::~BatchQueueEntry () {
|
||||||
|
|
||||||
batchQueueEntryUpdater.removeJobs (this);
|
batchQueueEntryUpdater.removeJobs (this);
|
||||||
delete [] opreview; opreview=NULL;
|
if (opreview) delete [] opreview; opreview=NULL;
|
||||||
if (thumbnail)
|
if (thumbnail)
|
||||||
thumbnail->decreaseRef ();
|
thumbnail->decreaseRef ();
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
if (bqih->pending)
|
if (bqih->pending)
|
||||||
bqih->destroyed = true;
|
bqih->destroyed = true;
|
||||||
else
|
else
|
||||||
delete bqih;
|
delete bqih;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueueEntry::refreshThumbnailImage () {
|
void BatchQueueEntry::refreshThumbnailImage () {
|
||||||
|
|
||||||
if (!opreview)
|
if (!opreviewDone) {
|
||||||
return;
|
// creating the image buffer first
|
||||||
|
//if (!opreview) opreview = new guint8[(origpw+1) * origph * 3];
|
||||||
batchQueueEntryUpdater.process (opreview, origpw, origph, preh, this); // this will asynchronously land at this.updateImage
|
// this will asynchronously compute the original preview and land at this.updateImage
|
||||||
|
batchQueueEntryUpdater.process (NULL, origpw, origph, preh, this, ¶ms, thumbnail);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this will asynchronously land at this.updateImage
|
||||||
|
batchQueueEntryUpdater.process (opreview, origpw, origph, preh, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueueEntry::calcThumbnailSize () {
|
void BatchQueueEntry::calcThumbnailSize () {
|
||||||
@@ -166,8 +170,6 @@ Glib::ustring BatchQueueEntry::getToolTip (int x, int y) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
|
|
||||||
struct BQUpdateParam {
|
struct BQUpdateParam {
|
||||||
BatchQueueEntryIdleHelper* bqih;
|
BatchQueueEntryIdleHelper* bqih;
|
||||||
guint8* img;
|
guint8* img;
|
||||||
@@ -180,11 +182,13 @@ int updateImageUIThread (void* data) {
|
|||||||
|
|
||||||
BatchQueueEntryIdleHelper* bqih = params->bqih;
|
BatchQueueEntryIdleHelper* bqih = params->bqih;
|
||||||
|
|
||||||
// If the BQEntry was destroyed meanwhile, remove all the IdleHelper if all entries came through
|
GThreadLock tLock; // Acquire the GUI
|
||||||
|
|
||||||
|
// If the BQEntry was destroyed meanwhile, remove all the IdleHelper if all entries came through
|
||||||
if (bqih->destroyed) {
|
if (bqih->destroyed) {
|
||||||
if (bqih->pending == 1)
|
if (bqih->pending == 1)
|
||||||
delete bqih;
|
delete bqih;
|
||||||
else
|
else
|
||||||
bqih->pending--;
|
bqih->pending--;
|
||||||
delete [] params->img;
|
delete [] params->img;
|
||||||
delete params;
|
delete params;
|
||||||
@@ -198,35 +202,29 @@ int updateImageUIThread (void* data) {
|
|||||||
delete params;
|
delete params;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Starts a copy of img->preview via GTK thread
|
// Starts a copy of img->preview via GTK thread
|
||||||
void BatchQueueEntry::updateImage (guint8* img, int w, int h) {
|
void BatchQueueEntry::updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) {
|
||||||
// TODO: Check for Linux/Mac
|
|
||||||
#ifdef WIN32
|
|
||||||
// since the update itself is already called in an async thread and there are problem with accessing opreview in thumbbrowserbase,
|
// since the update itself is already called in an async thread and there are problem with accessing opreview in thumbbrowserbase,
|
||||||
// it's safer to do this synchrously
|
// it's safer to do this synchronously
|
||||||
{
|
{
|
||||||
GThreadLock lock;
|
GThreadLock lock;
|
||||||
|
|
||||||
_updateImage(img,w,h);
|
_updateImage(img,w,h);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
bqih->pending++;
|
|
||||||
|
|
||||||
BQUpdateParam* param = new BQUpdateParam ();
|
|
||||||
param->bqih = bqih;
|
|
||||||
param->img = img;
|
|
||||||
param->w = w;
|
|
||||||
param->h = h;
|
|
||||||
g_idle_add (updateImageUIThread, param);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueueEntry::_updateImage (guint8* img, int w, int h) {
|
void BatchQueueEntry::_updateImage (guint8* img, int w, int h) {
|
||||||
|
|
||||||
if (preh == h) {
|
if (preh == h) {
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
prew = w;
|
prew = w;
|
||||||
|
assert (preview == NULL);
|
||||||
preview = new guint8 [prew*preh*3];
|
preview = new guint8 [prew*preh*3];
|
||||||
memcpy (preview, img, prew*preh*3);
|
memcpy (preview, img, prew*preh*3);
|
||||||
if (parent)
|
if (parent)
|
||||||
|
@@ -37,6 +37,7 @@ class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListen
|
|||||||
guint8* opreview;
|
guint8* opreview;
|
||||||
int origpw, origph;
|
int origpw, origph;
|
||||||
BatchQueueEntryIdleHelper* bqih;
|
BatchQueueEntryIdleHelper* bqih;
|
||||||
|
bool opreviewDone;
|
||||||
static bool iconsLoaded;
|
static bool iconsLoaded;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -51,7 +52,7 @@ public:
|
|||||||
SaveFormat saveFormat;
|
SaveFormat saveFormat;
|
||||||
bool forceFormatOpts;
|
bool forceFormatOpts;
|
||||||
|
|
||||||
BatchQueueEntry (rtengine::ProcessingJob* job, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, guint8* previmg, int prevw, int prevh, Thumbnail* thm=NULL);
|
BatchQueueEntry (rtengine::ProcessingJob* job, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm=NULL);
|
||||||
~BatchQueueEntry ();
|
~BatchQueueEntry ();
|
||||||
|
|
||||||
void refreshThumbnailImage ();
|
void refreshThumbnailImage ();
|
||||||
@@ -66,7 +67,7 @@ public:
|
|||||||
virtual Glib::ustring getToolTip (int x, int y);
|
virtual Glib::ustring getToolTip (int x, int y);
|
||||||
|
|
||||||
// bqentryupdatelistener interface
|
// bqentryupdatelistener interface
|
||||||
void updateImage (guint8* img, int w, int h);
|
void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview);
|
||||||
void _updateImage (guint8* img, int w, int h); // inside gtk thread
|
void _updateImage (guint8* img, int w, int h); // inside gtk thread
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -25,6 +25,16 @@
|
|||||||
#include "../rtengine/safegtk.h"
|
#include "../rtengine/safegtk.h"
|
||||||
#include "rtimage.h"
|
#include "rtimage.h"
|
||||||
|
|
||||||
|
struct BQProcessLoaded {
|
||||||
|
BatchQueue* bq;
|
||||||
|
};
|
||||||
|
|
||||||
|
int processLoadedBatchQueueUIThread (void* data) {
|
||||||
|
|
||||||
|
BatchQueue* bq = static_cast<BatchQueue*>(data);
|
||||||
|
bq->resizeLoadedQueue();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BatchQueuePanel::BatchQueuePanel () {
|
BatchQueuePanel::BatchQueuePanel () {
|
||||||
|
|
||||||
@@ -132,7 +142,9 @@ BatchQueuePanel::BatchQueuePanel () {
|
|||||||
batchQueue->setBatchQueueListener (this);
|
batchQueue->setBatchQueueListener (this);
|
||||||
|
|
||||||
show_all ();
|
show_all ();
|
||||||
batchQueue->loadBatchQueue ();
|
if (batchQueue->loadBatchQueue ()) {
|
||||||
|
g_idle_add_full (G_PRIORITY_LOW, processLoadedBatchQueueUIThread, batchQueue, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@ using namespace rtengine::procparams;
|
|||||||
|
|
||||||
BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), parent(parent) {
|
BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), parent(parent) {
|
||||||
|
|
||||||
|
blockedUpdate = false;
|
||||||
// remove exif panel and iptc panel
|
// remove exif panel and iptc panel
|
||||||
std::vector<ToolPanel*>::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel);
|
std::vector<ToolPanel*>::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel);
|
||||||
if (epi!=toolPanels.end())
|
if (epi!=toolPanels.end())
|
||||||
@@ -56,13 +57,13 @@ void BatchToolPanelCoordinator::selectionChanged (const std::vector<Thumbnail*>&
|
|||||||
|
|
||||||
void BatchToolPanelCoordinator::closeSession (bool save) {
|
void BatchToolPanelCoordinator::closeSession (bool save) {
|
||||||
|
|
||||||
pparamsEdited.set (false);
|
pparamsEdited.set (false);
|
||||||
|
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
selected[i]->removeThumbnailListener (this);
|
selected[i]->removeThumbnailListener (this);
|
||||||
|
|
||||||
if (somethingChanged && save) {
|
if (somethingChanged && save) {
|
||||||
|
|
||||||
// read new values from the gui
|
// read new values from the gui
|
||||||
for (size_t i=0; i<toolPanels.size(); i++)
|
for (size_t i=0; i<toolPanels.size(); i++)
|
||||||
toolPanels[i]->write (&pparams, &pparamsEdited);
|
toolPanels[i]->write (&pparams, &pparamsEdited);
|
||||||
@@ -73,11 +74,11 @@ void BatchToolPanelCoordinator::closeSession (bool save) {
|
|||||||
newParams = initialPP[i];
|
newParams = initialPP[i];
|
||||||
pparamsEdited.combine (newParams, pparams, selected.size()==1);
|
pparamsEdited.combine (newParams, pparams, selected.size()==1);
|
||||||
|
|
||||||
// trim new adjuster's values to the adjuster's limits
|
// trim new adjuster's values to the adjuster's limits
|
||||||
for (unsigned int j=0; j<toolPanels.size(); j++)
|
for (unsigned int j=0; j<toolPanels.size(); j++)
|
||||||
toolPanels[j]->trimValues (&newParams);
|
toolPanels[j]->trimValues (&newParams);
|
||||||
|
|
||||||
selected[i]->setProcParams (newParams, NULL, BATCHEDITOR, true);
|
selected[i]->setProcParams (newParams, NULL, BATCHEDITOR, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i=0; i<paramcListeners.size(); i++)
|
for (size_t i=0; i<paramcListeners.size(); i++)
|
||||||
@@ -333,12 +334,28 @@ void BatchToolPanelCoordinator::optionsChanged () {
|
|||||||
|
|
||||||
void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
|
void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
|
||||||
|
|
||||||
if (whoChangedIt!=BATCHEDITOR) {
|
if (whoChangedIt!=BATCHEDITOR && !blockedUpdate) {
|
||||||
closeSession (false);
|
closeSession (false);
|
||||||
initSession ();
|
initSession ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BatchToolPanelCoordinator::beginBatchPParamsChange(int numberOfEntries) {
|
||||||
|
|
||||||
|
blockedUpdate = true;
|
||||||
|
if (numberOfEntries > 50) // Arbitrary amount
|
||||||
|
parent->set_sensitive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The end of a batch pparams change triggers a close/initsession
|
||||||
|
void BatchToolPanelCoordinator::endBatchPParamsChange() {
|
||||||
|
//printf("BatchToolPanelCoordinator::endBatchPParamsChange / Nouvelle session!\n");
|
||||||
|
closeSession (false);
|
||||||
|
initSession ();
|
||||||
|
blockedUpdate = false;
|
||||||
|
parent->set_sensitive(true);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING: profileChange is actually called by the History only.
|
* WARNING: profileChange is actually called by the History only.
|
||||||
* Using a Profile panel in the batch tool panel editor is actually
|
* Using a Profile panel in the batch tool panel editor is actually
|
||||||
|
@@ -30,6 +30,7 @@ class FilePanel;
|
|||||||
class BatchToolPanelCoordinator :
|
class BatchToolPanelCoordinator :
|
||||||
public ToolPanelCoordinator,
|
public ToolPanelCoordinator,
|
||||||
public FileSelectionChangeListener,
|
public FileSelectionChangeListener,
|
||||||
|
public BatchPParamsChangeListener,
|
||||||
public ThumbnailListener
|
public ThumbnailListener
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -39,6 +40,7 @@ class BatchToolPanelCoordinator :
|
|||||||
std::vector<Glib::ustring> selFileNames;
|
std::vector<Glib::ustring> selFileNames;
|
||||||
std::vector<rtengine::procparams::ProcParams> initialPP;
|
std::vector<rtengine::procparams::ProcParams> initialPP;
|
||||||
bool somethingChanged;
|
bool somethingChanged;
|
||||||
|
bool blockedUpdate;
|
||||||
FilePanel* parent;
|
FilePanel* parent;
|
||||||
|
|
||||||
void closeSession (bool save=true);
|
void closeSession (bool save=true);
|
||||||
@@ -63,7 +65,11 @@ class BatchToolPanelCoordinator :
|
|||||||
|
|
||||||
// thumbnaillistener interface
|
// thumbnaillistener interface
|
||||||
void procParamsChanged (Thumbnail* thm, int whoChangedIt);
|
void procParamsChanged (Thumbnail* thm, int whoChangedIt);
|
||||||
|
|
||||||
|
// batchpparamschangelistener interface
|
||||||
|
void beginBatchPParamsChange(int numberOfEntries);
|
||||||
|
void endBatchPParamsChange();
|
||||||
|
|
||||||
// imageareatoollistener interface
|
// imageareatoollistener interface
|
||||||
void spotWBselected (int x, int y, Thumbnail* thm=NULL);
|
void spotWBselected (int x, int y, Thumbnail* thm=NULL);
|
||||||
void cropSelectionReady ();
|
void cropSelectionReady ();
|
||||||
|
@@ -23,12 +23,17 @@
|
|||||||
BatchQueueEntryUpdater batchQueueEntryUpdater;
|
BatchQueueEntryUpdater batchQueueEntryUpdater;
|
||||||
|
|
||||||
BatchQueueEntryUpdater::BatchQueueEntryUpdater ()
|
BatchQueueEntryUpdater::BatchQueueEntryUpdater ()
|
||||||
: tostop(false), stopped(true), qMutex(NULL) {
|
: tostop(false), stopped(true), thread(NULL), qMutex(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener) {
|
void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams, Thumbnail* thumbnail) {
|
||||||
|
if (!oimg && (!pparams || !thumbnail)) {
|
||||||
|
//printf("WARNING! !oimg && (!pparams || !thumbnail)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!qMutex)
|
if (!qMutex)
|
||||||
qMutex = new Glib::Mutex ();
|
qMutex = new Glib::Mutex ();
|
||||||
|
|
||||||
qMutex->lock ();
|
qMutex->lock ();
|
||||||
// look up if an older version is in the queue
|
// look up if an older version is in the queue
|
||||||
@@ -39,6 +44,8 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ
|
|||||||
i->oh = oh;
|
i->oh = oh;
|
||||||
i->newh = newh;
|
i->newh = newh;
|
||||||
i->listener = listener;
|
i->listener = listener;
|
||||||
|
i->pparams = pparams;
|
||||||
|
i->thumbnail = thumbnail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +57,8 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ
|
|||||||
j.oh = oh;
|
j.oh = oh;
|
||||||
j.newh = newh;
|
j.newh = newh;
|
||||||
j.listener = listener;
|
j.listener = listener;
|
||||||
|
j.pparams = pparams;
|
||||||
|
j.thumbnail = thumbnail;
|
||||||
jqueue.push_back (j);
|
jqueue.push_back (j);
|
||||||
}
|
}
|
||||||
qMutex->unlock ();
|
qMutex->unlock ();
|
||||||
@@ -79,11 +88,37 @@ void BatchQueueEntryUpdater::processThread () {
|
|||||||
}
|
}
|
||||||
qMutex->unlock ();
|
qMutex->unlock ();
|
||||||
|
|
||||||
if (!isEmpty && current.listener) {
|
rtengine::IImage8* img = NULL;
|
||||||
|
bool newBuffer = false;
|
||||||
|
if (current.thumbnail && current.pparams) {
|
||||||
|
// the thumbnail and the pparams are provided, it means that we have to build the original preview image
|
||||||
|
double tmpscale;
|
||||||
|
img = current.thumbnail->processThumbImage (*current.pparams, current.oh, tmpscale);
|
||||||
|
//current.thumbnail->decreaseRef (); // WARNING: decreasing refcount (and maybe deleting) thumbnail, with or without processed image
|
||||||
|
if (img) {
|
||||||
|
int prevw = img->getWidth();
|
||||||
|
int prevh = img->getHeight();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (current.ow != img->getW() || current.oh != img->getH())
|
||||||
|
printf("WARNING! Expected image size: %dx%d ; image size is: %dx%d\n", current.ow, current.oh, img->getW(), img->getH());
|
||||||
|
assert ((current.ow+1)*current.oh >= img->getW()*img->getH());
|
||||||
|
#endif
|
||||||
|
current.ow = prevw;
|
||||||
|
current.oh = prevh;
|
||||||
|
if (!current.oimg) {
|
||||||
|
current.oimg = new guint8[prevw*prevh*3];
|
||||||
|
newBuffer = true;
|
||||||
|
}
|
||||||
|
memcpy(current.oimg, img->getData(), prevw * prevh * 3);
|
||||||
|
img->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.oimg && !isEmpty && current.listener) {
|
||||||
int neww = current.newh * current.ow / current.oh;
|
int neww = current.newh * current.ow / current.oh;
|
||||||
guint8* img = new guint8 [current.newh*neww*3];
|
guint8* img = new guint8 [current.newh*neww*3];
|
||||||
thumbInterp (current.oimg, current.ow, current.oh, img, neww, current.newh);
|
thumbInterp (current.oimg, current.ow, current.oh, img, neww, current.newh);
|
||||||
current.listener->updateImage (img, neww, current.newh);
|
current.listener->updateImage (img, neww, current.newh, current.ow, current.oh, newBuffer?current.oimg:NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,12 +149,11 @@ void BatchQueueEntryUpdater::terminate () {
|
|||||||
if (!qMutex || stopped) return;
|
if (!qMutex || stopped) return;
|
||||||
|
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
// Yield to currenly running thread and wait till it's finished
|
// Yield to currently running thread and wait till it's finished
|
||||||
gdk_threads_leave();
|
GThreadUnLock();
|
||||||
tostop = true;
|
tostop = true;
|
||||||
Glib::Thread::self()->yield();
|
Glib::Thread::self()->yield();
|
||||||
if (!stopped) thread->join ();
|
if (!stopped) thread->join ();
|
||||||
gdk_threads_enter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove remaining jobs
|
// Remove remaining jobs
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
class BQEntryUpdateListener {
|
class BQEntryUpdateListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void updateImage (guint8* img, int w, int h) {}
|
virtual ~BQEntryUpdateListener () {}
|
||||||
|
virtual void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BatchQueueEntryUpdater {
|
class BatchQueueEntryUpdater {
|
||||||
@@ -35,6 +36,8 @@ class BatchQueueEntryUpdater {
|
|||||||
guint8* oimg;
|
guint8* oimg;
|
||||||
int ow, oh, newh;
|
int ow, oh, newh;
|
||||||
BQEntryUpdateListener* listener;
|
BQEntryUpdateListener* listener;
|
||||||
|
rtengine::ProcParams* pparams;
|
||||||
|
Thumbnail* thumbnail;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -47,7 +50,7 @@ class BatchQueueEntryUpdater {
|
|||||||
public:
|
public:
|
||||||
BatchQueueEntryUpdater ();
|
BatchQueueEntryUpdater ();
|
||||||
|
|
||||||
void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener);
|
void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams=NULL, Thumbnail* thumbnail=NULL);
|
||||||
void removeJobs (BQEntryUpdateListener* listener);
|
void removeJobs (BQEntryUpdateListener* listener);
|
||||||
void terminate ();
|
void terminate ();
|
||||||
|
|
||||||
|
@@ -33,8 +33,13 @@ int CacheImageData::load (const Glib::ustring& fname) {
|
|||||||
rtengine::SafeKeyFile keyFile;
|
rtengine::SafeKeyFile keyFile;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!keyFile.load_from_file (fname))
|
bool loaded = keyFile.load_from_file (fname);
|
||||||
|
if (!loaded) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
printf("Failed to load_from_file(%s)\n", fname.c_str());
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (keyFile.has_group ("General")) {
|
if (keyFile.has_group ("General")) {
|
||||||
if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5");
|
if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5");
|
||||||
@@ -58,32 +63,31 @@ int CacheImageData::load (const Glib::ustring& fname) {
|
|||||||
if (keyFile.has_key ("DateTime", "MSec")) msec = keyFile.get_integer ("DateTime", "MSec");
|
if (keyFile.has_key ("DateTime", "MSec")) msec = keyFile.get_integer ("DateTime", "MSec");
|
||||||
}
|
}
|
||||||
|
|
||||||
exifValid = false;
|
exifValid = false;
|
||||||
|
|
||||||
if (keyFile.has_group ("ExifInfo")) {
|
|
||||||
exifValid = true;
|
|
||||||
if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid");
|
|
||||||
|
|
||||||
if (exifValid) {
|
if (keyFile.has_group ("ExifInfo")) {
|
||||||
if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber");
|
exifValid = true;
|
||||||
if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter");
|
if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid");
|
||||||
if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen");
|
|
||||||
|
if (exifValid) {
|
||||||
|
if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber");
|
||||||
|
if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter");
|
||||||
|
if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen");
|
||||||
if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm");
|
if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm");
|
||||||
else focalLen35mm=focalLen; // prevent crashes on old files
|
else focalLen35mm=focalLen; // prevent crashes on old files
|
||||||
if (keyFile.has_key ("ExifInfo", "FocusDist")) focusDist = keyFile.get_double ("ExifInfo", "FocusDist");
|
if (keyFile.has_key ("ExifInfo", "FocusDist")) focusDist = keyFile.get_double ("ExifInfo", "FocusDist");
|
||||||
else focusDist=0;
|
else focusDist=0;
|
||||||
if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO");
|
if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO");
|
||||||
if (keyFile.has_key ("ExifInfo", "ExpComp")) expcomp = keyFile.get_string ("ExifInfo", "ExpComp");
|
if (keyFile.has_key ("ExifInfo", "ExpComp")) expcomp = keyFile.get_string ("ExifInfo", "ExpComp");
|
||||||
}
|
}
|
||||||
if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens");
|
if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens");
|
||||||
if (keyFile.has_key ("ExifInfo", "Camera")) camera = keyFile.get_string ("ExifInfo", "Camera");
|
if (keyFile.has_key ("ExifInfo", "Camera")) camera = keyFile.get_string ("ExifInfo", "Camera");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyFile.has_group ("FileInfo")) {
|
if (keyFile.has_group ("FileInfo")) {
|
||||||
if (keyFile.has_key ("FileInfo", "Filetype")) filetype = keyFile.get_string ("FileInfo", "Filetype");
|
if (keyFile.has_key ("FileInfo", "Filetype")) filetype = keyFile.get_string ("FileInfo", "Filetype");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
|
if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
|
||||||
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType");
|
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType");
|
||||||
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset");
|
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset");
|
||||||
@@ -94,9 +98,10 @@ int CacheImageData::load (const Glib::ustring& fname) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (Glib::Error) {
|
catch (Glib::Error &err) {
|
||||||
return 1;
|
printf("Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str());
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CacheImageData::save (const Glib::ustring& fname) {
|
int CacheImageData::save (const Glib::ustring& fname) {
|
||||||
@@ -151,5 +156,6 @@ int CacheImageData::save (const Glib::ustring& fname) {
|
|||||||
fprintf (f, "%s", keyFile.to_data().c_str());
|
fprintf (f, "%s", keyFile.to_data().c_str());
|
||||||
fclose (f);
|
fclose (f);
|
||||||
return 0;
|
return 0;
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -64,7 +64,11 @@ void CacheManager::init () {
|
|||||||
safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "data")), 511);
|
safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "data")), 511);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) {
|
/*
|
||||||
|
* if pparams is NULL (default), get the ProcParams from the cache;
|
||||||
|
* if pparams is non NULL, compute the thumbnails with the provided pparams
|
||||||
|
*/
|
||||||
|
Thumbnail* CacheManager::getEntry (const Glib::ustring& fname, const rtengine::procparams::ProcParams *pparams) {
|
||||||
|
|
||||||
Thumbnail* res = NULL;
|
Thumbnail* res = NULL;
|
||||||
|
|
||||||
@@ -93,8 +97,8 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) {
|
|||||||
if (safe_file_test (cfname, Glib::FILE_TEST_EXISTS)) {
|
if (safe_file_test (cfname, Glib::FILE_TEST_EXISTS)) {
|
||||||
CacheImageData* cfs = new CacheImageData ();
|
CacheImageData* cfs = new CacheImageData ();
|
||||||
int e = cfs->load (cfname);
|
int e = cfs->load (cfname);
|
||||||
if (!e && cfs->supported==true)
|
if (!e && cfs->supported==true)
|
||||||
res = new Thumbnail (this, fname, cfs);
|
res = new Thumbnail (this, fname, cfs, pparams);
|
||||||
if (res && !res->isSupported ()) {
|
if (res && !res->isSupported ()) {
|
||||||
delete res;
|
delete res;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
@@ -104,7 +108,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) {
|
|||||||
|
|
||||||
// if not, create a new one
|
// if not, create a new one
|
||||||
if (!res) {
|
if (!res) {
|
||||||
res = new Thumbnail (this, fname, md5);
|
res = new Thumbnail (this, fname, md5, pparams);
|
||||||
if (!res->isSupported ()) {
|
if (!res->isSupported ()) {
|
||||||
delete res;
|
delete res;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include <glibmm.h>
|
#include <glibmm.h>
|
||||||
#include "thumbnail.h"
|
#include "thumbnail.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include "../rtengine/procparams.h"
|
||||||
|
|
||||||
class Thumbnail;
|
class Thumbnail;
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ class CacheManager {
|
|||||||
static CacheManager* getInstance(void);
|
static CacheManager* getInstance(void);
|
||||||
|
|
||||||
void init ();
|
void init ();
|
||||||
Thumbnail* getEntry (const Glib::ustring& fname);
|
Thumbnail* getEntry (const Glib::ustring& fname, const rtengine::procparams::ProcParams *pparams=NULL);
|
||||||
void deleteEntry (const Glib::ustring& fname);
|
void deleteEntry (const Glib::ustring& fname);
|
||||||
void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename);
|
void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename);
|
||||||
|
|
||||||
|
@@ -893,14 +893,14 @@ void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int autoCamChangedUI (void* data) {
|
int autoCamChangedUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
(static_cast<ColorAppearance*>(data))->autoCamComputed_ ();
|
(static_cast<ColorAppearance*>(data))->autoCamComputed_ ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void ColorAppearance::autoCamChanged (double ccam)
|
void ColorAppearance::autoCamChanged (double ccam)
|
||||||
{
|
{
|
||||||
nextCcam = ccam;
|
nextCcam = ccam;
|
||||||
g_idle_add (autoCamChangedUI, this);
|
g_idle_add (autoCamChangedUI, this);
|
||||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::autoCamComputed_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ColorAppearance::autoCamComputed_ () {
|
bool ColorAppearance::autoCamComputed_ () {
|
||||||
@@ -913,14 +913,14 @@ bool ColorAppearance::autoCamComputed_ () {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int adapCamChangedUI (void* data) {
|
int adapCamChangedUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
(static_cast<ColorAppearance*>(data))->adapCamComputed_ ();
|
(static_cast<ColorAppearance*>(data))->adapCamComputed_ ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void ColorAppearance::adapCamChanged (double cadap)
|
void ColorAppearance::adapCamChanged (double cadap)
|
||||||
{
|
{
|
||||||
nextCadap = cadap;
|
nextCadap = cadap;
|
||||||
g_idle_add (adapCamChangedUI, this);
|
g_idle_add (adapCamChangedUI, this);
|
||||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::autoCamComputed_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ColorAppearance::adapCamComputed_ () {
|
bool ColorAppearance::adapCamComputed_ () {
|
||||||
|
@@ -469,11 +469,13 @@ void Crop::enabledChanged () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int notifyListenerUI (void* data) {
|
int notifyListenerUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
(static_cast<Crop*>(data))->notifyListener ();
|
(static_cast<Crop*>(data))->notifyListener ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int refreshSpinsUI (void* data) {
|
int refreshSpinsUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
RefreshSpinHelper* rsh = static_cast<RefreshSpinHelper*>(data);
|
RefreshSpinHelper* rsh = static_cast<RefreshSpinHelper*>(data);
|
||||||
rsh->crop->refreshSpins (rsh->notify);
|
rsh->crop->refreshSpins (rsh->notify);
|
||||||
delete rsh;
|
delete rsh;
|
||||||
@@ -587,23 +589,23 @@ void Crop::ratioChanged () {
|
|||||||
|
|
||||||
// Correct current crop if it doesn't fit
|
// Correct current crop if it doesn't fit
|
||||||
void Crop::adjustCropToRatio() {
|
void Crop::adjustCropToRatio() {
|
||||||
if (fixr->get_active() && !fixr->get_inconsistent()) {
|
if (fixr->get_active() && !fixr->get_inconsistent()) {
|
||||||
|
|
||||||
// int W = w->get_value ();
|
// int W = w->get_value ();
|
||||||
// int H = h->get_value ();
|
// int H = h->get_value ();
|
||||||
int W = nw;
|
int W = nw;
|
||||||
int H = nh;
|
int H = nh;
|
||||||
int X = nx;
|
int X = nx;
|
||||||
int Y = ny;
|
int Y = ny;
|
||||||
if (W>=H)
|
if (W>=H)
|
||||||
cropWidth2Resized (X, Y, W, H);
|
cropWidth2Resized (X, Y, W, H);
|
||||||
else
|
else
|
||||||
cropHeight2Resized (X, Y, W, H);
|
cropHeight2Resized (X, Y, W, H);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will safe the options
|
// This will save the options
|
||||||
g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, true));
|
g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Crop::refreshSize () {
|
void Crop::refreshSize () {
|
||||||
|
|
||||||
@@ -667,6 +669,7 @@ struct setdimparams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int sizeChangedUI (void* data) {
|
int sizeChangedUI (void* data) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
setdimparams* params = static_cast<setdimparams*>(data);
|
setdimparams* params = static_cast<setdimparams*>(data);
|
||||||
params->crop->setDimensions (params->x, params->y);
|
params->crop->setDimensions (params->x, params->y);
|
||||||
delete params;
|
delete params;
|
||||||
@@ -958,12 +961,11 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) {
|
|||||||
nh = H;
|
nh = H;
|
||||||
|
|
||||||
g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false));
|
g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false));
|
||||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Crop::cropManipReady () {
|
void Crop::cropManipReady () {
|
||||||
|
|
||||||
g_idle_add (notifyListenerUI, this);
|
g_idle_add (notifyListenerUI, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Crop::getRatio () {
|
double Crop::getRatio () {
|
||||||
|
@@ -186,11 +186,11 @@ int createpixbufs (void* data) {
|
|||||||
if (!ch->enabled) {
|
if (!ch->enabled) {
|
||||||
delete [] ch->cropimg;
|
delete [] ch->cropimg;
|
||||||
ch->cropimg = NULL;
|
ch->cropimg = NULL;
|
||||||
delete [] ch->cropimgtrue;
|
delete [] ch->cropimgtrue;
|
||||||
ch->cropimgtrue = NULL;
|
ch->cropimgtrue = NULL;
|
||||||
ch->cimg.unlock ();
|
ch->cimg.unlock ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch->cropimg) {
|
if (ch->cropimg) {
|
||||||
if (ch->cix==ch->cropX && ch->ciy==ch->cropY && ch->ciw==ch->cropW && ch->cih==ch->cropH && ch->cis==(ch->zoom>=1000?1:ch->zoom)) {
|
if (ch->cix==ch->cropX && ch->ciy==ch->cropY && ch->ciw==ch->cropW && ch->cih==ch->cropH && ch->cis==(ch->zoom>=1000?1:ch->zoom)) {
|
||||||
@@ -207,15 +207,15 @@ int createpixbufs (void* data) {
|
|||||||
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
||||||
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
||||||
tmpPixbuf.clear ();
|
tmpPixbuf.clear ();
|
||||||
|
|
||||||
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2*ch->cropimg_height, 3*ch->cropimg_width);
|
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2*ch->cropimg_height, 3*ch->cropimg_width);
|
||||||
ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
||||||
tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
||||||
tmpPixbuftrue.clear ();
|
tmpPixbuftrue.clear ();
|
||||||
}
|
}
|
||||||
delete [] ch->cropimg;
|
delete [] ch->cropimg;
|
||||||
ch->cropimg = NULL;
|
ch->cropimg = NULL;
|
||||||
delete [] ch->cropimgtrue;
|
delete [] ch->cropimgtrue;
|
||||||
ch->cropimgtrue = NULL;
|
ch->cropimgtrue = NULL;
|
||||||
}
|
}
|
||||||
ch->cimg.unlock ();
|
ch->cimg.unlock ();
|
||||||
@@ -233,7 +233,7 @@ int createpixbufs (void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp,
|
void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp,
|
||||||
rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) {
|
rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) {
|
||||||
|
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
@@ -255,9 +255,9 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
|
|||||||
cropimg_width = im->getWidth ();
|
cropimg_width = im->getWidth ();
|
||||||
cropimg_height = im->getHeight ();
|
cropimg_height = im->getHeight ();
|
||||||
cropimg = new unsigned char [3*cropimg_width*cropimg_height];
|
cropimg = new unsigned char [3*cropimg_width*cropimg_height];
|
||||||
cropimgtrue = new unsigned char [3*cropimg_width*cropimg_height];
|
cropimgtrue = new unsigned char [3*cropimg_width*cropimg_height];
|
||||||
memcpy (cropimg, im->getData(), 3*cropimg_width*cropimg_height);
|
memcpy (cropimg, im->getData(), 3*cropimg_width*cropimg_height);
|
||||||
memcpy (cropimgtrue, imtrue->getData(), 3*cropimg_width*cropimg_height);
|
memcpy (cropimgtrue, imtrue->getData(), 3*cropimg_width*cropimg_height);
|
||||||
cix = ax;
|
cix = ax;
|
||||||
ciy = ay;
|
ciy = ay;
|
||||||
ciw = aw;
|
ciw = aw;
|
||||||
|
@@ -29,9 +29,12 @@
|
|||||||
#include "rtimage.h"
|
#include "rtimage.h"
|
||||||
|
|
||||||
#define CHECKTIME 5000
|
#define CHECKTIME 5000
|
||||||
extern Glib::ustring argv0;
|
|
||||||
|
|
||||||
DirBrowser::DirBrowser () {
|
DirBrowser::DirBrowser () : expandSuccess(false)
|
||||||
|
#ifdef WIN32
|
||||||
|
, volumes(0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
dirtree = Gtk::manage ( new Gtk::TreeView() );
|
dirtree = Gtk::manage ( new Gtk::TreeView() );
|
||||||
scrolledwindow4 = Gtk::manage ( new Gtk::ScrolledWindow() );
|
scrolledwindow4 = Gtk::manage ( new Gtk::ScrolledWindow() );
|
||||||
@@ -144,7 +147,7 @@ void DirBrowser::updateVolumes () {
|
|||||||
|
|
||||||
int nvolumes = GetLogicalDrives ();
|
int nvolumes = GetLogicalDrives ();
|
||||||
if (nvolumes!=volumes) {
|
if (nvolumes!=volumes) {
|
||||||
GThreadLock lock;
|
GThreadLock lock;
|
||||||
|
|
||||||
for (int i=0; i<32; i++)
|
for (int i=0; i<32; i++)
|
||||||
if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted
|
if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted
|
||||||
@@ -237,23 +240,26 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) {
|
|||||||
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end(); it++)
|
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end(); it++)
|
||||||
if (!safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS)
|
if (!safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS)
|
||||||
|| !safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) {
|
|| !safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) {
|
||||||
|
GThreadLock lock;
|
||||||
dirTreeModel->erase (it);
|
dirTreeModel->erase (it);
|
||||||
change = true;
|
change = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// test if new files are created
|
// test if new files are created
|
||||||
std::vector<Glib::ustring> subDirs;
|
std::vector<Glib::ustring> subDirs;
|
||||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
|
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
|
||||||
safe_build_subdir_list (dir, subDirs, options.fbShowHidden);
|
safe_build_subdir_list (dir, subDirs, options.fbShowHidden);
|
||||||
|
|
||||||
for (int i=0; i<subDirs.size(); i++) {
|
for (int i=0; i<subDirs.size(); i++) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end() && !found ; it++)
|
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end() && !found ; it++)
|
||||||
found = (it->get_value (dtColumns.filename)==subDirs[i]);
|
found = (it->get_value (dtColumns.filename)==subDirs[i]);
|
||||||
|
|
||||||
if (!found)
|
if (!found) {
|
||||||
|
GThreadLock lock;
|
||||||
addDir (iter, subDirs[i]);
|
addDir (iter, subDirs[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,9 +359,7 @@ void DirBrowser::file_changed (const Glib::RefPtr<Gio::File>& file, const Glib::
|
|||||||
if (!file || !safe_file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type==Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
|
if (!file || !safe_file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type==Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gdk_threads_enter();
|
|
||||||
updateDir (iter);
|
updateDir (iter);
|
||||||
gdk_threads_leave();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirBrowser::selectDir (Glib::ustring dir) {
|
void DirBrowser::selectDir (Glib::ustring dir) {
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
class DirSelectionListener {
|
class DirSelectionListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~DirSelectionListener () {}
|
||||||
virtual void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="") {}
|
virtual void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -597,6 +597,7 @@ struct spparams {
|
|||||||
|
|
||||||
int setprogressStrUI( void *p )
|
int setprogressStrUI( void *p )
|
||||||
{
|
{
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
spparams *s= static_cast<spparams*>(p);
|
spparams *s= static_cast<spparams*>(p);
|
||||||
|
|
||||||
if( ! s->str.empty() )
|
if( ! s->str.empty() )
|
||||||
@@ -662,6 +663,7 @@ void EditorPanel::refreshProcessingState (bool inProcessingP) {
|
|||||||
s->val = 1.0;
|
s->val = 1.0;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
// Maybe accessing "parent", which is a Gtk object, can justify to get the Gtk lock...
|
||||||
if (!firstProcessingDone && static_cast<RTWindow*>(parent)->getIsFullscreen()) { parent->fullscreen(); }
|
if (!firstProcessingDone && static_cast<RTWindow*>(parent)->getIsFullscreen()) { parent->fullscreen(); }
|
||||||
#endif
|
#endif
|
||||||
firstProcessingDone = true;
|
firstProcessingDone = true;
|
||||||
@@ -1108,19 +1110,11 @@ BatchQueueEntry* EditorPanel::createBatchQueueEntry () {
|
|||||||
ipc->getParams (&pparams);
|
ipc->getParams (&pparams);
|
||||||
//rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
//rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
||||||
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType()==FT_Raw, pparams);
|
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType()==FT_Raw, pparams);
|
||||||
int prevh = options.maxThumbnailHeight;
|
int fullW=0, fullH=0;
|
||||||
int prevw = prevh;
|
isrc->getImageSource()->getFullSize(fullW, fullH, pparams.coarse.rotate==90 || pparams.coarse.rotate==270 ? TR_R90 : TR_NONE);
|
||||||
guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh);
|
int prevh = BatchQueue::calcMaxThumbnailHeight();
|
||||||
double tmpscale;
|
int prevw = int((size_t)fullW * (size_t)prevh / (size_t)fullH);
|
||||||
rtengine::IImage8* img = openThm->processThumbImage (pparams, options.maxThumbnailHeight, tmpscale);
|
return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "../rtengine/dfmanager.h"
|
#include "../rtengine/dfmanager.h"
|
||||||
#include "../rtengine/ffmanager.h"
|
#include "../rtengine/ffmanager.h"
|
||||||
#include "rtimage.h"
|
#include "rtimage.h"
|
||||||
|
#include "guiutils.h"
|
||||||
|
|
||||||
extern Options options;
|
extern Options options;
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ FileBrowser::FileBrowser ()
|
|||||||
/***********************
|
/***********************
|
||||||
* external programs
|
* external programs
|
||||||
* *********************/
|
* *********************/
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Gtk::manage(miOpenDefaultViewer=new Gtk::MenuItem (M("FILEBROWSER_OPENDEFAULTVIEWER")));
|
Gtk::manage(miOpenDefaultViewer=new Gtk::MenuItem (M("FILEBROWSER_OPENDEFAULTVIEWER")));
|
||||||
#else
|
#else
|
||||||
miOpenDefaultViewer=NULL;
|
miOpenDefaultViewer=NULL;
|
||||||
@@ -301,6 +302,12 @@ FileBrowser::~FileBrowser ()
|
|||||||
|
|
||||||
void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) {
|
void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) {
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
trash->set_sensitive (false);
|
trash->set_sensitive (false);
|
||||||
untrash->set_sensitive (false);
|
untrash->set_sensitive (false);
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
@@ -318,6 +325,7 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) {
|
|||||||
partpasteprof->set_sensitive (clipboard.hasProcParams());
|
partpasteprof->set_sensitive (clipboard.hasProcParams());
|
||||||
copyprof->set_sensitive (selected.size()==1);
|
copyprof->set_sensitive (selected.size()==1);
|
||||||
clearprof->set_sensitive (!selected.empty());
|
clearprof->set_sensitive (!selected.empty());
|
||||||
|
}
|
||||||
|
|
||||||
// submenu applmenu
|
// submenu applmenu
|
||||||
int p = 0;
|
int p = 0;
|
||||||
@@ -336,10 +344,10 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) {
|
|||||||
Gtk::Menu* applpartmenu = Gtk::manage (new Gtk::Menu ());
|
Gtk::Menu* applpartmenu = Gtk::manage (new Gtk::Menu ());
|
||||||
//std::vector<Glib::ustring> profnames = profileStore.getProfileNames (); // this is already created for submenu applmenu above
|
//std::vector<Glib::ustring> profnames = profileStore.getProfileNames (); // this is already created for submenu applmenu above
|
||||||
for (size_t i=0; i<profnames.size(); i++) {
|
for (size_t i=0; i<profnames.size(); i++) {
|
||||||
Gtk::MenuItem* mi = Gtk::manage (new Gtk::MenuItem (profnames[i]));
|
Gtk::MenuItem* mi = Gtk::manage (new Gtk::MenuItem (profnames[i]));
|
||||||
applpartmenu->attach (*mi, 0, 1, p, p+1); p++;
|
applpartmenu->attach (*mi, 0, 1, p, p+1); p++;
|
||||||
mi->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyPartialMenuItemActivated), profnames[i]));
|
mi->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyPartialMenuItemActivated), profnames[i]));
|
||||||
mi->show ();
|
mi->show ();
|
||||||
}
|
}
|
||||||
applypartprof->set_submenu (*applpartmenu);
|
applypartprof->set_submenu (*applpartmenu);
|
||||||
|
|
||||||
@@ -428,7 +436,7 @@ void FileBrowser::addEntry (FileBrowserEntry* entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::addEntry_ (FileBrowserEntry* entry) {
|
void FileBrowser::addEntry_ (FileBrowserEntry* entry) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
entry->selected = false;
|
entry->selected = false;
|
||||||
entry->drawable = false;
|
entry->drawable = false;
|
||||||
entry->framed = editedFiles.find (entry->filename)!=editedFiles.end();
|
entry->framed = editedFiles.find (entry->filename)!=editedFiles.end();
|
||||||
@@ -439,14 +447,14 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) {
|
|||||||
entry->getThumbButtonSet()->setColorLabel (entry->thumbnail->getColorLabel());
|
entry->getThumbButtonSet()->setColorLabel (entry->thumbnail->getColorLabel());
|
||||||
entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()==1);
|
entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()==1);
|
||||||
entry->getThumbButtonSet()->setButtonListener (this);
|
entry->getThumbButtonSet()->setButtonListener (this);
|
||||||
entry->resize (getCurrentThumbSize());
|
entry->resize (getThumbnailHeight());
|
||||||
|
|
||||||
// find place in abc order
|
// find place in abc order
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator i = fd.begin();
|
std::vector<ThumbBrowserEntryBase*>::iterator i = fd.begin();
|
||||||
while (i!=fd.end() && *entry < *((FileBrowserEntry*)*i))
|
while (i!=fd.end() && *entry < *((FileBrowserEntry*)*i))
|
||||||
@@ -455,15 +463,15 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) {
|
|||||||
fd.insert (i, entry);
|
fd.insert (i, entry);
|
||||||
|
|
||||||
initEntry (entry);
|
initEntry (entry);
|
||||||
}
|
}
|
||||||
redraw ();
|
redraw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) {
|
FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) {
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (std::vector<ThumbBrowserEntryBase*>::iterator i=fd.begin(); i!=fd.end(); i++)
|
for (std::vector<ThumbBrowserEntryBase*>::iterator i=fd.begin(); i!=fd.end(); i++)
|
||||||
if ((*i)->filename==fname) {
|
if ((*i)->filename==fname) {
|
||||||
@@ -472,8 +480,8 @@ FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) {
|
|||||||
fd.erase (i);
|
fd.erase (i);
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), entry);
|
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), entry);
|
||||||
|
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
l.release();
|
MYWRITERLOCK_RELEASE(l);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (j!=selected.end()) {
|
if (j!=selected.end()) {
|
||||||
@@ -486,7 +494,7 @@ FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) {
|
|||||||
lastClicked = NULL;
|
lastClicked = NULL;
|
||||||
redraw ();
|
redraw ();
|
||||||
|
|
||||||
return (static_cast<FileBrowserEntry*>(entry));
|
return (static_cast<FileBrowserEntry*>(entry));
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -502,22 +510,33 @@ void FileBrowser::close () {
|
|||||||
fbih->destroyed = false;
|
fbih->destroyed = false;
|
||||||
fbih->pending = 0;
|
fbih->pending = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
notifySelectionListener ();
|
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l); // notifySelectionListener will need read access!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
notifySelectionListener ();
|
||||||
|
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_ACQUIRE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// The listener merges parameters with old values, so delete afterwards
|
// The listener merges parameters with old values, so delete afterwards
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
{
|
{
|
||||||
delete fd[i];
|
delete fd.at(i);
|
||||||
}
|
}
|
||||||
fd.clear ();
|
fd.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastClicked = NULL;
|
lastClicked = NULL;
|
||||||
}
|
}
|
||||||
@@ -537,8 +556,17 @@ void FileBrowser::menuColorlabelActivated (Gtk::MenuItem* m) {
|
|||||||
void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
||||||
|
|
||||||
std::vector<FileBrowserEntry*> mselected;
|
std::vector<FileBrowserEntry*> mselected;
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!tbl || (m!=selall && mselected.empty()) )
|
if (!tbl || (m!=selall && mselected.empty()) )
|
||||||
return;
|
return;
|
||||||
@@ -560,8 +588,8 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
|
|
||||||
// Build vector of all file names
|
// Build vector of all file names
|
||||||
std::vector<Glib::ustring> selFileNames;
|
std::vector<Glib::ustring> selFileNames;
|
||||||
for (int i=0; i<selected.size(); i++) {
|
for (int i=0; i<mselected.size(); i++) {
|
||||||
Glib::ustring fn=selected[i]->thumbnail->getFileName();
|
Glib::ustring fn=mselected[i]->thumbnail->getFileName();
|
||||||
|
|
||||||
// Maybe batch processed version
|
// Maybe batch processed version
|
||||||
if (pAct->target==2) fn = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fn), options.saveFormatBatch.format);
|
if (pAct->target==2) fn = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fn), options.saveFormatBatch.format);
|
||||||
@@ -576,7 +604,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
|
|
||||||
if (m==open) {
|
if (m==open) {
|
||||||
std::vector<Thumbnail*> entries;
|
std::vector<Thumbnail*> entries;
|
||||||
for (size_t i=0; i<mselected.size(); i++)
|
for (size_t i=0; i<mselected.size(); i++)
|
||||||
entries.push_back (mselected[i]->thumbnail);
|
entries.push_back (mselected[i]->thumbnail);
|
||||||
tbl->openRequested (entries);
|
tbl->openRequested (entries);
|
||||||
}
|
}
|
||||||
@@ -598,19 +626,19 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
tbl->renameRequested (mselected);
|
tbl->renameRequested (mselected);
|
||||||
else if (m==selall) {
|
else if (m==selall) {
|
||||||
lastClicked = NULL;
|
lastClicked = NULL;
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
if (checkFilter (fd[i])) {
|
if (checkFilter (fd[i])) {
|
||||||
fd[i]->selected = true;
|
fd[i]->selected = true;
|
||||||
selected.push_back (fd[i]);
|
selected.push_back (fd[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
notifySelectionListener ();
|
notifySelectionListener ();
|
||||||
}
|
}
|
||||||
@@ -623,86 +651,103 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (m==autoDF){
|
else if (m==autoDF){
|
||||||
for (size_t i=0; i<mselected.size(); i++){
|
if (!mselected.empty() && bppcl)
|
||||||
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
pp.raw.df_autoselect= true;
|
for (size_t i=0; i<mselected.size(); i++){
|
||||||
pp.raw.dark_frame.clear();
|
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
||||||
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
pp.raw.df_autoselect= true;
|
||||||
}
|
pp.raw.dark_frame.clear();
|
||||||
|
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
||||||
|
}
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
|
|
||||||
}else if (m==selectDF){
|
}else if (m==selectDF){
|
||||||
if( !mselected.empty() ){
|
if( !mselected.empty() ){
|
||||||
rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams();
|
rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams();
|
||||||
Gtk::FileChooserDialog fc("Dark Frame",Gtk::FILE_CHOOSER_ACTION_OPEN );
|
Gtk::FileChooserDialog fc("Dark Frame",Gtk::FILE_CHOOSER_ACTION_OPEN );
|
||||||
FileChooserLastFolderPersister persister(&fc, options.lastDarkframeDir);
|
FileChooserLastFolderPersister persister(&fc, options.lastDarkframeDir);
|
||||||
fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||||
fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY);
|
fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY);
|
||||||
if(!pp.raw.dark_frame.empty())
|
if(!pp.raw.dark_frame.empty())
|
||||||
fc.set_filename( pp.raw.dark_frame );
|
fc.set_filename( pp.raw.dark_frame );
|
||||||
if( fc.run() == Gtk::RESPONSE_APPLY ){
|
if( fc.run() == Gtk::RESPONSE_APPLY ) {
|
||||||
for (size_t i=0; i<mselected.size(); i++){
|
if (bppcl)
|
||||||
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
pp.raw.dark_frame= fc.get_filename();
|
for (size_t i=0; i<mselected.size(); i++){
|
||||||
pp.raw.df_autoselect= false;
|
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
||||||
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
pp.raw.dark_frame= fc.get_filename();
|
||||||
}
|
pp.raw.df_autoselect= false;
|
||||||
}
|
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
||||||
}
|
}
|
||||||
|
if (bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
}else if( m==thisIsDF){
|
}else if( m==thisIsDF){
|
||||||
if( !options.rtSettings.darkFramesPath.empty()) {
|
if( !options.rtSettings.darkFramesPath.empty()) {
|
||||||
if (Gio::File::create_for_path(options.rtSettings.darkFramesPath)->query_exists() ){
|
if (Gio::File::create_for_path(options.rtSettings.darkFramesPath)->query_exists() ){
|
||||||
for (size_t i=0; i<mselected.size(); i++){
|
for (size_t i=0; i<mselected.size(); i++){
|
||||||
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path ( mselected[i]->filename );
|
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path ( mselected[i]->filename );
|
||||||
if( !file )continue;
|
if( !file )continue;
|
||||||
Glib::ustring destName = options.rtSettings.darkFramesPath+ "/" + file->get_basename();
|
Glib::ustring destName = options.rtSettings.darkFramesPath+ "/" + file->get_basename();
|
||||||
Glib::RefPtr<Gio::File> dest = Gio::File::create_for_path ( destName );
|
Glib::RefPtr<Gio::File> dest = Gio::File::create_for_path ( destName );
|
||||||
file->move( dest );
|
file->move( dest );
|
||||||
}
|
}
|
||||||
// Reinit cache
|
// Reinit cache
|
||||||
rtengine::dfm.init( options.rtSettings.darkFramesPath );
|
rtengine::dfm.init( options.rtSettings.darkFramesPath );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Target directory creation failed, we clear the darkFramesPath setting
|
// Target directory creation failed, we clear the darkFramesPath setting
|
||||||
options.rtSettings.darkFramesPath.clear();
|
options.rtSettings.darkFramesPath.clear();
|
||||||
Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), options.rtSettings.darkFramesPath)
|
Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), options.rtSettings.darkFramesPath)
|
||||||
+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED");
|
+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED");
|
||||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
msgd.set_title(M("TP_DARKFRAME_LABEL"));
|
msgd.set_title(M("TP_DARKFRAME_LABEL"));
|
||||||
msgd.run ();
|
msgd.run ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST")+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED");
|
Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST")+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED");
|
||||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
msgd.set_title(M("TP_DARKFRAME_LABEL"));
|
msgd.set_title(M("TP_DARKFRAME_LABEL"));
|
||||||
msgd.run ();
|
msgd.run ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m==autoFF){
|
else if (m==autoFF){
|
||||||
for (size_t i=0; i<mselected.size(); i++){
|
if (!mselected.empty() && bppcl)
|
||||||
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
pp.raw.ff_AutoSelect= true;
|
for (size_t i=0; i<mselected.size(); i++){
|
||||||
pp.raw.ff_file.clear();
|
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
||||||
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
pp.raw.ff_AutoSelect= true;
|
||||||
}
|
pp.raw.ff_file.clear();
|
||||||
|
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
||||||
|
}
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
}
|
}
|
||||||
else if (m==selectFF){
|
else if (m==selectFF){
|
||||||
if( !mselected.empty() ){
|
if( !mselected.empty() ){
|
||||||
rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams();
|
rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams();
|
||||||
Gtk::FileChooserDialog fc("Flat Field",Gtk::FILE_CHOOSER_ACTION_OPEN );
|
Gtk::FileChooserDialog fc("Flat Field",Gtk::FILE_CHOOSER_ACTION_OPEN );
|
||||||
FileChooserLastFolderPersister persister(&fc, options.lastFlatfieldDir);
|
FileChooserLastFolderPersister persister(&fc, options.lastFlatfieldDir);
|
||||||
fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||||
fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY);
|
fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY);
|
||||||
if(!pp.raw.ff_file.empty())
|
if(!pp.raw.ff_file.empty())
|
||||||
fc.set_filename( pp.raw.ff_file );
|
fc.set_filename( pp.raw.ff_file );
|
||||||
if( fc.run() == Gtk::RESPONSE_APPLY ){
|
if( fc.run() == Gtk::RESPONSE_APPLY ) {
|
||||||
for (size_t i=0; i<mselected.size(); i++){
|
if (bppcl)
|
||||||
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
pp.raw.ff_file= fc.get_filename();
|
for (size_t i=0; i<mselected.size(); i++){
|
||||||
pp.raw.ff_AutoSelect= false;
|
rtengine::procparams::ProcParams pp=mselected[i]->thumbnail->getProcParams();
|
||||||
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
pp.raw.ff_file= fc.get_filename();
|
||||||
}
|
pp.raw.ff_AutoSelect= false;
|
||||||
}
|
mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false);
|
||||||
}
|
}
|
||||||
|
if (bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( m==thisIsFF){
|
else if( m==thisIsFF){
|
||||||
if( !options.rtSettings.flatFieldsPath.empty()) {
|
if( !options.rtSettings.flatFieldsPath.empty()) {
|
||||||
@@ -745,13 +790,17 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
mselected[i]->thumbnail->clearProcParams (FILEBROWSER);
|
mselected[i]->thumbnail->clearProcParams (FILEBROWSER);
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
} else if (m==execcustprof) {
|
} else if (m==execcustprof) {
|
||||||
for (size_t i=0; i<mselected.size(); i++) {
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
|
for (size_t i=0; i<mselected.size(); i++) {
|
||||||
mselected[i]->thumbnail->createProcParamsForUpdate (false, true);
|
mselected[i]->thumbnail->createProcParamsForUpdate (false, true);
|
||||||
|
|
||||||
// Empty run to update the thumb
|
// Empty run to update the thumb
|
||||||
rtengine::procparams::ProcParams params = mselected[i]->thumbnail->getProcParams ();
|
rtengine::procparams::ProcParams params = mselected[i]->thumbnail->getProcParams ();
|
||||||
mselected[i]->thumbnail->setProcParams (params, NULL, FILEBROWSER);
|
mselected[i]->thumbnail->setProcParams (params, NULL, FILEBROWSER);
|
||||||
}
|
}
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
} else if (m==clearFromCache) {
|
} else if (m==clearFromCache) {
|
||||||
for (size_t i=0; i<mselected.size(); i++)
|
for (size_t i=0; i<mselected.size(); i++)
|
||||||
tbl->clearFromCacheRequested (mselected, false);
|
tbl->clearFromCacheRequested (mselected, false);
|
||||||
@@ -767,6 +816,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::copyProfile () {
|
void FileBrowser::copyProfile () {
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (selected.size()==1)
|
if (selected.size()==1)
|
||||||
clipboard.setProcParams ((static_cast<FileBrowserEntry*>(selected[0]))->thumbnail->getProcParams());
|
clipboard.setProcParams ((static_cast<FileBrowserEntry*>(selected[0]))->thumbnail->getProcParams());
|
||||||
@@ -776,12 +829,21 @@ void FileBrowser::pasteProfile () {
|
|||||||
|
|
||||||
if (clipboard.hasProcParams()) {
|
if (clipboard.hasProcParams()) {
|
||||||
std::vector<FileBrowserEntry*> mselected;
|
std::vector<FileBrowserEntry*> mselected;
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (unsigned int i=0; i<selected.size(); i++)
|
for (unsigned int i=0; i<selected.size(); i++)
|
||||||
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
||||||
|
}
|
||||||
|
|
||||||
if (!tbl || mselected.empty())
|
if (!tbl || mselected.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
for (unsigned int i=0; i<mselected.size(); i++) {
|
for (unsigned int i=0; i<mselected.size(); i++) {
|
||||||
// copying read only clipboard PartialProfile to a temporary one
|
// copying read only clipboard PartialProfile to a temporary one
|
||||||
rtengine::procparams::PartialProfile cbPartProf = clipboard.getPartialProfile();
|
rtengine::procparams::PartialProfile cbPartProf = clipboard.getPartialProfile();
|
||||||
@@ -791,6 +853,8 @@ void FileBrowser::pasteProfile () {
|
|||||||
mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
||||||
pastedPartProf.deleteInstance();
|
pastedPartProf.deleteInstance();
|
||||||
}
|
}
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
|
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
@@ -801,8 +865,15 @@ void FileBrowser::partPasteProfile () {
|
|||||||
if (clipboard.hasProcParams()) {
|
if (clipboard.hasProcParams()) {
|
||||||
|
|
||||||
std::vector<FileBrowserEntry*> mselected;
|
std::vector<FileBrowserEntry*> mselected;
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (unsigned int i=0; i<selected.size(); i++)
|
for (unsigned int i=0; i<selected.size(); i++)
|
||||||
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
||||||
|
}
|
||||||
|
|
||||||
if (!tbl || mselected.empty())
|
if (!tbl || mselected.empty())
|
||||||
return;
|
return;
|
||||||
@@ -810,6 +881,8 @@ void FileBrowser::partPasteProfile () {
|
|||||||
int i = partialPasteDlg.run ();
|
int i = partialPasteDlg.run ();
|
||||||
if (i == Gtk::RESPONSE_OK) {
|
if (i == Gtk::RESPONSE_OK) {
|
||||||
|
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->beginBatchPParamsChange(mselected.size());
|
||||||
for (unsigned int i=0; i<mselected.size(); i++) {
|
for (unsigned int i=0; i<mselected.size(); i++) {
|
||||||
// copying read only clipboard PartialProfile to a temporary one, initialized to the thumb's ProcParams
|
// copying read only clipboard PartialProfile to a temporary one, initialized to the thumb's ProcParams
|
||||||
mselected[i]->thumbnail->createProcParamsForUpdate(false,false); // this can execute customprofilebuilder to generate param file
|
mselected[i]->thumbnail->createProcParamsForUpdate(false,false); // this can execute customprofilebuilder to generate param file
|
||||||
@@ -823,6 +896,8 @@ void FileBrowser::partPasteProfile () {
|
|||||||
mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
||||||
pastedPartProf.deleteInstance();
|
pastedPartProf.deleteInstance();
|
||||||
}
|
}
|
||||||
|
if (!mselected.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
|
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
@@ -832,9 +907,17 @@ void FileBrowser::partPasteProfile () {
|
|||||||
|
|
||||||
void FileBrowser::openDefaultViewer (int destination) {
|
void FileBrowser::openDefaultViewer (int destination) {
|
||||||
bool success=true;
|
bool success=true;
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (selected.size()==1)
|
if (selected.size()==1)
|
||||||
success=(static_cast<FileBrowserEntry*>(selected[0]))->thumbnail->openDefaultViewer(destination);
|
success=(static_cast<FileBrowserEntry*>(selected[0]))->thumbnail->openDefaultViewer(destination);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Gtk::MessageDialog msgd (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
Gtk::MessageDialog msgd (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
msgd.run ();
|
msgd.run ();
|
||||||
@@ -956,18 +1039,47 @@ bool FileBrowser::keyPressed (GdkEventKey* event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileBrowser::saveThumbnailHeight (int height) {
|
||||||
|
if (!options.sameThumbSize && inTabMode)
|
||||||
|
options.thumbSizeTab = height;
|
||||||
|
else
|
||||||
|
options.thumbSize = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileBrowser::getThumbnailHeight () {
|
||||||
|
// The user could have manually forced the option to a too big value
|
||||||
|
if (!options.sameThumbSize && inTabMode)
|
||||||
|
return std::max(std::min(options.thumbSizeTab, 200), 10);
|
||||||
|
else
|
||||||
|
return std::max(std::min(options.thumbSize, 200), 10);
|
||||||
|
}
|
||||||
|
|
||||||
void FileBrowser::applyMenuItemActivated (Glib::ustring ppname) {
|
void FileBrowser::applyMenuItemActivated (Glib::ustring ppname) {
|
||||||
|
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
const rtengine::procparams::PartialProfile* partProfile = profileStore.getProfile (ppname);
|
const rtengine::procparams::PartialProfile* partProfile = profileStore.getProfile (ppname);
|
||||||
if (partProfile->pparams && !selected.empty()) {
|
if (partProfile->pparams && !selected.empty()) {
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
if (bppcl)
|
||||||
|
bppcl->beginBatchPParamsChange(selected.size());
|
||||||
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
(static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->setProcParams (*partProfile->pparams, partProfile->pedited, FILEBROWSER);
|
(static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->setProcParams (*partProfile->pparams, partProfile->pedited, FILEBROWSER);
|
||||||
|
if (bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::applyPartialMenuItemActivated (Glib::ustring ppname) {
|
void FileBrowser::applyPartialMenuItemActivated (Glib::ustring ppname) {
|
||||||
|
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!tbl || selected.empty())
|
if (!tbl || selected.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -976,6 +1088,8 @@ void FileBrowser::applyPartialMenuItemActivated (Glib::ustring ppname) {
|
|||||||
if (srcProfiles->pparams) {
|
if (srcProfiles->pparams) {
|
||||||
if (partialPasteDlg.run()==Gtk::RESPONSE_OK) {
|
if (partialPasteDlg.run()==Gtk::RESPONSE_OK) {
|
||||||
|
|
||||||
|
if (bppcl)
|
||||||
|
bppcl->beginBatchPParamsChange(selected.size());
|
||||||
for (size_t i=0; i<selected.size(); i++) {
|
for (size_t i=0; i<selected.size(); i++) {
|
||||||
selected[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
selected[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
||||||
|
|
||||||
@@ -986,6 +1100,8 @@ void FileBrowser::applyPartialMenuItemActivated (Glib::ustring ppname) {
|
|||||||
(static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER);
|
(static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER);
|
||||||
dstProfile.deleteInstance();
|
dstProfile.deleteInstance();
|
||||||
}
|
}
|
||||||
|
if (bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
partialPasteDlg.hide ();
|
partialPasteDlg.hide ();
|
||||||
@@ -999,16 +1115,16 @@ void FileBrowser::applyFilter (const BrowserFilter& filter) {
|
|||||||
// remove items not complying the filter from the selection
|
// remove items not complying the filter from the selection
|
||||||
bool selchanged = false;
|
bool selchanged = false;
|
||||||
numFiltered=0;
|
numFiltered=0;
|
||||||
{
|
{
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW); // Don't make this a writer lock!
|
MYWRITERLOCK(l, entryRW); // Don't make this a writer lock! HOMBRE: Why? 'selected' is modified here
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<fd.size(); i++) {
|
for (size_t i=0; i<fd.size(); i++) {
|
||||||
if (checkFilter (fd[i]))
|
if (checkFilter (fd[i]))
|
||||||
numFiltered++;
|
numFiltered++;
|
||||||
else if (fd[i]->selected ) {
|
else if (fd[i]->selected ) {
|
||||||
fd[i]->selected = false;
|
fd[i]->selected = false;
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), fd[i]);
|
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), fd[i]);
|
||||||
selected.erase (j);
|
selected.erase (j);
|
||||||
@@ -1017,7 +1133,7 @@ void FileBrowser::applyFilter (const BrowserFilter& filter) {
|
|||||||
selchanged = true;
|
selchanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selchanged)
|
if (selchanged)
|
||||||
notifySelectionListener ();
|
notifySelectionListener ();
|
||||||
@@ -1138,42 +1254,59 @@ void FileBrowser::fromTrashRequested (std::vector<FileBrowserEntry*> tbe) {
|
|||||||
|
|
||||||
void FileBrowser::rankingRequested (std::vector<FileBrowserEntry*> tbe, int rank) {
|
void FileBrowser::rankingRequested (std::vector<FileBrowserEntry*> tbe, int rank) {
|
||||||
|
|
||||||
for (size_t i=0; i<tbe.size(); i++) {
|
if (!tbe.empty() && bppcl)
|
||||||
// try to load the last saved parameters from the cache or from the paramfile file
|
bppcl->beginBatchPParamsChange(tbe.size());
|
||||||
tbe[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
|
||||||
|
|
||||||
// notify listeners TODO: should do this ONLY when params changed by customprofilebuilder?
|
for (size_t i=0; i<tbe.size(); i++) {
|
||||||
tbe[i]->thumbnail->notifylisterners_procParamsChanged(FILEBROWSER);
|
|
||||||
|
// try to load the last saved parameters from the cache or from the paramfile file
|
||||||
|
tbe[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
||||||
|
|
||||||
|
// notify listeners TODO: should do this ONLY when params changed by customprofilebuilder?
|
||||||
|
tbe[i]->thumbnail->notifylisterners_procParamsChanged(FILEBROWSER);
|
||||||
|
|
||||||
tbe[i]->thumbnail->setRank (rank);
|
tbe[i]->thumbnail->setRank (rank);
|
||||||
tbe[i]->thumbnail->updateCache (); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file
|
tbe[i]->thumbnail->updateCache (); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file
|
||||||
//TODO? - should update pparams instead?
|
//TODO? - should update pparams instead?
|
||||||
|
|
||||||
if (tbe[i]->getThumbButtonSet())
|
if (tbe[i]->getThumbButtonSet())
|
||||||
tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank());
|
tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank());
|
||||||
}
|
}
|
||||||
applyFilter (filter);
|
applyFilter (filter);
|
||||||
|
|
||||||
|
if (!tbe.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::colorlabelRequested (std::vector<FileBrowserEntry*> tbe, int colorlabel) {
|
void FileBrowser::colorlabelRequested (std::vector<FileBrowserEntry*> tbe, int colorlabel) {
|
||||||
|
|
||||||
for (size_t i=0; i<tbe.size(); i++) {
|
if (!tbe.empty() && bppcl)
|
||||||
// try to load the last saved parameters from the cache or from the paramfile file
|
bppcl->beginBatchPParamsChange(tbe.size());
|
||||||
tbe[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
|
||||||
|
|
||||||
// notify listeners TODO: should do this ONLY when params changed by customprofilebuilder?
|
for (size_t i=0; i<tbe.size(); i++) {
|
||||||
tbe[i]->thumbnail->notifylisterners_procParamsChanged(FILEBROWSER);
|
// try to load the last saved parameters from the cache or from the paramfile file
|
||||||
|
tbe[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
||||||
|
|
||||||
|
// notify listeners TODO: should do this ONLY when params changed by customprofilebuilder?
|
||||||
|
tbe[i]->thumbnail->notifylisterners_procParamsChanged(FILEBROWSER);
|
||||||
|
|
||||||
tbe[i]->thumbnail->setColorLabel (colorlabel);
|
tbe[i]->thumbnail->setColorLabel (colorlabel);
|
||||||
tbe[i]->thumbnail->updateCache(); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file
|
tbe[i]->thumbnail->updateCache(); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file
|
||||||
//TODO? - should update pparams instead?
|
//TODO? - should update pparams instead?
|
||||||
if (tbe[i]->getThumbButtonSet())
|
if (tbe[i]->getThumbButtonSet())
|
||||||
tbe[i]->getThumbButtonSet()->setColorLabel (tbe[i]->thumbnail->getColorLabel());
|
tbe[i]->getThumbButtonSet()->setColorLabel (tbe[i]->thumbnail->getColorLabel());
|
||||||
}
|
}
|
||||||
applyFilter (filter);
|
applyFilter (filter);
|
||||||
|
|
||||||
|
if (!tbe.empty() && bppcl)
|
||||||
|
bppcl->endBatchPParamsChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::requestRanking(int rank){
|
void FileBrowser::requestRanking(int rank){
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
std::vector<FileBrowserEntry*> mselected;
|
std::vector<FileBrowserEntry*> mselected;
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
||||||
@@ -1182,6 +1315,10 @@ void FileBrowser::requestRanking(int rank){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::requestColorLabel(int colorlabel){
|
void FileBrowser::requestColorLabel(int colorlabel){
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
std::vector<FileBrowserEntry*> mselected;
|
std::vector<FileBrowserEntry*> mselected;
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
mselected.push_back (static_cast<FileBrowserEntry*>(selected[i]));
|
||||||
@@ -1219,8 +1356,8 @@ void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionD
|
|||||||
|
|
||||||
void FileBrowser::openNextImage () {
|
void FileBrowser::openNextImage () {
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!fd.empty() && selected.size()>0 && !options.tabbedUI) {
|
if (!fd.empty() && selected.size()>0 && !options.tabbedUI) {
|
||||||
@@ -1240,8 +1377,18 @@ void FileBrowser::openNextImage () {
|
|||||||
fd[k]->selected = true;
|
fd[k]->selected = true;
|
||||||
selected.push_back (fd[k]);
|
selected.push_back (fd[k]);
|
||||||
//queue_draw ();
|
//queue_draw ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// this will require a read access
|
||||||
notifySelectionListener ();
|
notifySelectionListener ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_ACQUIRE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// scroll to the selected position
|
// scroll to the selected position
|
||||||
double h1, v1;
|
double h1, v1;
|
||||||
getScrollPosition(h1,v1);
|
getScrollPosition(h1,v1);
|
||||||
@@ -1249,15 +1396,22 @@ void FileBrowser::openNextImage () {
|
|||||||
double h2=selected[0]->getStartX();
|
double h2=selected[0]->getStartX();
|
||||||
double v2=selected[0]->getStartY();
|
double v2=selected[0]->getStartY();
|
||||||
|
|
||||||
|
Thumbnail* thumb = (static_cast<FileBrowserEntry*>(fd[k]))->thumbnail;
|
||||||
|
int minWidth = get_width()-fd[k]->getMinimalWidth();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// scroll only when selected[0] is outside of the displayed bounds
|
// scroll only when selected[0] is outside of the displayed bounds
|
||||||
if (h2+fd[k]->getMinimalWidth()-h1 > get_width())
|
if (h2+minWidth-h1 > get_width())
|
||||||
setScrollPosition(h2-(get_width()-fd[k]->getMinimalWidth()),v2);
|
setScrollPosition(h2-minWidth,v2);
|
||||||
if (h1>h2)
|
if (h1>h2)
|
||||||
setScrollPosition(h2,v2);
|
setScrollPosition(h2,v2);
|
||||||
|
|
||||||
// open the selected image
|
// open the selected image
|
||||||
std::vector<Thumbnail*> entries;
|
std::vector<Thumbnail*> entries;
|
||||||
entries.push_back ((static_cast<FileBrowserEntry*>(fd[k]))->thumbnail);
|
entries.push_back (thumb);
|
||||||
tbl->openRequested (entries);
|
tbl->openRequested (entries);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1270,8 +1424,8 @@ void FileBrowser::openNextImage () {
|
|||||||
|
|
||||||
void FileBrowser::openPrevImage () {
|
void FileBrowser::openPrevImage () {
|
||||||
// TODO: Check for Linux
|
// TODO: Check for Linux
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW);
|
MYWRITERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!fd.empty() && selected.size()>0 && !options.tabbedUI) {
|
if (!fd.empty() && selected.size()>0 && !options.tabbedUI) {
|
||||||
@@ -1291,8 +1445,18 @@ void FileBrowser::openPrevImage () {
|
|||||||
fd[k]->selected = true;
|
fd[k]->selected = true;
|
||||||
selected.push_back (fd[k]);
|
selected.push_back (fd[k]);
|
||||||
//queue_draw ();
|
//queue_draw ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// this will require a read access
|
||||||
notifySelectionListener ();
|
notifySelectionListener ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_ACQUIRE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// scroll to the selected position
|
// scroll to the selected position
|
||||||
double h1, v1;
|
double h1, v1;
|
||||||
getScrollPosition(h1,v1);
|
getScrollPosition(h1,v1);
|
||||||
@@ -1300,15 +1464,22 @@ void FileBrowser::openPrevImage () {
|
|||||||
double h2=selected[0]->getStartX();
|
double h2=selected[0]->getStartX();
|
||||||
double v2=selected[0]->getStartY();
|
double v2=selected[0]->getStartY();
|
||||||
|
|
||||||
|
Thumbnail* thumb = (static_cast<FileBrowserEntry*>(fd[k]))->thumbnail;
|
||||||
|
int minWidth = get_width()-fd[k]->getMinimalWidth();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// scroll only when selected[0] is outside of the displayed bounds
|
// scroll only when selected[0] is outside of the displayed bounds
|
||||||
if (h2+fd[k]->getMinimalWidth()-h1 > get_width())
|
if (h2+minWidth-h1 > get_width())
|
||||||
setScrollPosition(h2-(get_width()-fd[k]->getMinimalWidth()),v2);
|
setScrollPosition(h2-minWidth,v2);
|
||||||
if (h1>h2)
|
if (h1>h2)
|
||||||
setScrollPosition(h2,v2);
|
setScrollPosition(h2,v2);
|
||||||
|
|
||||||
// open the selected image
|
// open the selected image
|
||||||
std::vector<Thumbnail*> entries;
|
std::vector<Thumbnail*> entries;
|
||||||
entries.push_back ((static_cast<FileBrowserEntry*>(fd[k]))->thumbnail);
|
entries.push_back (thumb);
|
||||||
tbl->openRequested (entries);
|
tbl->openRequested (entries);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1324,6 +1495,11 @@ void FileBrowser::selectImage (Glib::ustring fname) {
|
|||||||
|
|
||||||
// need to clear the filter in filecatalog
|
// need to clear the filter in filecatalog
|
||||||
|
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!fd.empty() && !options.tabbedUI) {
|
if (!fd.empty() && !options.tabbedUI) {
|
||||||
for (size_t i=0; i<fd.size(); i++){
|
for (size_t i=0; i<fd.size(); i++){
|
||||||
if (fname==fd[i]->filename && !fd[i]->filtered) {
|
if (fname==fd[i]->filename && !fd[i]->filtered) {
|
||||||
@@ -1338,11 +1514,26 @@ void FileBrowser::selectImage (Glib::ustring fname) {
|
|||||||
fd[i]->selected = true;
|
fd[i]->selected = true;
|
||||||
selected.push_back (fd[i]);
|
selected.push_back (fd[i]);
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// this will require a read access
|
||||||
notifySelectionListener ();
|
notifySelectionListener ();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_ACQUIRE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
// scroll to the selected position
|
// scroll to the selected position
|
||||||
double h=selected[0]->getStartX();
|
double h=selected[0]->getStartX();
|
||||||
double v=selected[0]->getStartY();
|
double v=selected[0]->getStartY();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
|
||||||
setScrollPosition(h,v);
|
setScrollPosition(h,v);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1373,6 +1564,7 @@ void FileBrowser::_thumbRearrangementNeeded () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::thumbRearrangementNeeded () {
|
void FileBrowser::thumbRearrangementNeeded () {
|
||||||
|
// refreshThumbImagesUI will handle thread safety itself
|
||||||
g_idle_add (refreshThumbImagesUI, this);
|
g_idle_add (refreshThumbImagesUI, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,15 +1576,20 @@ void FileBrowser::selectionChanged () {
|
|||||||
void FileBrowser::notifySelectionListener () {
|
void FileBrowser::notifySelectionListener () {
|
||||||
|
|
||||||
if (tbl) {
|
if (tbl) {
|
||||||
|
// TODO: Check for Linux
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<Thumbnail*> thm;
|
std::vector<Thumbnail*> thm;
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
thm.push_back ((static_cast<FileBrowserEntry*>(selected[i]))->thumbnail);
|
thm.push_back ((static_cast<FileBrowserEntry*>(selected[i]))->thumbnail);
|
||||||
tbl->selectionChanged (thm);
|
tbl->selectionChanged (thm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::redrawNeeded (LWButton* button) {
|
void FileBrowser::redrawNeeded (LWButton* button) {
|
||||||
|
GThreadLock lock;
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
FileBrowser::type_trash_changed FileBrowser::trash_changed () {
|
FileBrowser::type_trash_changed FileBrowser::trash_changed () {
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "exiffiltersettings.h"
|
#include "exiffiltersettings.h"
|
||||||
#include "filebrowserentry.h"
|
#include "filebrowserentry.h"
|
||||||
#include "browserfilter.h"
|
#include "browserfilter.h"
|
||||||
|
#include "pparamschangelistener.h"
|
||||||
#include "partialpastedlg.h"
|
#include "partialpastedlg.h"
|
||||||
#include "exportpanel.h"
|
#include "exportpanel.h"
|
||||||
#include "extprog.h"
|
#include "extprog.h"
|
||||||
@@ -34,6 +35,7 @@ class FileBrowserEntry;
|
|||||||
class FileBrowserListener {
|
class FileBrowserListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~FileBrowserListener () {}
|
||||||
virtual void openRequested (std::vector<Thumbnail*> tbe) {}
|
virtual void openRequested (std::vector<Thumbnail*> tbe) {}
|
||||||
virtual void developRequested (std::vector<FileBrowserEntry*> tbe, bool fastmode) {}
|
virtual void developRequested (std::vector<FileBrowserEntry*> tbe, bool fastmode) {}
|
||||||
virtual void renameRequested (std::vector<FileBrowserEntry*> tbe) {}
|
virtual void renameRequested (std::vector<FileBrowserEntry*> tbe) {}
|
||||||
@@ -112,6 +114,7 @@ class FileBrowser : public ThumbBrowserBase,
|
|||||||
|
|
||||||
Glib::RefPtr<Gtk::AccelGroup> pmaccelgroup;
|
Glib::RefPtr<Gtk::AccelGroup> pmaccelgroup;
|
||||||
|
|
||||||
|
BatchPParamsChangeListener* bppcl;
|
||||||
FileBrowserListener* tbl;
|
FileBrowserListener* tbl;
|
||||||
BrowserFilter filter;
|
BrowserFilter filter;
|
||||||
int numFiltered;
|
int numFiltered;
|
||||||
@@ -140,6 +143,7 @@ class FileBrowser : public ThumbBrowserBase,
|
|||||||
FileBrowserEntry* delEntry (const Glib::ustring& fname); // return the entry if found here return NULL otherwise
|
FileBrowserEntry* delEntry (const Glib::ustring& fname); // return the entry if found here return NULL otherwise
|
||||||
void close ();
|
void close ();
|
||||||
|
|
||||||
|
void setBatchPParamsChangeListener (BatchPParamsChangeListener* l) { bppcl = l; }
|
||||||
void setFileBrowserListener (FileBrowserListener* l) { tbl = l; }
|
void setFileBrowserListener (FileBrowserListener* l) { tbl = l; }
|
||||||
|
|
||||||
void menuItemActivated (Gtk::MenuItem* m);
|
void menuItemActivated (Gtk::MenuItem* m);
|
||||||
@@ -156,6 +160,9 @@ class FileBrowser : public ThumbBrowserBase,
|
|||||||
void doubleClicked (ThumbBrowserEntryBase* entry);
|
void doubleClicked (ThumbBrowserEntryBase* entry);
|
||||||
bool keyPressed (GdkEventKey* event);
|
bool keyPressed (GdkEventKey* event);
|
||||||
|
|
||||||
|
void saveThumbnailHeight (int height);
|
||||||
|
int getThumbnailHeight ();
|
||||||
|
|
||||||
void openNextImage ();
|
void openNextImage ();
|
||||||
void openPrevImage ();
|
void openPrevImage ();
|
||||||
void copyProfile ();
|
void copyProfile ();
|
||||||
|
@@ -203,11 +203,14 @@ void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengi
|
|||||||
param->img = img;
|
param->img = img;
|
||||||
param->scale = scale;
|
param->scale = scale;
|
||||||
param->cropParams = cropParams;
|
param->cropParams = cropParams;
|
||||||
g_idle_add (updateImageUI, param);
|
g_idle_add_full (G_PRIORITY_LOW, updateImageUI, param, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine::procparams::CropParams cropParams) {
|
void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine::procparams::CropParams cropParams) {
|
||||||
Glib::RWLock::WriterLock l(lockRW);
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
redrawRequests--;
|
redrawRequests--;
|
||||||
scale = s;
|
scale = s;
|
||||||
@@ -219,6 +222,8 @@ void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine:
|
|||||||
if (preh == img->getHeight ()) {
|
if (preh == img->getHeight ()) {
|
||||||
prew = img->getWidth ();
|
prew = img->getWidth ();
|
||||||
|
|
||||||
|
GThreadLock lock;
|
||||||
|
|
||||||
// Check if image has been rotated since last time
|
// Check if image has been rotated since last time
|
||||||
rotated = preview!=NULL && newLandscape!=landscape;
|
rotated = preview!=NULL && newLandscape!=landscape;
|
||||||
|
|
||||||
|
@@ -38,8 +38,6 @@ using namespace std;
|
|||||||
|
|
||||||
#define CHECKTIME 2000
|
#define CHECKTIME 2000
|
||||||
|
|
||||||
extern Glib::ustring argv0;
|
|
||||||
|
|
||||||
FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) :
|
FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) :
|
||||||
filepanel(filepanel),
|
filepanel(filepanel),
|
||||||
selectedDirectoryId(1),
|
selectedDirectoryId(1),
|
||||||
@@ -462,9 +460,12 @@ void FileCatalog::closeDir () {
|
|||||||
// remove entries
|
// remove entries
|
||||||
selectedDirectory = "";
|
selectedDirectory = "";
|
||||||
fileBrowser->close ();
|
fileBrowser->close ();
|
||||||
fileNameList.clear ();
|
fileNameList.clear ();
|
||||||
|
|
||||||
|
{
|
||||||
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
dirEFS.clear ();
|
dirEFS.clear ();
|
||||||
|
}
|
||||||
hasValidCurrentEFS = false;
|
hasValidCurrentEFS = false;
|
||||||
redrawAll ();
|
redrawAll ();
|
||||||
}
|
}
|
||||||
@@ -537,13 +538,15 @@ void FileCatalog::_refreshProgressBar () {
|
|||||||
// Also mention that this progress bar only measures the FIRST pass (quick thumbnails)
|
// Also mention that this progress bar only measures the FIRST pass (quick thumbnails)
|
||||||
// The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this
|
// The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this
|
||||||
if (!inTabMode) {
|
if (!inTabMode) {
|
||||||
Gtk::Notebook *nb =(Gtk::Notebook *)(filepanel->get_parent());
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
Gtk::Box* hbb=NULL;
|
|
||||||
Gtk::Label *label=NULL;
|
Gtk::Notebook *nb =(Gtk::Notebook *)(filepanel->get_parent());
|
||||||
if( options.mainNBVertical )
|
Gtk::Box* hbb=NULL;
|
||||||
hbb = Gtk::manage (new Gtk::VBox ());
|
Gtk::Label *label=NULL;
|
||||||
else
|
if( options.mainNBVertical )
|
||||||
hbb = Gtk::manage (new Gtk::HBox ());
|
hbb = Gtk::manage (new Gtk::VBox ());
|
||||||
|
else
|
||||||
|
hbb = Gtk::manage (new Gtk::HBox ());
|
||||||
if (!previewsToLoad ) {
|
if (!previewsToLoad ) {
|
||||||
hbb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU)));
|
hbb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU)));
|
||||||
int filteredCount=fileBrowser->getNumFiltered();
|
int filteredCount=fileBrowser->getNumFiltered();
|
||||||
@@ -573,17 +576,9 @@ int refreshProgressBarUI (void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) {
|
void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) {
|
||||||
GThreadLock lock;
|
|
||||||
previewReadyUI (dir_id,fdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called WITHIN gtk thread
|
if ( dir_id != selectedDirectoryId )
|
||||||
void FileCatalog::previewReadyUI (int dir_id, FileBrowserEntry* fdn) {
|
return;
|
||||||
|
|
||||||
if ( dir_id != selectedDirectoryId )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// put it into the "full directory" browser
|
// put it into the "full directory" browser
|
||||||
fdn->setImageAreaToolListener (iatlistener);
|
fdn->setImageAreaToolListener (iatlistener);
|
||||||
@@ -591,6 +586,9 @@ void FileCatalog::previewReadyUI (int dir_id, FileBrowserEntry* fdn) {
|
|||||||
|
|
||||||
// update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...)
|
// update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...)
|
||||||
const CacheImageData* cfs = fdn->thumbnail->getCacheImageData();
|
const CacheImageData* cfs = fdn->thumbnail->getCacheImageData();
|
||||||
|
|
||||||
|
{
|
||||||
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
if (cfs->exifValid) {
|
if (cfs->exifValid) {
|
||||||
if (cfs->fnumber < dirEFS.fnumberFrom)
|
if (cfs->fnumber < dirEFS.fnumberFrom)
|
||||||
dirEFS.fnumberFrom = cfs->fnumber;
|
dirEFS.fnumberFrom = cfs->fnumber;
|
||||||
@@ -613,13 +611,14 @@ void FileCatalog::previewReadyUI (int dir_id, FileBrowserEntry* fdn) {
|
|||||||
dirEFS.cameras.insert (cfs->camera);
|
dirEFS.cameras.insert (cfs->camera);
|
||||||
dirEFS.lenses.insert (cfs->lens);
|
dirEFS.lenses.insert (cfs->lens);
|
||||||
dirEFS.expcomp.insert (cfs->expcomp);
|
dirEFS.expcomp.insert (cfs->expcomp);
|
||||||
|
}
|
||||||
|
|
||||||
previewsLoaded++;
|
previewsLoaded++;
|
||||||
|
|
||||||
g_idle_add (refreshProgressBarUI, this);
|
g_idle_add (refreshProgressBarUI, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int prevfinished (void* data) {
|
int prevfinished (void* data) {
|
||||||
GThreadLock lock;
|
|
||||||
(static_cast<FileCatalog*>(data))->previewsFinishedUI ();
|
(static_cast<FileCatalog*>(data))->previewsFinishedUI ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -627,26 +626,30 @@ int prevfinished (void* data) {
|
|||||||
// Called within GTK UI thread
|
// Called within GTK UI thread
|
||||||
void FileCatalog::previewsFinishedUI () {
|
void FileCatalog::previewsFinishedUI () {
|
||||||
|
|
||||||
redrawAll ();
|
{
|
||||||
previewsToLoad = 0;
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
|
redrawAll ();
|
||||||
|
previewsToLoad = 0;
|
||||||
|
|
||||||
if (filterPanel) {
|
if (filterPanel) {
|
||||||
filterPanel->set_sensitive (true);
|
filterPanel->set_sensitive (true);
|
||||||
if ( !hasValidCurrentEFS ){
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
currentEFS = dirEFS;
|
if ( !hasValidCurrentEFS ){
|
||||||
filterPanel->setFilter ( dirEFS,true );
|
currentEFS = dirEFS;
|
||||||
}else {
|
filterPanel->setFilter ( dirEFS,true );
|
||||||
filterPanel->setFilter ( currentEFS,false );
|
}else {
|
||||||
}
|
filterPanel->setFilter ( currentEFS,false );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (exportPanel)
|
|
||||||
exportPanel->set_sensitive (true);
|
|
||||||
|
|
||||||
// restart anything that might have been loaded low quality
|
if (exportPanel)
|
||||||
fileBrowser->refreshQuickThumbImages();
|
exportPanel->set_sensitive (true);
|
||||||
fileBrowser->applyFilter (getFilter()); // refresh total image count
|
|
||||||
_refreshProgressBar();
|
// restart anything that might have been loaded low quality
|
||||||
|
fileBrowser->refreshQuickThumbImages();
|
||||||
|
fileBrowser->applyFilter (getFilter()); // refresh total image count
|
||||||
|
_refreshProgressBar();
|
||||||
|
}
|
||||||
filepanel->loadingThumbs(M("PROGRESSBAR_READY"),0);
|
filepanel->loadingThumbs(M("PROGRESSBAR_READY"),0);
|
||||||
|
|
||||||
if (!imageToSelect_fname.empty()){
|
if (!imageToSelect_fname.empty()){
|
||||||
@@ -668,8 +671,10 @@ void FileCatalog::previewsFinished (int dir_id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasValidCurrentEFS)
|
if (!hasValidCurrentEFS) {
|
||||||
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
currentEFS = dirEFS;
|
currentEFS = dirEFS;
|
||||||
|
}
|
||||||
|
|
||||||
g_idle_add (prevfinished, this);
|
g_idle_add (prevfinished, this);
|
||||||
}
|
}
|
||||||
@@ -689,9 +694,9 @@ void FileCatalog::refreshThumbImages () {
|
|||||||
void FileCatalog::refreshHeight () {
|
void FileCatalog::refreshHeight () {
|
||||||
int newHeight=fileBrowser->getEffectiveHeight() + buttonBar->get_height();
|
int newHeight=fileBrowser->getEffectiveHeight() + buttonBar->get_height();
|
||||||
if (!options.FileBrowserToolbarSingleRow) {
|
if (!options.FileBrowserToolbarSingleRow) {
|
||||||
newHeight += hbToolBar1->get_height();
|
newHeight += hbToolBar1->get_height();
|
||||||
}
|
}
|
||||||
set_size_request(0, newHeight);
|
set_size_request(0, newHeight+2); // HOMBRE: yeah, +2, there's always 2 pixels missing... sorry for this dirty hack O:)
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileCatalog::_openImage (std::vector<Thumbnail*> tmb) {
|
void FileCatalog::_openImage (std::vector<Thumbnail*> tmb) {
|
||||||
@@ -879,11 +884,14 @@ void FileCatalog::developRequested (std::vector<FileBrowserEntry*> tbe, bool fas
|
|||||||
if (listener) {
|
if (listener) {
|
||||||
std::vector<BatchQueueEntry*> entries;
|
std::vector<BatchQueueEntry*> entries;
|
||||||
|
|
||||||
#pragma omp parallel for ordered
|
// TODO: (HOMBRE) should we still use parallelization here, now that thumbnails are processed asynchronously...?
|
||||||
|
//#pragma omp parallel for ordered
|
||||||
for (size_t i=0; i<tbe.size(); i++) {
|
for (size_t i=0; i<tbe.size(); i++) {
|
||||||
rtengine::procparams::ProcParams params = tbe[i]->thumbnail->getProcParams();
|
FileBrowserEntry* fbe = tbe[i];
|
||||||
|
Thumbnail* th = fbe->thumbnail;
|
||||||
|
rtengine::procparams::ProcParams params = th->getProcParams();
|
||||||
|
|
||||||
// if fast mode is selected, override (disable) prams
|
// if fast mode is selected, override (disable) params
|
||||||
// controlling time and resource consuming tasks
|
// controlling time and resource consuming tasks
|
||||||
// and also those which effect is not pronounced after reducing the image size
|
// and also those which effect is not pronounced after reducing the image size
|
||||||
// TODO!!! could expose selections below via preferences
|
// TODO!!! could expose selections below via preferences
|
||||||
@@ -921,30 +929,19 @@ void FileCatalog::developRequested (std::vector<FileBrowserEntry*> tbe, bool fas
|
|||||||
params.resize.height = options.fastexport_resize_height ;
|
params.resize.height = options.fastexport_resize_height ;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (tbe[i]->filename, tbe[i]->thumbnail->getType()==FT_Raw, params);
|
rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType()==FT_Raw, params);
|
||||||
double tmpscale;
|
|
||||||
rtengine::IImage8* img = tbe[i]->thumbnail->processThumbImage (params, BatchQueue::calcMaxThumbnailHeight(), tmpscale);
|
|
||||||
|
|
||||||
int pw, ph;
|
int pw;
|
||||||
guint8* prev=NULL;
|
int ph = BatchQueue::calcMaxThumbnailHeight();
|
||||||
|
th->getThumbnailSize (pw, ph);
|
||||||
if (img) {
|
|
||||||
pw = img->getWidth ();
|
|
||||||
ph = img->getHeight ();
|
|
||||||
prev = new guint8 [pw*ph*3];
|
|
||||||
memcpy (prev, img->getData (), pw*ph*3);
|
|
||||||
img->free();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
tbe[i]->thumbnail->getThumbnailSize (pw, ph);
|
|
||||||
}
|
|
||||||
|
|
||||||
// processThumbImage is the processing intensive part, but adding to queue must be ordered
|
// processThumbImage is the processing intensive part, but adding to queue must be ordered
|
||||||
#pragma omp ordered
|
//#pragma omp ordered
|
||||||
{
|
//{
|
||||||
entries.push_back(new BatchQueueEntry (pjob, params, tbe[i]->filename, prev, pw, ph, tbe[i]->thumbnail));
|
BatchQueueEntry* bqh = new BatchQueueEntry (pjob, params, fbe->filename, pw, ph, th);
|
||||||
}
|
entries.push_back(bqh);
|
||||||
}
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
listener->addBatchQueueJobs( entries );
|
listener->addBatchQueueJobs( entries );
|
||||||
}
|
}
|
||||||
@@ -1324,8 +1321,10 @@ BrowserFilter FileCatalog::getFilter () {
|
|||||||
if (!filterPanel)
|
if (!filterPanel)
|
||||||
filter.exifFilterEnabled = false;
|
filter.exifFilterEnabled = false;
|
||||||
else {
|
else {
|
||||||
if (!hasValidCurrentEFS)
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
|
if (!hasValidCurrentEFS) {
|
||||||
filter.exifFilter = dirEFS;
|
filter.exifFilter = dirEFS;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
filter.exifFilter = currentEFS;
|
filter.exifFilter = currentEFS;
|
||||||
filter.exifFilterEnabled = filterPanel->isEnabled ();
|
filter.exifFilterEnabled = filterPanel->isEnabled ();
|
||||||
@@ -1408,15 +1407,14 @@ void FileCatalog::winDirChanged () {
|
|||||||
|
|
||||||
void FileCatalog::on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal) {
|
void FileCatalog::on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal) {
|
||||||
|
|
||||||
if (options.has_retained_extention(file->get_parse_name())) {
|
if (options.has_retained_extention(file->get_parse_name())
|
||||||
if (!internal)
|
&& (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)) {
|
||||||
gdk_threads_enter();
|
if (!internal) {
|
||||||
|
GThreadLock lock;
|
||||||
if (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)
|
reparseDirectory ();
|
||||||
reparseDirectory ();
|
}
|
||||||
|
else
|
||||||
if (!internal)
|
reparseDirectory ();
|
||||||
gdk_threads_leave();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1454,7 +1452,7 @@ void FileCatalog::addAndOpenFile (const Glib::ustring& fname) {
|
|||||||
Thumbnail* tmb = cacheMgr->getEntry (file->get_parse_name());
|
Thumbnail* tmb = cacheMgr->getEntry (file->get_parse_name());
|
||||||
if (tmb) {
|
if (tmb) {
|
||||||
FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name());
|
FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name());
|
||||||
previewReadyUI (selectedDirectoryId,entry);
|
previewReady (selectedDirectoryId,entry);
|
||||||
// open the file
|
// open the file
|
||||||
FCOIParams* params = new FCOIParams;
|
FCOIParams* params = new FCOIParams;
|
||||||
params->catalog = this;
|
params->catalog = this;
|
||||||
@@ -1511,7 +1509,9 @@ void FileCatalog::selectionChanged (std::vector<Thumbnail*> tbe) {
|
|||||||
|
|
||||||
void FileCatalog::exifFilterChanged () {
|
void FileCatalog::exifFilterChanged () {
|
||||||
|
|
||||||
currentEFS = filterPanel->getFilter ();
|
// not sure that locking is necessary here...
|
||||||
|
Glib::Mutex::Lock lock(filterMutex);
|
||||||
|
currentEFS = filterPanel->getFilter ();
|
||||||
hasValidCurrentEFS = true;
|
hasValidCurrentEFS = true;
|
||||||
fileBrowser->applyFilter (getFilter ());
|
fileBrowser->applyFilter (getFilter ());
|
||||||
_refreshProgressBar();
|
_refreshProgressBar();
|
||||||
@@ -1557,9 +1557,11 @@ bool FileCatalog::Query_key_pressed (GdkEventKey *event){
|
|||||||
FileCatalog::buttonQueryClearPressed ();
|
FileCatalog::buttonQueryClearPressed ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileCatalog::updateFBQueryTB (bool singleRow) {
|
void FileCatalog::updateFBQueryTB (bool singleRow) {
|
||||||
@@ -1625,9 +1627,11 @@ bool FileCatalog::BrowsePath_key_pressed (GdkEventKey *event){
|
|||||||
BrowsePath->select_region(BrowsePath->get_text_length(), BrowsePath->get_text_length());
|
BrowsePath->select_region(BrowsePath->get_text_length(), BrowsePath->get_text_length());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileCatalog::tbLeftPanel_1_visible (bool visible){
|
void FileCatalog::tbLeftPanel_1_visible (bool visible){
|
||||||
@@ -1806,6 +1810,7 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) {
|
|||||||
FileCatalog::buttonBrowsePathPressed ();
|
FileCatalog::buttonBrowsePathPressed ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -133,6 +133,7 @@ class FileCatalog : public Gtk::VBox,
|
|||||||
Gtk::Button* zoomInButton;
|
Gtk::Button* zoomInButton;
|
||||||
Gtk::Button* zoomOutButton;
|
Gtk::Button* zoomOutButton;
|
||||||
|
|
||||||
|
Glib::Mutex filterMutex;
|
||||||
ExifFilterSettings dirEFS;
|
ExifFilterSettings dirEFS;
|
||||||
ExifFilterSettings currentEFS;
|
ExifFilterSettings currentEFS;
|
||||||
bool hasValidCurrentEFS;
|
bool hasValidCurrentEFS;
|
||||||
@@ -172,21 +173,20 @@ class FileCatalog : public Gtk::VBox,
|
|||||||
void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="");
|
void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="");
|
||||||
void closeDir ();
|
void closeDir ();
|
||||||
void refreshEditedState (const std::set<Glib::ustring>& efiles);
|
void refreshEditedState (const std::set<Glib::ustring>& efiles);
|
||||||
|
|
||||||
// previewloaderlistener interface
|
// previewloaderlistener interface
|
||||||
void previewReadyUI (int dir_id, FileBrowserEntry* fdn);
|
void previewReady (int dir_id, FileBrowserEntry* fdn);
|
||||||
void previewReady (int dir_id, FileBrowserEntry* fdn);
|
void previewsFinished (int dir_id);
|
||||||
void previewsFinished (int dir_id);
|
|
||||||
void previewsFinishedUI ();
|
void previewsFinishedUI ();
|
||||||
void _refreshProgressBar ();
|
void _refreshProgressBar ();
|
||||||
|
|
||||||
// filterpanel interface
|
// filterpanel interface
|
||||||
void exifFilterChanged ();
|
void exifFilterChanged ();
|
||||||
|
|
||||||
// exportpanel interface
|
// exportpanel interface
|
||||||
void exportRequested();
|
void exportRequested();
|
||||||
|
|
||||||
Glib::ustring lastSelectedDir () { return selectedDirectory; }
|
Glib::ustring lastSelectedDir () { return selectedDirectory; }
|
||||||
void setEnabled (bool e); // if not enabled, it does not open image
|
void setEnabled (bool e); // if not enabled, it does not open image
|
||||||
void enableTabMode(bool enable); // sets progress bar
|
void enableTabMode(bool enable); // sets progress bar
|
||||||
|
|
||||||
@@ -210,18 +210,18 @@ class FileCatalog : public Gtk::VBox,
|
|||||||
void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; }
|
void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; }
|
||||||
void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { dirlistener = l; }
|
void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { dirlistener = l; }
|
||||||
|
|
||||||
void setFilterPanel (FilterPanel* fpanel);
|
void setFilterPanel (FilterPanel* fpanel);
|
||||||
void setExportPanel (ExportPanel* expanel);
|
void setExportPanel (ExportPanel* expanel);
|
||||||
void exifInfoButtonToggled();
|
void exifInfoButtonToggled();
|
||||||
void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick);
|
void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick);
|
||||||
bool capture_event(GdkEventButton* event);
|
bool capture_event(GdkEventButton* event);
|
||||||
void filterChanged ();
|
void filterChanged ();
|
||||||
void runFilterDialog ();
|
void runFilterDialog ();
|
||||||
|
|
||||||
void on_realize();
|
void on_realize();
|
||||||
void reparseDirectory ();
|
void reparseDirectory ();
|
||||||
void _openImage (std::vector<Thumbnail*> tmb);
|
void _openImage (std::vector<Thumbnail*> tmb);
|
||||||
|
|
||||||
void zoomIn ();
|
void zoomIn ();
|
||||||
void zoomOut ();
|
void zoomOut ();
|
||||||
|
|
||||||
|
@@ -87,6 +87,7 @@ FilePanel::FilePanel () : parent(NULL) {
|
|||||||
fileCatalog->setFilterPanel (filterPanel);
|
fileCatalog->setFilterPanel (filterPanel);
|
||||||
fileCatalog->setExportPanel (exportPanel);
|
fileCatalog->setExportPanel (exportPanel);
|
||||||
fileCatalog->setImageAreaToolListener (tpc);
|
fileCatalog->setImageAreaToolListener (tpc);
|
||||||
|
fileCatalog->fileBrowser->setBatchPParamsChangeListener (tpc);
|
||||||
|
|
||||||
//------------------
|
//------------------
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ void FilePanel::setAspect () {
|
|||||||
|
|
||||||
void FilePanel::init () {
|
void FilePanel::init () {
|
||||||
|
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
dirBrowser->fillDirTree ();
|
dirBrowser->fillDirTree ();
|
||||||
placesBrowser->refreshPlacesList ();
|
placesBrowser->refreshPlacesList ();
|
||||||
|
|
||||||
@@ -170,40 +172,49 @@ bool FilePanel::fileSelected (Thumbnail* thm) {
|
|||||||
|
|
||||||
ProgressConnector<rtengine::InitialImage*> *ld = new ProgressConnector<rtengine::InitialImage*>();
|
ProgressConnector<rtengine::InitialImage*> *ld = new ProgressConnector<rtengine::InitialImage*>();
|
||||||
ld->startFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), thm->getFileName (), thm->getType()==FT_Raw, &error, parent->getProgressListener()),
|
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) );
|
sigc::bind(sigc::mem_fun(*this,&FilePanel::imageLoaded), thm, ld) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector<rtengine::InitialImage*> *pc ){
|
bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector<rtengine::InitialImage*> *pc ){
|
||||||
|
|
||||||
if (pc->returnValue() && thm) {
|
if (pc->returnValue() && thm) {
|
||||||
|
|
||||||
if (options.tabbedUI) {
|
if (options.tabbedUI) {
|
||||||
EditorPanel* epanel = Gtk::manage (new EditorPanel ());
|
EditorPanel* epanel;
|
||||||
|
{
|
||||||
|
GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm
|
||||||
|
epanel = Gtk::manage (new EditorPanel ());
|
||||||
parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName()));
|
parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName()));
|
||||||
|
}
|
||||||
epanel->open(thm, pc->returnValue() );
|
epanel->open(thm, pc->returnValue() );
|
||||||
} else {
|
} else {
|
||||||
|
{
|
||||||
|
GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm
|
||||||
parent->SetEditorCurrent();
|
parent->SetEditorCurrent();
|
||||||
parent->epanel->open(thm, pc->returnValue() );
|
}
|
||||||
|
parent->epanel->open(thm, pc->returnValue() );
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Glib::ustring msg_ = Glib::ustring("<b>") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n</b>";
|
||||||
|
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
|
msgd.run ();
|
||||||
|
}
|
||||||
|
delete pc;
|
||||||
|
|
||||||
} else {
|
{
|
||||||
Glib::ustring msg_ = Glib::ustring("<b>") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n</b>";
|
GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm
|
||||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
parent->setProgress(0.);
|
||||||
msgd.run ();
|
parent->setProgressStr("");
|
||||||
}
|
}
|
||||||
delete pc;
|
thm->imageLoad( false );
|
||||||
|
|
||||||
parent->setProgress(0.);
|
|
||||||
parent->setProgressStr("");
|
|
||||||
thm->imageLoad( false );
|
|
||||||
|
|
||||||
return false; // MUST return false from idle function
|
return false; // MUST return false from idle function
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilePanel::saveOptions () {
|
void FilePanel::saveOptions () {
|
||||||
|
|
||||||
int winW, winH;
|
int winW, winH;
|
||||||
parent->get_size(winW, winH);
|
parent->get_size(winW, winH);
|
||||||
options.dirBrowserWidth = dirpaned->get_position ();
|
options.dirBrowserWidth = dirpaned->get_position ();
|
||||||
options.dirBrowserHeight = placespaned->get_position ();
|
options.dirBrowserHeight = placespaned->get_position ();
|
||||||
options.browserToolPanelWidth = winW - get_position();
|
options.browserToolPanelWidth = winW - get_position();
|
||||||
@@ -262,6 +273,7 @@ bool FilePanel::handleShortcutKey (GdkEventKey* event) {
|
|||||||
|
|
||||||
void FilePanel::loadingThumbs(Glib::ustring str, double rate)
|
void FilePanel::loadingThumbs(Glib::ustring str, double rate)
|
||||||
{
|
{
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
if( !str.empty())
|
if( !str.empty())
|
||||||
parent->setProgressStr(str);
|
parent->setProgressStr(str);
|
||||||
parent->setProgress( rate );
|
parent->setProgress( rate );
|
||||||
|
@@ -28,6 +28,11 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX==1 && !defined NDEBUG
|
||||||
|
unsigned int MyReaderLock::readerLockCounter = 0;
|
||||||
|
unsigned int MyWriterLock::writerLockCounter = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
Glib::ustring escapeHtmlChars(const Glib::ustring &src) {
|
Glib::ustring escapeHtmlChars(const Glib::ustring &src) {
|
||||||
|
|
||||||
// Sources chars to be escaped
|
// Sources chars to be escaped
|
||||||
|
452
rtgui/guiutils.h
452
rtgui/guiutils.h
@@ -20,7 +20,10 @@
|
|||||||
#define __GUI_UTILS_
|
#define __GUI_UTILS_
|
||||||
|
|
||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
|
#include <glibmm.h>
|
||||||
#include "../rtengine/rtengine.h"
|
#include "../rtengine/rtengine.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Glib::ustring escapeHtmlChars(const Glib::ustring &src);
|
Glib::ustring escapeHtmlChars(const Glib::ustring &src);
|
||||||
bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference=true);
|
bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference=true);
|
||||||
@@ -74,6 +77,455 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
// We don't trace mutex
|
||||||
|
#undef TRACE_MYRWMUTEX
|
||||||
|
#define TRACE_MYRWMUTEX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Uncomment this if you want to bypass the CMakeList options and force the values
|
||||||
|
// Of course, DO NOT COMMIT! :)
|
||||||
|
|
||||||
|
//#undef PROTECT_VECTORS
|
||||||
|
//#define PROTECT_VECTORS 1
|
||||||
|
//#undef TRACE_MYRWMUTEX
|
||||||
|
//#define TRACE_MYRWMUTEX 1
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Custom RWLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
|
||||||
|
*
|
||||||
|
* It may be slower, but thread safe!
|
||||||
|
*/
|
||||||
|
class MyRWMutex {
|
||||||
|
public:
|
||||||
|
Glib::Mutex handlerMutex;
|
||||||
|
Glib::Cond access;
|
||||||
|
size_t writerCount;
|
||||||
|
size_t readerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
Glib::ustring lastWriterFile;
|
||||||
|
int lastWriterLine;
|
||||||
|
// Unfortunately, ownerThread may not be the culprit of a deadlock, it can be another concurrent Reader...
|
||||||
|
void* ownerThread;
|
||||||
|
|
||||||
|
MyRWMutex() : writerCount(0), readerCount(0), lastWriterLine(0), ownerThread(NULL) {}
|
||||||
|
#else
|
||||||
|
MyRWMutex() : writerCount(0), readerCount(0) {}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Custom ReaderLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class MyReaderLock {
|
||||||
|
|
||||||
|
MyRWMutex& rwMutex;
|
||||||
|
bool locked;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
static unsigned int readerLockCounter;
|
||||||
|
int locknumber;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline MyReaderLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
|
||||||
|
#else
|
||||||
|
public:
|
||||||
|
inline MyReaderLock(MyRWMutex& mutex) : rwMutex(mutex)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
locknumber = readerLockCounter++;
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.writerCount) {
|
||||||
|
// There's no writer operating, we can increment the writer count which will lock writers
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " ++ new owner";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The writer count is non null, but we can be the owner of the writer lock
|
||||||
|
// It will be the case if the reader count is non null too.
|
||||||
|
if (!rwMutex.readerCount) {
|
||||||
|
// the mutex is in real write mode, we're waiting to see it null
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
|
||||||
|
#endif
|
||||||
|
while (rwMutex.writerCount)
|
||||||
|
rwMutex.access.wait(rwMutex.handlerMutex);
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = file;
|
||||||
|
rwMutex.lastWriterLine = line;
|
||||||
|
rwMutex.ownerThread = thread;
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R ++ new owner";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// then we can increment the reader count
|
||||||
|
++rwMutex.readerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = true;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
|
||||||
|
inline void acquire(const char* file, const int line)
|
||||||
|
#else
|
||||||
|
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
|
||||||
|
inline void acquire()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (!locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock)";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.writerCount) {
|
||||||
|
// There's no writer operating, we can increment the writer count which will lock writers
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " ++ new owner";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The writer count is non null, but a reader can be the owner of the writer lock,
|
||||||
|
// it will be the case if the reader count is non null too.
|
||||||
|
if (!rwMutex.readerCount) {
|
||||||
|
// the mutex is in real write mode, we're waiting to see it null
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
|
||||||
|
#endif
|
||||||
|
while (rwMutex.writerCount)
|
||||||
|
rwMutex.access.wait(rwMutex.handlerMutex);
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = file;
|
||||||
|
rwMutex.lastWriterLine = line;
|
||||||
|
rwMutex.ownerThread = thread;
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock) ++ new owner";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// then we can increment the reader count
|
||||||
|
++rwMutex.readerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = true;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already locked by this object - R (lock)" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
inline ~MyReaderLock() {
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
// decrement the writer number first
|
||||||
|
--rwMutex.readerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << " / unlocking - R - ReaderCount: " << rwMutex.readerCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.readerCount) {
|
||||||
|
// no more reader, so we decrement the writer count
|
||||||
|
--rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = "";
|
||||||
|
rwMutex.lastWriterLine = 0;
|
||||||
|
rwMutex.ownerThread = NULL;
|
||||||
|
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
|
||||||
|
#endif
|
||||||
|
// and signal the next waiting reader/writer that it's free
|
||||||
|
rwMutex.access.broadcast();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - R" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
|
||||||
|
inline void release(const char* file, const int line)
|
||||||
|
#else
|
||||||
|
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
|
||||||
|
inline void release()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
// decrement the writer number first
|
||||||
|
--rwMutex.readerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << " / unlocking - R (release) - ReaderCount: " << rwMutex.readerCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.readerCount) {
|
||||||
|
// no more reader, so we decrement the writer count
|
||||||
|
--rwMutex.writerCount;
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = "";
|
||||||
|
rwMutex.lastWriterLine = 0;
|
||||||
|
rwMutex.ownerThread = NULL;
|
||||||
|
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
|
||||||
|
#endif
|
||||||
|
// and signal the next waiting reader/writer that it's free
|
||||||
|
rwMutex.access.broadcast();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already unlocked - R (release)" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Custom WriterLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class MyWriterLock {
|
||||||
|
|
||||||
|
MyRWMutex& rwMutex;
|
||||||
|
bool locked;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
static unsigned int writerLockCounter;
|
||||||
|
int locknumber;
|
||||||
|
public:
|
||||||
|
inline MyWriterLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
|
||||||
|
#else
|
||||||
|
public:
|
||||||
|
inline MyWriterLock(MyRWMutex& mutex) : rwMutex(mutex)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
locknumber = writerLockCounter++;
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - W";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rwMutex.writerCount) {
|
||||||
|
// The writer count is non null, so we have to wait for it to be null again
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
|
||||||
|
#endif
|
||||||
|
while (rwMutex.writerCount)
|
||||||
|
rwMutex.access.wait(rwMutex.handlerMutex);
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// then we can increment the writer count
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = file;
|
||||||
|
rwMutex.lastWriterLine = line;
|
||||||
|
rwMutex.ownerThread = thread;
|
||||||
|
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = true;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
|
||||||
|
inline void acquire(const char* file, const int line)
|
||||||
|
#else
|
||||||
|
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
|
||||||
|
inline void acquire()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (!locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rwMutex.writerCount) {
|
||||||
|
// The writer count is non null, so we have to wait for it to be null again
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
|
||||||
|
#endif
|
||||||
|
while (rwMutex.writerCount)
|
||||||
|
rwMutex.access.wait(rwMutex.handlerMutex);
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// then we can increment the reader count
|
||||||
|
++rwMutex.writerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = file;
|
||||||
|
rwMutex.lastWriterLine = line;
|
||||||
|
rwMutex.ownerThread = thread;
|
||||||
|
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = true;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already locked by this object - W (lock)" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
inline ~MyWriterLock() {
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
// decrement the writer number first
|
||||||
|
--rwMutex.writerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << " / unlocking - W";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.writerCount) {
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = "";
|
||||||
|
rwMutex.lastWriterLine = 0;
|
||||||
|
rwMutex.ownerThread = NULL;
|
||||||
|
std::cout << " -- new owner possible!";
|
||||||
|
#endif
|
||||||
|
// The writer count is null again, so we can wake up the next writer or reader
|
||||||
|
rwMutex.access.broadcast();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
|
||||||
|
inline void release(const char* file, const int line)
|
||||||
|
#else
|
||||||
|
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
|
||||||
|
inline void release()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
void* thread = Glib::Thread::self();
|
||||||
|
#endif
|
||||||
|
if (locked) {
|
||||||
|
// to operate safely
|
||||||
|
rwMutex.handlerMutex.lock();
|
||||||
|
|
||||||
|
// decrement the writer number first
|
||||||
|
--rwMutex.writerCount;
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << thread << "/" << locknumber << " / unlocking - W (release)";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rwMutex.writerCount) {
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
rwMutex.lastWriterFile = "";
|
||||||
|
rwMutex.lastWriterLine = 0;
|
||||||
|
rwMutex.ownerThread = NULL;
|
||||||
|
std::cout << " -- new owner possible!";
|
||||||
|
#endif
|
||||||
|
// The writer count is null again, so we can wake up the next writer or reader
|
||||||
|
rwMutex.access.broadcast();
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rwMutex.handlerMutex.unlock();
|
||||||
|
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W (release)" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if TRACE_MYRWMUTEX
|
||||||
|
#define MYREADERLOCK(ln, e) MyReaderLock ln(e, #e, __FILE__, __LINE__);
|
||||||
|
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e, #e, __FILE__, __LINE__);
|
||||||
|
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
|
||||||
|
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
|
||||||
|
#define MYREADERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
|
||||||
|
#define MYWRITERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
|
||||||
|
#else
|
||||||
|
#define MYREADERLOCK(ln, e) MyReaderLock ln(e);
|
||||||
|
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e);
|
||||||
|
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire();
|
||||||
|
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire();
|
||||||
|
#define MYREADERLOCK_RELEASE(ln) ln.release();
|
||||||
|
#define MYWRITERLOCK_RELEASE(ln) ln.release();
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief subclass of Gtk::ScrolledWindow in order to handle the scrollwheel
|
* @brief subclass of Gtk::ScrolledWindow in order to handle the scrollwheel
|
||||||
*/
|
*/
|
||||||
|
@@ -353,6 +353,9 @@ void HistogramRGBArea::renderRGBMarks (int r, int g, int b) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mostly not necessary, but should be in some case
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
|
|
||||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||||
int winx, winy, winw, winh, wind;
|
int winx, winy, winw, winh, wind;
|
||||||
window->get_geometry(winx, winy, winw, winh, wind);
|
window->get_geometry(winx, winy, winw, winh, wind);
|
||||||
@@ -420,8 +423,6 @@ void HistogramRGBArea::renderRGBMarks (int r, int g, int b) {
|
|||||||
|
|
||||||
int histrgbupdate (void* data) {
|
int histrgbupdate (void* data) {
|
||||||
|
|
||||||
gdk_threads_enter ();
|
|
||||||
|
|
||||||
HistogramRGBAreaIdleHelper* harih = static_cast<HistogramRGBAreaIdleHelper*>(data);
|
HistogramRGBAreaIdleHelper* harih = static_cast<HistogramRGBAreaIdleHelper*>(data);
|
||||||
|
|
||||||
if (harih->destroyed) {
|
if (harih->destroyed) {
|
||||||
@@ -429,7 +430,6 @@ int histrgbupdate (void* data) {
|
|||||||
delete harih;
|
delete harih;
|
||||||
else
|
else
|
||||||
harih->pending--;
|
harih->pending--;
|
||||||
gdk_threads_leave ();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +437,6 @@ int histrgbupdate (void* data) {
|
|||||||
harih->harea->queue_draw ();
|
harih->harea->queue_draw ();
|
||||||
|
|
||||||
harih->pending--;
|
harih->pending--;
|
||||||
gdk_threads_leave ();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -453,7 +452,7 @@ void HistogramRGBArea::update (int valh, int rh, int gh, int bh) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
valid = false;
|
valid = false;
|
||||||
|
|
||||||
harih->pending++;
|
harih->pending++;
|
||||||
g_idle_add (histrgbupdate, harih);
|
g_idle_add (histrgbupdate, harih);
|
||||||
}
|
}
|
||||||
@@ -618,8 +617,9 @@ void HistogramArea::update (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
valid = false;
|
valid = false;
|
||||||
|
|
||||||
haih->pending++;
|
haih->pending++;
|
||||||
|
// Can be done outside of the GUI thread
|
||||||
g_idle_add (histupdateUI, haih);
|
g_idle_add (histupdateUI, haih);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "lwbutton.h"
|
#include "lwbutton.h"
|
||||||
|
#include "guiutils.h"
|
||||||
|
|
||||||
LWButton::LWButton (Cairo::RefPtr<Cairo::ImageSurface> i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip)
|
LWButton::LWButton (Cairo::RefPtr<Cairo::ImageSurface> i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip)
|
||||||
: halign(ha), valign(va), icon(i), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) {
|
: halign(ha), valign(va), icon(i), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) {
|
||||||
@@ -145,6 +146,7 @@ bool LWButton::releaseNotify (int x, int y) {
|
|||||||
|
|
||||||
void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context) {
|
void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context) {
|
||||||
|
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
context->set_line_width (1.0);
|
context->set_line_width (1.0);
|
||||||
context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||||
context->rectangle (xpos+0.5, ypos+0.5, w-1.0, h-1.0);
|
context->rectangle (xpos+0.5, ypos+0.5, w-1.0, h-1.0);
|
||||||
@@ -162,10 +164,10 @@ void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context) {
|
|||||||
if (state==Pressed_In)
|
if (state==Pressed_In)
|
||||||
dilat++;
|
dilat++;
|
||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
context->set_source (icon, xpos+dilat, ypos+dilat);
|
context->set_source (icon, xpos+dilat, ypos+dilat);
|
||||||
context->paint ();
|
context->paint ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LWButton::getAlignment (Alignment& ha, Alignment& va) {
|
void LWButton::getAlignment (Alignment& ha, Alignment& va) {
|
||||||
|
@@ -25,6 +25,7 @@ class LWButton;
|
|||||||
class LWButtonListener {
|
class LWButtonListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~LWButtonListener () {}
|
||||||
virtual void buttonPressed (LWButton* button, int actionCode, void* actionData) {}
|
virtual void buttonPressed (LWButton* button, int actionCode, void* actionData) {}
|
||||||
virtual void redrawNeeded (LWButton* button) {}
|
virtual void redrawNeeded (LWButton* button) {}
|
||||||
};
|
};
|
||||||
|
@@ -85,7 +85,7 @@ void LWButtonSet::arrangeButtons (int x, int y, int w, int h) {
|
|||||||
|
|
||||||
void LWButtonSet::move (int nx, int ny) {
|
void LWButtonSet::move (int nx, int ny) {
|
||||||
|
|
||||||
for (size_t i=0; i<buttons.size(); i++) {
|
for (size_t i=0; i<buttons.size(); i++) {
|
||||||
int x, y;
|
int x, y;
|
||||||
buttons[i]->getPosition (x, y);
|
buttons[i]->getPosition (x, y);
|
||||||
buttons[i]->setPosition (x+nx-ax, y+ny-ay);
|
buttons[i]->setPosition (x+nx-ax, y+ny-ay);
|
||||||
@@ -97,7 +97,7 @@ void LWButtonSet::move (int nx, int ny) {
|
|||||||
|
|
||||||
void LWButtonSet::redraw (Cairo::RefPtr<Cairo::Context> context) {
|
void LWButtonSet::redraw (Cairo::RefPtr<Cairo::Context> context) {
|
||||||
|
|
||||||
for (size_t i=0; i<buttons.size(); i++)
|
for (size_t i=0; i<buttons.size(); i++)
|
||||||
buttons[i]->redraw (context);
|
buttons[i]->redraw (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
// This file is for your program, I won't touch it again!
|
// This file is for your program, I won't touch it again!
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <glibmm/thread.h>
|
||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
#include <giomm.h>
|
#include <giomm.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -53,6 +54,22 @@ Glib::ustring creditsPath;
|
|||||||
Glib::ustring licensePath;
|
Glib::ustring licensePath;
|
||||||
Glib::ustring argv1;
|
Glib::ustring argv1;
|
||||||
bool simpleEditor;
|
bool simpleEditor;
|
||||||
|
Glib::Thread* mainThread;
|
||||||
|
|
||||||
|
|
||||||
|
// This recursive mutex will be used by g_thread_enter/leave instead of a simple mutex
|
||||||
|
static Glib::RecMutex myGdkRecMutex;
|
||||||
|
|
||||||
|
static void myGdkLockEnter() { myGdkRecMutex.lock(); }
|
||||||
|
static void myGdkLockLeave() {
|
||||||
|
// Automatic gdk_flush for non main tread
|
||||||
|
#if AUTO_GDK_FLUSH
|
||||||
|
if (Glib::Thread::self() != mainThread) {
|
||||||
|
gdk_flush();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
myGdkRecMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
/* Process line command options
|
/* Process line command options
|
||||||
* Returns
|
* Returns
|
||||||
@@ -105,9 +122,12 @@ int main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Glib::thread_init();
|
Glib::thread_init();
|
||||||
|
gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), ((GCallback) (myGdkLockLeave)));
|
||||||
gdk_threads_init();
|
gdk_threads_init();
|
||||||
Gio::init ();
|
Gio::init ();
|
||||||
|
|
||||||
|
mainThread = Glib::Thread::self();
|
||||||
|
|
||||||
Options::load ();
|
Options::load ();
|
||||||
extProgStore->init();
|
extProgStore->init();
|
||||||
SoundManager::init();
|
SoundManager::init();
|
||||||
@@ -158,9 +178,8 @@ int main(int argc, char **argv)
|
|||||||
printf("Error: no default settings to update!\n");
|
printf("Error: no default settings to update!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
RTWindow *rtWindow = new class RTWindow();
|
|
||||||
gdk_threads_enter ();
|
gdk_threads_enter ();
|
||||||
|
RTWindow *rtWindow = new class RTWindow();
|
||||||
|
|
||||||
// alerting users if the default raw and image profiles are missing
|
// alerting users if the default raw and image profiles are missing
|
||||||
if (options.is_defProfRawMissing()) {
|
if (options.is_defProfRawMissing()) {
|
||||||
|
@@ -806,6 +806,7 @@ void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) {
|
|||||||
bghistvalid = false;
|
bghistvalid = false;
|
||||||
|
|
||||||
mcih->pending++;
|
mcih->pending++;
|
||||||
|
// Can be done outside of the GUI thread
|
||||||
g_idle_add (diagonalmchistupdateUI, mcih);
|
g_idle_add (diagonalmchistupdateUI, mcih);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -250,6 +250,8 @@ void Options::setDefaults () {
|
|||||||
version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize
|
version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize
|
||||||
thumbSize = 240;
|
thumbSize = 240;
|
||||||
thumbSizeTab = 80;
|
thumbSizeTab = 80;
|
||||||
|
thumbSizeQueue = 100;
|
||||||
|
sameThumbSize = true; // preferring speed of switch between file browser and single editor tab
|
||||||
showHistory = true;
|
showHistory = true;
|
||||||
showFilePanelState = 0; // Not used anymore ; was the thumb strip state
|
showFilePanelState = 0; // Not used anymore ; was the thumb strip state
|
||||||
showInfo = true;
|
showInfo = true;
|
||||||
@@ -588,6 +590,8 @@ if (keyFile.has_group ("Profiles")) {
|
|||||||
if (keyFile.has_group ("File Browser")) {
|
if (keyFile.has_group ("File Browser")) {
|
||||||
if (keyFile.has_key ("File Browser", "ThumbnailSize")) thumbSize = keyFile.get_integer ("File Browser", "ThumbnailSize");
|
if (keyFile.has_key ("File Browser", "ThumbnailSize")) thumbSize = keyFile.get_integer ("File Browser", "ThumbnailSize");
|
||||||
if (keyFile.has_key ("File Browser", "ThumbnailSizeTab")) thumbSizeTab = keyFile.get_integer ("File Browser", "ThumbnailSizeTab");
|
if (keyFile.has_key ("File Browser", "ThumbnailSizeTab")) thumbSizeTab = keyFile.get_integer ("File Browser", "ThumbnailSizeTab");
|
||||||
|
if (keyFile.has_key ("File Browser", "ThumbnailSizeQueue")) thumbSizeQueue = keyFile.get_integer ("File Browser", "ThumbnailSizeQueue");
|
||||||
|
if (keyFile.has_key ("File Browser", "SameThumbSize")) sameThumbSize = keyFile.get_integer ("File Browser", "SameThumbSize");
|
||||||
if (keyFile.has_key ("File Browser", "BrowseOnlyRaw")) fbOnlyRaw = keyFile.get_boolean ("File Browser", "BrowseOnlyRaw");
|
if (keyFile.has_key ("File Browser", "BrowseOnlyRaw")) fbOnlyRaw = keyFile.get_boolean ("File Browser", "BrowseOnlyRaw");
|
||||||
if (keyFile.has_key ("File Browser", "BrowserShowsDate")) fbShowDateTime = keyFile.get_boolean ("File Browser", "BrowserShowsDate");
|
if (keyFile.has_key ("File Browser", "BrowserShowsDate")) fbShowDateTime = keyFile.get_boolean ("File Browser", "BrowserShowsDate");
|
||||||
if (keyFile.has_key ("File Browser", "BrowserShowsExif")) fbShowBasicExif = keyFile.get_boolean ("File Browser", "BrowserShowsExif");
|
if (keyFile.has_key ("File Browser", "BrowserShowsExif")) fbShowBasicExif = keyFile.get_boolean ("File Browser", "BrowserShowsExif");
|
||||||
@@ -816,6 +820,8 @@ int Options::saveToFile (Glib::ustring fname) {
|
|||||||
keyFile.set_boolean ("File Browser", "BrowserShowsHidden", fbShowHidden);
|
keyFile.set_boolean ("File Browser", "BrowserShowsHidden", fbShowHidden);
|
||||||
keyFile.set_integer ("File Browser", "ThumbnailSize", thumbSize);
|
keyFile.set_integer ("File Browser", "ThumbnailSize", thumbSize);
|
||||||
keyFile.set_integer ("File Browser", "ThumbnailSizeTab", thumbSizeTab);
|
keyFile.set_integer ("File Browser", "ThumbnailSizeTab", thumbSizeTab);
|
||||||
|
keyFile.set_integer ("File Browser", "ThumbnailSizeQueue", thumbSizeQueue);
|
||||||
|
keyFile.set_integer ("File Browser", "SameThumbSize", sameThumbSize);
|
||||||
keyFile.set_integer ("File Browser", "MaxPreviewHeight", maxThumbnailHeight);
|
keyFile.set_integer ("File Browser", "MaxPreviewHeight", maxThumbnailHeight);
|
||||||
keyFile.set_integer ("File Browser", "MaxCacheEntries", maxCacheEntries);
|
keyFile.set_integer ("File Browser", "MaxCacheEntries", maxCacheEntries);
|
||||||
Glib::ArrayHandle<Glib::ustring> pext = parseExtensions;
|
Glib::ArrayHandle<Glib::ustring> pext = parseExtensions;
|
||||||
|
@@ -122,7 +122,8 @@ class Options {
|
|||||||
bool multiUser;
|
bool multiUser;
|
||||||
static Glib::ustring rtdir;
|
static Glib::ustring rtdir;
|
||||||
Glib::ustring version;
|
Glib::ustring version;
|
||||||
int thumbSize,thumbSizeTab;
|
int thumbSize,thumbSizeTab, thumbSizeQueue;
|
||||||
|
bool sameThumbSize; // Will use only one thumb size for the file browser and the single editor tab, and avoid recomputing them
|
||||||
bool showHistory;
|
bool showHistory;
|
||||||
int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden
|
int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden
|
||||||
bool showInfo;
|
bool showInfo;
|
||||||
|
@@ -26,9 +26,18 @@
|
|||||||
class PParamsChangeListener {
|
class PParamsChangeListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~PParamsChangeListener() {}
|
||||||
virtual void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL) {}
|
virtual void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL) {}
|
||||||
virtual void clearParamChanges () {}
|
virtual void clearParamChanges () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BatchPParamsChangeListener {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~BatchPParamsChangeListener() {}
|
||||||
|
virtual void beginBatchPParamsChange(int numberOfEntries) {}
|
||||||
|
virtual void endBatchPParamsChange() {}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -23,8 +23,8 @@
|
|||||||
using namespace rtengine;
|
using namespace rtengine;
|
||||||
using namespace rtengine::procparams;
|
using namespace rtengine::procparams;
|
||||||
|
|
||||||
PreviewHandler::PreviewHandler () : image(NULL) {
|
PreviewHandler::PreviewHandler () : image(NULL), previewScale(1.) {
|
||||||
|
|
||||||
pih = new PreviewHandlerIdleHelper;
|
pih = new PreviewHandlerIdleHelper;
|
||||||
pih->phandler = this;
|
pih->phandler = this;
|
||||||
pih->destroyed = false;
|
pih->destroyed = false;
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
class PreviewListener {
|
class PreviewListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~PreviewListener () {}
|
||||||
virtual void previewImageChanged () {}
|
virtual void previewImageChanged () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ class PreviewHandler : public rtengine::PreviewImageListener {
|
|||||||
friend int imageReadyUI (void* data);
|
friend int imageReadyUI (void* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rtengine::IImage8* image;
|
rtengine::IImage8* image;
|
||||||
rtengine::procparams::CropParams cropParams;
|
rtengine::procparams::CropParams cropParams;
|
||||||
double previewScale;
|
double previewScale;
|
||||||
PreviewHandlerIdleHelper* pih;
|
PreviewHandlerIdleHelper* pih;
|
||||||
|
@@ -25,9 +25,19 @@
|
|||||||
class ProfileChangeListener {
|
class ProfileChangeListener {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~ProfileChangeListener() {}
|
||||||
virtual void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL) {}
|
virtual void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL) {}
|
||||||
virtual void setDefaults (rtengine::procparams::ProcParams* defparams) {}
|
virtual void setDefaults (rtengine::procparams::ProcParams* defparams) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BatchProfileChangeListener {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~BatchProfileChangeListener() {}
|
||||||
|
virtual void beginBatchProfileChange(int numberOfEntries) {}
|
||||||
|
virtual void endBatchProfileChange() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -58,19 +58,25 @@ ThumbBrowserBase::ThumbBrowserBase ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::scrollChanged () {
|
void ThumbBrowserBase::scrollChanged () {
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
fd[i]->setOffset ((int)(hscroll.get_value()), (int)(vscroll.get_value()));
|
fd[i]->setOffset ((int)(hscroll.get_value()), (int)(vscroll.get_value()));
|
||||||
|
}
|
||||||
|
|
||||||
internal.setPosition ((int)(hscroll.get_value()), (int)(vscroll.get_value()));
|
internal.setPosition ((int)(hscroll.get_value()), (int)(vscroll.get_value()));
|
||||||
|
|
||||||
if (!internal.isDirty()) {
|
if (!internal.isDirty()) {
|
||||||
internal.setDirty ();
|
internal.setDirty ();
|
||||||
internal.queue_draw ();
|
internal.queue_draw ();
|
||||||
// gdk_window_process_updates (get_window()->gobj(), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::scroll (int direction) {
|
void ThumbBrowserBase::scroll (int direction) {
|
||||||
|
// GUI already acquired when here
|
||||||
if (arrangement==TB_Vertical)
|
if (arrangement==TB_Vertical)
|
||||||
vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_step_increment());
|
vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_step_increment());
|
||||||
else
|
else
|
||||||
@@ -78,6 +84,7 @@ void ThumbBrowserBase::scroll (int direction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::scrollPage (int direction) {
|
void ThumbBrowserBase::scrollPage (int direction) {
|
||||||
|
// GUI already acquired when here
|
||||||
if (arrangement==TB_Vertical)
|
if (arrangement==TB_Vertical)
|
||||||
vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment());
|
vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment());
|
||||||
else
|
else
|
||||||
@@ -107,6 +114,9 @@ void ThumbBrowserBase::internalAreaResized (Gtk::Allocation& req) {
|
|||||||
|
|
||||||
void ThumbBrowserBase::configScrollBars () {
|
void ThumbBrowserBase::configScrollBars () {
|
||||||
|
|
||||||
|
// HOMBRE:DELETE ME?
|
||||||
|
GThreadLock tLock; // Acquire the GUI
|
||||||
|
|
||||||
if (inW>0 && inH>0) {
|
if (inW>0 && inH>0) {
|
||||||
|
|
||||||
int iw = internal.get_width ();
|
int iw = internal.get_width ();
|
||||||
@@ -136,10 +146,14 @@ void ThumbBrowserBase::configScrollBars () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::arrangeFiles () {
|
void ThumbBrowserBase::arrangeFiles () {
|
||||||
// TODO: Check for Linux
|
|
||||||
#ifdef WIN32
|
#if PROTECT_VECTORS
|
||||||
Glib::RWLock::ReaderLock l(entryRW);
|
MYREADERLOCK(l, entryRW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// GUI already locked by ::redraw, the only caller of this method for now.
|
||||||
|
// We could lock it one more time, there's no harm excepted (negligible) speed penalty
|
||||||
|
//GThreadLock lock;
|
||||||
|
|
||||||
int N = fd.size ();
|
int N = fd.size ();
|
||||||
// apply filter
|
// apply filter
|
||||||
@@ -152,7 +166,7 @@ void ThumbBrowserBase::arrangeFiles () {
|
|||||||
if (!fd[i]->filtered && fd[i]->getMinimalHeight() > rowHeight)
|
if (!fd[i]->filtered && fd[i]->getMinimalHeight() > rowHeight)
|
||||||
rowHeight = fd[i]->getMinimalHeight ();
|
rowHeight = fd[i]->getMinimalHeight ();
|
||||||
|
|
||||||
if (arrangement==TB_Horizontal) {
|
if (arrangement==TB_Horizontal) {
|
||||||
|
|
||||||
int numOfRows = 1;
|
int numOfRows = 1;
|
||||||
// if (rowHeight>0) {
|
// if (rowHeight>0) {
|
||||||
@@ -183,6 +197,10 @@ void ThumbBrowserBase::arrangeFiles () {
|
|||||||
}
|
}
|
||||||
currx += maxw;
|
currx += maxw;
|
||||||
}
|
}
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
// This will require a Writer access
|
||||||
resizeThumbnailArea (currx, numOfRows*rowHeight);
|
resizeThumbnailArea (currx, numOfRows*rowHeight);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -234,13 +252,17 @@ void ThumbBrowserBase::arrangeFiles () {
|
|||||||
if (currx>0) // there were thumbnails placed in the row
|
if (currx>0) // there were thumbnails placed in the row
|
||||||
curry += rowHeight;
|
curry += rowHeight;
|
||||||
}
|
}
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
// This will require a Writer access
|
||||||
resizeThumbnailArea (colsWidth, curry);
|
resizeThumbnailArea (colsWidth, curry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ThumbBrowserBase::Internal::on_realize()
|
void ThumbBrowserBase::Internal::on_realize() {
|
||||||
{
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
Cairo::FontOptions cfo;
|
Cairo::FontOptions cfo;
|
||||||
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||||
get_pango_context()->set_cairo_font_options (cfo);
|
get_pango_context()->set_cairo_font_options (cfo);
|
||||||
@@ -255,12 +277,20 @@ void ThumbBrowserBase::Internal::on_realize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip) {
|
bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
Glib::ustring ttip = "";
|
Glib::ustring ttip = "";
|
||||||
|
|
||||||
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, parent->entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<parent->fd.size(); i++)
|
for (size_t i=0; i<parent->fd.size(); i++)
|
||||||
if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) {
|
if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) {
|
||||||
ttip = parent->fd[i]->getToolTip (x, y);
|
ttip = parent->fd[i]->getToolTip (x, y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ttip!="") {
|
if (ttip!="") {
|
||||||
tooltip->set_text (ttip);
|
tooltip->set_text (ttip);
|
||||||
return true;
|
return true;
|
||||||
@@ -270,8 +300,8 @@ bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
void ThumbBrowserBase::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||||
|
// GUI will be acquired by refreshThumbImages
|
||||||
refreshThumbImages ();
|
refreshThumbImages ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ThumbBrowserBase::Internal::Internal () : ofsX(0), ofsY(0), parent(NULL), dirty(true) {
|
ThumbBrowserBase::Internal::Internal () : ofsX(0), ofsY(0), parent(NULL), dirty(true) {
|
||||||
@@ -287,10 +317,12 @@ void ThumbBrowserBase::Internal::setPosition (int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_key_press_event (GdkEventKey* event) {
|
bool ThumbBrowserBase::Internal::on_key_press_event (GdkEventKey* event) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
return parent->keyPressed (event);
|
return parent->keyPressed (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) {
|
bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
grab_focus ();
|
grab_focus ();
|
||||||
|
|
||||||
parent->eventTime = event->time;
|
parent->eventTime = event->time;
|
||||||
@@ -310,30 +342,43 @@ bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh) {
|
void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh) {
|
||||||
|
// GUI already acquired
|
||||||
|
|
||||||
ThumbBrowserEntryBase* fileDescr = NULL;
|
ThumbBrowserEntryBase* fileDescr = NULL;
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
if (fd[i]->drawable) {
|
if (fd[i]->drawable) {
|
||||||
if (fd[i]->inside (x, y) && fd[i]->insideWindow (clx, cly, clw, clh))
|
if (fd[i]->inside (x, y) && fd[i]->insideWindow (clx, cly, clw, clh))
|
||||||
fileDescr = fd[i];
|
fileDescr = fd[i];
|
||||||
bool b = fd[i]->pressNotify (button, type, state, x, y);
|
bool b = fd[i]->pressNotify (button, type, state, x, y);
|
||||||
handled = handled || b;
|
handled = handled || b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled || (fileDescr && fileDescr->processing))
|
if (handled || (fileDescr && fileDescr->processing))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (selected.size()==1 && type==GDK_2BUTTON_PRESS && button==1)
|
if (selected.size()==1 && type==GDK_2BUTTON_PRESS && button==1)
|
||||||
doubleClicked (selected[0]);
|
doubleClicked (selected[0]);
|
||||||
else if (button==1 && type==GDK_BUTTON_PRESS) {
|
else if (button==1 && type==GDK_BUTTON_PRESS) {
|
||||||
if (fileDescr && state & GDK_SHIFT_MASK) {
|
if (fileDescr && (state & GDK_SHIFT_MASK)) {
|
||||||
if (selected.empty()) {
|
if (selected.empty()) {
|
||||||
selected.push_back (fileDescr);
|
selected.push_back (fileDescr);
|
||||||
fileDescr->selected = true;
|
fileDescr->selected = true;
|
||||||
lastClicked = fileDescr;
|
lastClicked = fileDescr;
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
selectionChanged ();
|
selectionChanged ();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -363,16 +408,19 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
|
|||||||
selected[i]->selected = false;
|
selected[i]->selected = false;
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
// select thumbnails in the interval
|
// select thumbnails in the interval
|
||||||
for (size_t i=startx; i<=endx; i++) {
|
for (size_t i=startx; i<=endx; i++) {
|
||||||
if (!fd[i]->filtered) {
|
if (!fd[i]->filtered) {
|
||||||
fd[i]->selected = true;
|
fd[i]->selected = true;
|
||||||
selected.push_back (fd[i]);
|
selected.push_back (fd[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
selectionChanged ();
|
selectionChanged ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (fileDescr && state & GDK_CONTROL_MASK) {
|
else if (fileDescr && (state & GDK_CONTROL_MASK)) {
|
||||||
std::vector<ThumbBrowserEntryBase*>::iterator i = std::find (selected.begin(), selected.end(), fileDescr);
|
std::vector<ThumbBrowserEntryBase*>::iterator i = std::find (selected.begin(), selected.end(), fileDescr);
|
||||||
if (i!=selected.end()) {
|
if (i!=selected.end()) {
|
||||||
(*i)->selected = false;
|
(*i)->selected = false;
|
||||||
@@ -383,10 +431,13 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
|
|||||||
fileDescr->selected = true;
|
fileDescr->selected = true;
|
||||||
}
|
}
|
||||||
lastClicked = fileDescr;
|
lastClicked = fileDescr;
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
selectionChanged ();
|
selectionChanged ();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
selected[i]->selected = false;
|
selected[i]->selected = false;
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
if (fileDescr) {
|
if (fileDescr) {
|
||||||
@@ -394,28 +445,36 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
|
|||||||
fileDescr->selected = true;
|
fileDescr->selected = true;
|
||||||
}
|
}
|
||||||
lastClicked = fileDescr;
|
lastClicked = fileDescr;
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
selectionChanged ();
|
selectionChanged ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (fileDescr && button==3 && type==GDK_BUTTON_PRESS) {
|
else if (fileDescr && button==3 && type==GDK_BUTTON_PRESS) {
|
||||||
if (!fileDescr->selected) {
|
if (!fileDescr->selected) {
|
||||||
for (size_t i=0; i<selected.size(); i++)
|
for (size_t i=0; i<selected.size(); i++)
|
||||||
selected[i]->selected = false;
|
selected[i]->selected = false;
|
||||||
selected.clear ();
|
selected.clear ();
|
||||||
fileDescr->selected = true;
|
fileDescr->selected = true;
|
||||||
selected.push_back (fileDescr);
|
selected.push_back (fileDescr);
|
||||||
lastClicked = fileDescr;
|
lastClicked = fileDescr;
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
selectionChanged ();
|
selectionChanged ();
|
||||||
}
|
}
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
rightClicked (fileDescr);
|
rightClicked (fileDescr);
|
||||||
}
|
}
|
||||||
|
} // end of MYWRITERLOCK(l, entryRW);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) {
|
bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) {
|
||||||
// TODO: Check for Linux
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
#ifdef WIN32
|
|
||||||
Glib::RWLock::ReaderLock l(parent->entryRW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
|
||||||
@@ -428,6 +487,12 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) {
|
|||||||
// draw thumbnails
|
// draw thumbnails
|
||||||
Glib::RefPtr<Pango::Context> context = get_pango_context ();
|
Glib::RefPtr<Pango::Context> context = get_pango_context ();
|
||||||
context->set_font_description (get_style()->get_font());
|
context->set_font_description (get_style()->get_font());
|
||||||
|
|
||||||
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, parent->entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<parent->fd.size() && !dirty; i++) { // if dirty meanwhile, cancel and wait for next redraw
|
for (size_t i=0; i<parent->fd.size() && !dirty; i++) { // if dirty meanwhile, cancel and wait for next redraw
|
||||||
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;
|
parent->fd[i]->updatepriority = false;
|
||||||
@@ -436,36 +501,56 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) {
|
|||||||
parent->fd[i]->draw ();
|
parent->fd[i]->draw ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_button_release_event (GdkEventButton* event) {
|
bool ThumbBrowserBase::Internal::on_button_release_event (GdkEventButton* event) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
int w = get_width();
|
int w = get_width();
|
||||||
int h = get_height();
|
int h = get_height();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, parent->entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<parent->fd.size(); i++)
|
for (size_t i=0; i<parent->fd.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]->releaseNotify (event->button, event->type, event->state, (int)event->x, (int)event->y);
|
ThumbBrowserEntryBase* tbe = parent->fd[i];
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
// This will require a Writer access...
|
||||||
|
tbe->releaseNotify (event->button, event->type, event->state, (int)event->x, (int)event->y);
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_ACQUIRE(l);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_motion_notify_event (GdkEventMotion* event) {
|
bool ThumbBrowserBase::Internal::on_motion_notify_event (GdkEventMotion* event) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
int w = get_width();
|
int w = get_width();
|
||||||
int h = get_height();
|
int h = get_height();
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, parent->entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<parent->fd.size(); i++)
|
for (size_t i=0; i<parent->fd.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)) {
|
||||||
#ifdef WIN32
|
/*#if PROTECT_VECTORS
|
||||||
//l.release(); // motionNotify calls the queue, which locks
|
MYREADERLOCK_RELEASE(l); // motionNotify calls the queue, which locks
|
||||||
#endif
|
#endif*/
|
||||||
parent->fd[i]->motionNotify ((int)event->x, (int)event->y);
|
parent->fd[i]->motionNotify ((int)event->x, (int)event->y);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) {
|
bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) {
|
||||||
|
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||||
|
|
||||||
parent->scroll (event->direction);
|
parent->scroll (event->direction);
|
||||||
return true;
|
return true;
|
||||||
@@ -474,6 +559,7 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) {
|
|||||||
|
|
||||||
void ThumbBrowserBase::redraw () {
|
void ThumbBrowserBase::redraw () {
|
||||||
|
|
||||||
|
GThreadLock lock;
|
||||||
arrangeFiles ();
|
arrangeFiles ();
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
@@ -481,30 +567,31 @@ void ThumbBrowserBase::redraw () {
|
|||||||
void ThumbBrowserBase::zoomChanged (bool zoomIn) {
|
void ThumbBrowserBase::zoomChanged (bool zoomIn) {
|
||||||
|
|
||||||
int newHeight=0;
|
int newHeight=0;
|
||||||
int optThumbSize=getCurrentThumbSize();
|
int optThumbSize=getThumbnailHeight();
|
||||||
if (zoomIn)
|
if (zoomIn)
|
||||||
for (size_t i=0; i<options.thumbnailZoomRatios.size(); i++) {
|
for (size_t i=0; i<options.thumbnailZoomRatios.size(); i++) {
|
||||||
newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight());
|
newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight());
|
||||||
if (newHeight > optThumbSize)
|
if (newHeight > optThumbSize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (size_t i=options.thumbnailZoomRatios.size()-1; i>0; i--) {
|
for (size_t i=options.thumbnailZoomRatios.size()-1; i>0; i--) {
|
||||||
newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight());
|
newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight());
|
||||||
if (newHeight < optThumbSize)
|
if (newHeight < optThumbSize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
previewHeight = newHeight;
|
previewHeight = newHeight;
|
||||||
if (inTabMode) options.thumbSizeTab = newHeight; else options.thumbSize = newHeight;
|
|
||||||
|
|
||||||
{
|
saveThumbnailHeight(newHeight);
|
||||||
// TODO: Check for Linux
|
|
||||||
#ifdef WIN32
|
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (size_t i=0; i<fd.size(); i++) fd[i]->resize (previewHeight);
|
{
|
||||||
}
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
|
fd[i]->resize (previewHeight);
|
||||||
|
}
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -512,44 +599,46 @@ void ThumbBrowserBase::zoomChanged (bool zoomIn) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ThumbBrowserBase::getCurrentThumbSize() { return inTabMode ? options.thumbSizeTab : options.thumbSize; }
|
|
||||||
|
|
||||||
void ThumbBrowserBase::refreshThumbImages () {
|
void ThumbBrowserBase::refreshThumbImages () {
|
||||||
{
|
|
||||||
// TODO: Check for Linux
|
|
||||||
#ifdef WIN32
|
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int previewHeight = getCurrentThumbSize();
|
int previewHeight = getThumbnailHeight();
|
||||||
for (size_t i=0; i<fd.size(); i++) fd[i]->resize (previewHeight);
|
{
|
||||||
}
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t i=0; i<fd.size(); i++) fd[i]->resize (previewHeight);
|
||||||
|
}
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::refreshQuickThumbImages () {
|
void ThumbBrowserBase::refreshQuickThumbImages () {
|
||||||
// TODO: Check for Linux
|
#if PROTECT_VECTORS
|
||||||
#ifdef WIN32
|
MYWRITERLOCK(l, entryRW);
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
for (size_t i=0; i<fd.size(); ++i) fd[i]->refreshQuickThumbnailImage ();
|
for (size_t i=0; i<fd.size(); ++i) fd[i]->refreshQuickThumbnailImage ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::refreshEditedState (const std::set<Glib::ustring>& efiles) {
|
void ThumbBrowserBase::refreshEditedState (const std::set<Glib::ustring>& efiles) {
|
||||||
|
|
||||||
editedFiles = efiles;
|
editedFiles = efiles;
|
||||||
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
fd[i]->framed = editedFiles.find (fd[i]->filename)!=editedFiles.end();
|
fd[i]->framed = editedFiles.find (fd[i]->filename)!=editedFiles.end();
|
||||||
|
}
|
||||||
|
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ThumbBrowserBase::setArrangement (Arrangement a) {
|
void ThumbBrowserBase::setArrangement (Arrangement a) {
|
||||||
|
|
||||||
arrangement = a;
|
arrangement = a;
|
||||||
redraw ();
|
redraw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,31 +646,40 @@ void ThumbBrowserBase::enableTabMode(bool enable) {
|
|||||||
inTabMode = enable;
|
inTabMode = enable;
|
||||||
arrangement = inTabMode ? ThumbBrowserBase::TB_Horizontal : ThumbBrowserBase::TB_Vertical;
|
arrangement = inTabMode ? ThumbBrowserBase::TB_Horizontal : ThumbBrowserBase::TB_Vertical;
|
||||||
|
|
||||||
if (options.thumbSizeTab!=options.thumbSize) {
|
if (!options.sameThumbSize && (options.thumbSizeTab!=options.thumbSize)) {
|
||||||
// TODO: Check for Linux
|
#if PROTECT_VECTORS
|
||||||
#ifdef WIN32
|
MYWRITERLOCK(l, entryRW);
|
||||||
Glib::RWLock::WriterLock l(entryRW);
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
for (size_t i=0; i<fd.size(); i++)
|
for (size_t i=0; i<fd.size(); i++)
|
||||||
fd[i]->resize (getCurrentThumbSize());
|
fd[i]->resize (getThumbnailHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw ();
|
redraw ();
|
||||||
|
|
||||||
// Scroll to selected position if going into ribbon mode or back
|
// Scroll to selected position if going into ribbon mode or back
|
||||||
// Tab mode is horizontal, file browser is vertical
|
// Tab mode is horizontal, file browser is vertical
|
||||||
|
{
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!selected.empty()) {
|
if (!selected.empty()) {
|
||||||
if (inTabMode) {
|
if (inTabMode) {
|
||||||
double h=selected[0]->getStartX();
|
double h=selected[0]->getStartX();
|
||||||
hscroll.set_value (min(h, hscroll.get_adjustment()->get_upper()));
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
|
hscroll.set_value (min(h, hscroll.get_adjustment()->get_upper()));
|
||||||
} else {
|
} else {
|
||||||
double v=selected[0]->getStartY();
|
double v=selected[0]->getStartY();
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK_RELEASE(l);
|
||||||
|
#endif
|
||||||
vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper()));
|
vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::initEntry (ThumbBrowserEntryBase* entry) {
|
void ThumbBrowserBase::initEntry (ThumbBrowserEntryBase* entry) {
|
||||||
@@ -602,6 +700,10 @@ void ThumbBrowserBase::setScrollPosition (double h, double v) {
|
|||||||
int ThumbBrowserBase::getEffectiveHeight() {
|
int ThumbBrowserBase::getEffectiveHeight() {
|
||||||
int h=hscroll.get_height() + 2; // have 2 pixels rounding error for scroll bars to appear
|
int h=hscroll.get_height() + 2; // have 2 pixels rounding error for scroll bars to appear
|
||||||
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, entryRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Filtered items do not change in size, so take a non-filtered
|
// Filtered items do not change in size, so take a non-filtered
|
||||||
for (size_t i=0;i<fd.size();i++)
|
for (size_t i=0;i<fd.size();i++)
|
||||||
if (!fd[i]->filtered) {
|
if (!fd[i]->filtered) {
|
||||||
@@ -610,10 +712,13 @@ int ThumbBrowserBase::getEffectiveHeight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserBase::redrawNeeded (ThumbBrowserEntryBase* entry) {
|
void ThumbBrowserBase::redrawNeeded (ThumbBrowserEntryBase* entry) {
|
||||||
|
|
||||||
|
// HOMBRE:DELETE ME?
|
||||||
|
GThreadLock tLock; // Acquire the GUI
|
||||||
|
|
||||||
if (entry->insideWindow (0, 0, internal.get_width(), internal.get_height())) {
|
if (entry->insideWindow (0, 0, internal.get_width(), internal.get_height())) {
|
||||||
if (!internal.isDirty ()) {
|
if (!internal.isDirty ()) {
|
||||||
internal.setDirty ();
|
internal.setDirty ();
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "thumbbrowserentrybase.h"
|
#include "thumbbrowserentrybase.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "guiutils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space
|
* Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space
|
||||||
@@ -54,6 +55,8 @@ class ThumbBrowserBase : public Gtk::VBox {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int getMaxThumbnailHeight() const { return options.maxThumbnailHeight; } // Differs between batch and file
|
virtual int getMaxThumbnailHeight() const { return options.maxThumbnailHeight; } // Differs between batch and file
|
||||||
|
virtual void saveThumbnailHeight (int height)=0;
|
||||||
|
virtual int getThumbnailHeight ()=0;
|
||||||
|
|
||||||
Internal internal;
|
Internal internal;
|
||||||
Gtk::HScrollbar hscroll;
|
Gtk::HScrollbar hscroll;
|
||||||
@@ -62,7 +65,6 @@ class ThumbBrowserBase : public Gtk::VBox {
|
|||||||
int inW, inH;
|
int inW, inH;
|
||||||
|
|
||||||
bool inTabMode; // Tab mode has e.g. different preview heights
|
bool inTabMode; // Tab mode has e.g. different preview heights
|
||||||
int getCurrentThumbSize(); // depending on filmstrip/file browser mode
|
|
||||||
|
|
||||||
void resizeThumbnailArea (int w, int h);
|
void resizeThumbnailArea (int w, int h);
|
||||||
void internalAreaResized (Gtk::Allocation& req);
|
void internalAreaResized (Gtk::Allocation& req);
|
||||||
@@ -80,7 +82,7 @@ class ThumbBrowserBase : public Gtk::VBox {
|
|||||||
|
|
||||||
int eventTime;
|
int eventTime;
|
||||||
|
|
||||||
Glib::RWLock entryRW; // Locks access to following vectors
|
MyRWMutex entryRW; // Locks access to following 'fd' AND 'selected'
|
||||||
std::vector<ThumbBrowserEntryBase*> fd;
|
std::vector<ThumbBrowserEntryBase*> fd;
|
||||||
std::vector<ThumbBrowserEntryBase*> selected;
|
std::vector<ThumbBrowserEntryBase*> selected;
|
||||||
ThumbBrowserEntryBase* lastClicked;
|
ThumbBrowserEntryBase* lastClicked;
|
||||||
|
@@ -22,26 +22,18 @@
|
|||||||
#include "../rtengine/mytime.h"
|
#include "../rtengine/mytime.h"
|
||||||
|
|
||||||
ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname)
|
ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname)
|
||||||
: preh(0), preview(NULL), buttonSet(NULL), exp_width(0), exp_height(0), redrawRequests(0),
|
: fnlabw(0), fnlabh(0), dtlabw(0), dtlabh(0), exlabw(0), exlabh(0), prew(0), preh(0),
|
||||||
parent(NULL), filename(fname), exifline(""), datetimeline(""), selected(false),
|
prex(0), prey(0), upperMargin(6), borderWidth(1), textGap(6), sideMargin(8), lowerMargin(8),
|
||||||
drawable(false),framed(false), processing(false), italicstyle(false),
|
preview(NULL), dispname(Glib::path_get_basename (fname)), buttonSet(NULL), width(0), height(0),
|
||||||
updatepriority(false) {
|
exp_width(0), exp_height(0), startx(0), starty(0), ofsX(0), ofsY(0), redrawRequests(0),
|
||||||
|
parent(NULL), bbSelected(false), bbFramed(false), bbPreview(NULL),
|
||||||
shortname = Glib::path_get_basename (fname);
|
thumbnail(NULL), filename(fname), shortname(dispname), exifline(""), datetimeline(""),
|
||||||
dispname = shortname;
|
selected(false), drawable(false), filtered(false), framed(false), processing(false), italicstyle(false),
|
||||||
|
edited(false), recentlysaved(false), updatepriority(false) {}
|
||||||
upperMargin = 6;
|
|
||||||
borderWidth = 1;
|
|
||||||
sideMargin = 8;
|
|
||||||
lowerMargin = 8;
|
|
||||||
textGap = 6;
|
|
||||||
|
|
||||||
ofsX = ofsY = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThumbBrowserEntryBase::~ThumbBrowserEntryBase () {
|
ThumbBrowserEntryBase::~ThumbBrowserEntryBase () {
|
||||||
|
|
||||||
delete [] preview;
|
if (preview) delete [] preview;
|
||||||
delete buttonSet;
|
delete buttonSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +251,10 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserEntryBase::resize (int h) {
|
void ThumbBrowserEntryBase::resize (int h) {
|
||||||
Glib::RWLock::WriterLock l(lockRW);
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
height = h;
|
height = h;
|
||||||
int old_preh = preh, old_width = width;
|
int old_preh = preh, old_width = width;
|
||||||
@@ -348,7 +343,9 @@ void ThumbBrowserEntryBase::draw () {
|
|||||||
if (!drawable || !parent)
|
if (!drawable || !parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Glib::RWLock::ReaderLock l(lockRW); // No resizes, position moves etc. inbetween
|
#if PROTECT_VECTORS
|
||||||
|
MYREADERLOCK(l, lockRW); // No resizes, position moves etc. inbetween
|
||||||
|
#endif
|
||||||
|
|
||||||
int bbWidth, bbHeight;
|
int bbWidth, bbHeight;
|
||||||
if (backBuffer)
|
if (backBuffer)
|
||||||
@@ -376,12 +373,16 @@ void ThumbBrowserEntryBase::draw () {
|
|||||||
// redraw button set above the thumbnail
|
// redraw button set above the thumbnail
|
||||||
if (buttonSet) {
|
if (buttonSet) {
|
||||||
buttonSet->setColors (selected ? bgs : bgn, selected ? bgn : bgs);
|
buttonSet->setColors (selected ? bgs : bgn, selected ? bgn : bgs);
|
||||||
buttonSet->redraw (w->get_window()->create_cairo_context());
|
Cairo::RefPtr<Cairo::Context> cc = w->get_window()->create_cairo_context();
|
||||||
|
buttonSet->redraw (cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserEntryBase::setPosition (int x, int y, int w, int h) {
|
void ThumbBrowserEntryBase::setPosition (int x, int y, int w, int h) {
|
||||||
Glib::RWLock::WriterLock l(lockRW);
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
exp_width = w;
|
exp_width = w;
|
||||||
exp_height = h;
|
exp_height = h;
|
||||||
@@ -393,7 +394,10 @@ void ThumbBrowserEntryBase::setPosition (int x, int y, int w, int h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThumbBrowserEntryBase::setOffset (int x, int y) {
|
void ThumbBrowserEntryBase::setOffset (int x, int y) {
|
||||||
Glib::RWLock::WriterLock l(lockRW);
|
|
||||||
|
#if PROTECT_VECTORS
|
||||||
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
#endif
|
||||||
|
|
||||||
ofsX = -x;
|
ofsX = -x;
|
||||||
ofsY = -y;
|
ofsY = -y;
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
#include "lwbuttonset.h"
|
#include "lwbuttonset.h"
|
||||||
#include "thumbnail.h"
|
#include "thumbnail.h"
|
||||||
|
#include "guiutils.h"
|
||||||
|
|
||||||
class ThumbBrowserBase;
|
class ThumbBrowserBase;
|
||||||
class ThumbBrowserEntryBase {
|
class ThumbBrowserEntryBase {
|
||||||
@@ -42,7 +43,7 @@ protected:
|
|||||||
int lowerMargin;
|
int lowerMargin;
|
||||||
|
|
||||||
|
|
||||||
Glib::RWLock lockRW; // Locks access to all image thumb changing actions
|
MyRWMutex lockRW; // Locks access to all image thumb changing actions
|
||||||
|
|
||||||
guint8* preview; // holds the preview image. used in updateBackBuffer. TODO Olli: Make a cache to reduce mem significantly
|
guint8* preview; // holds the preview image. used in updateBackBuffer. TODO Olli: Make a cache to reduce mem significantly
|
||||||
|
|
||||||
|
@@ -48,6 +48,8 @@ public:
|
|||||||
|
|
||||||
Job():
|
Job():
|
||||||
tbe_(0),
|
tbe_(0),
|
||||||
|
priority_(NULL),
|
||||||
|
upgrade_(false),
|
||||||
listener_(0)
|
listener_(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ public:
|
|||||||
Glib::Cond inactive_;
|
Glib::Cond inactive_;
|
||||||
|
|
||||||
void
|
void
|
||||||
processNextJob(void)
|
processNextJob()
|
||||||
{
|
{
|
||||||
Job j;
|
Job j;
|
||||||
|
|
||||||
|
@@ -33,13 +33,18 @@
|
|||||||
|
|
||||||
using namespace rtengine::procparams;
|
using namespace rtengine::procparams;
|
||||||
|
|
||||||
Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf)
|
Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf, const rtengine::procparams::ProcParams *pparams)
|
||||||
: fname(fname), cfs(*cf), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL),
|
: fname(fname), cfs(*cf), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL),
|
||||||
pparamsValid(false), needsReProcessing(true),imageLoading(false), lastImg(NULL),
|
pparamsValid(false), needsReProcessing(true),imageLoading(false), lastImg(NULL),
|
||||||
lastW(0), lastH(0), lastScale(0), initial_(false) {
|
lastW(0), lastH(0), lastScale(0), initial_(false)
|
||||||
|
{
|
||||||
|
|
||||||
cfs.load (getCacheFileName ("data")+".txt");
|
if (pparams) {
|
||||||
loadProcParams ();
|
this->pparams = *pparams;
|
||||||
|
pparamsValid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loadProcParams ();
|
||||||
_loadThumbnail ();
|
_loadThumbnail ();
|
||||||
generateExifDateTimeStrings ();
|
generateExifDateTimeStrings ();
|
||||||
|
|
||||||
@@ -55,25 +60,31 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageDa
|
|||||||
setStage(cfs.inTrashOld);
|
setStage(cfs.inTrashOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete tpp;
|
delete tpp;
|
||||||
tpp = 0;
|
tpp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5)
|
Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5, const rtengine::procparams::ProcParams *pparams)
|
||||||
: fname(fname), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL), pparamsValid(false),
|
: fname(fname), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL), pparamsValid(false),
|
||||||
needsReProcessing(true),imageLoading(false), lastImg(NULL),
|
needsReProcessing(true),imageLoading(false), lastImg(NULL),
|
||||||
initial_(true) {
|
initial_(true)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
cfs.md5 = md5;
|
cfs.md5 = md5;
|
||||||
_generateThumbnailImage ();
|
_generateThumbnailImage ();
|
||||||
loadProcParams ();
|
if (pparams) {
|
||||||
|
this->pparams = *pparams;
|
||||||
|
pparamsValid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loadProcParams ();
|
||||||
cfs.recentlySaved = false;
|
cfs.recentlySaved = false;
|
||||||
|
|
||||||
initial_ = false;
|
initial_ = false;
|
||||||
|
|
||||||
delete tpp;
|
delete tpp;
|
||||||
tpp = 0;
|
tpp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thumbnail::_generateThumbnailImage () {
|
void Thumbnail::_generateThumbnailImage () {
|
||||||
@@ -96,7 +107,7 @@ void Thumbnail::_generateThumbnailImage () {
|
|||||||
cfs.timeValid = false;
|
cfs.timeValid = false;
|
||||||
|
|
||||||
if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg") {
|
if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg") {
|
||||||
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, infoFromImage (fname));
|
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1);
|
||||||
if (tpp)
|
if (tpp)
|
||||||
cfs.format = FT_Jpeg;
|
cfs.format = FT_Jpeg;
|
||||||
}
|
}
|
||||||
@@ -106,8 +117,7 @@ void Thumbnail::_generateThumbnailImage () {
|
|||||||
cfs.format = FT_Png;
|
cfs.format = FT_Png;
|
||||||
}
|
}
|
||||||
else if (ext.lowercase()=="tif" || ext.lowercase()=="tiff") {
|
else if (ext.lowercase()=="tif" || ext.lowercase()=="tiff") {
|
||||||
int deg = infoFromImage (fname);
|
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1);
|
||||||
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, deg);
|
|
||||||
if (tpp)
|
if (tpp)
|
||||||
cfs.format = FT_Tiff;
|
cfs.format = FT_Tiff;
|
||||||
}
|
}
|
||||||
|
@@ -76,8 +76,8 @@ class Thumbnail {
|
|||||||
Glib::ustring getCacheFileName (Glib::ustring subdir);
|
Glib::ustring getCacheFileName (Glib::ustring subdir);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf);
|
Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf, const rtengine::procparams::ProcParams *pparams=NULL);
|
||||||
Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5);
|
Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5, const rtengine::procparams::ProcParams *pparams=NULL);
|
||||||
~Thumbnail ();
|
~Thumbnail ();
|
||||||
|
|
||||||
bool hasProcParams ();
|
bool hasProcParams ();
|
||||||
|
@@ -494,8 +494,6 @@ void ToneCurve::autoExpChanged (double expcomp, int bright, int contr, int black
|
|||||||
nextHlcompr = hlcompr;
|
nextHlcompr = hlcompr;
|
||||||
nextHlcomprthresh = hlcomprthresh;
|
nextHlcomprthresh = hlcomprthresh;
|
||||||
g_idle_add (autoExpChangedUI, this);
|
g_idle_add (autoExpChangedUI, this);
|
||||||
|
|
||||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::autoExpComputed_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToneCurve::enableAll () {
|
void ToneCurve::enableAll () {
|
||||||
@@ -515,6 +513,7 @@ void ToneCurve::enableAll () {
|
|||||||
|
|
||||||
bool ToneCurve::autoExpComputed_ () {
|
bool ToneCurve::autoExpComputed_ () {
|
||||||
|
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
disableListener ();
|
disableListener ();
|
||||||
enableAll ();
|
enableAll ();
|
||||||
expcomp->setValue (nextExpcomp);
|
expcomp->setValue (nextExpcomp);
|
||||||
|
@@ -580,6 +580,7 @@ bool ToolPanelCoordinator::handleShortcutKey (GdkEventKey* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ToolPanelCoordinator::updateVScrollbars (bool hide) {
|
void ToolPanelCoordinator::updateVScrollbars (bool hide) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
Gtk::PolicyType policy = hide ? Gtk::POLICY_NEVER : Gtk::POLICY_AUTOMATIC;
|
Gtk::PolicyType policy = hide ? Gtk::POLICY_NEVER : Gtk::POLICY_AUTOMATIC;
|
||||||
exposurePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy);
|
exposurePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy);
|
||||||
detailsPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy);
|
detailsPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy);
|
||||||
@@ -589,9 +590,10 @@ void ToolPanelCoordinator::updateVScrollbars (bool hide) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ToolPanelCoordinator::updateTabsHeader (bool useIcons) {
|
void ToolPanelCoordinator::updateTabsHeader (bool useIcons) {
|
||||||
TOITypes type = useIcons ? TOI_ICON : TOI_TEXT;
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
|
TOITypes type = useIcons ? TOI_ICON : TOI_TEXT;
|
||||||
|
|
||||||
toiE->switchTo(type);
|
toiE->switchTo(type);
|
||||||
toiD->switchTo(type);
|
toiD->switchTo(type);
|
||||||
toiC->switchTo(type);
|
toiC->switchTo(type);
|
||||||
toiT->switchTo(type);
|
toiT->switchTo(type);
|
||||||
@@ -609,6 +611,7 @@ void ToolPanelCoordinator::updateTabsUsesIcons (bool useIcons) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ToolPanelCoordinator::toolSelected (ToolMode tool) {
|
void ToolPanelCoordinator::toolSelected (ToolMode tool) {
|
||||||
|
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||||
switch (tool) {
|
switch (tool) {
|
||||||
case TMCropSelect:
|
case TMCropSelect:
|
||||||
crop->exp->set_expanded(true);
|
crop->exp->set_expanded(true);
|
||||||
|
Reference in New Issue
Block a user