Merge with 'dev/newlocallab'...
This commit is contained in:
@@ -16,11 +16,12 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include "filebrowser.h"
|
||||
|
||||
@@ -28,16 +29,17 @@
|
||||
#include "clipboard.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "options.h"
|
||||
#include "paramsedited.h"
|
||||
#include "profilestorecombobox.h"
|
||||
#include "procparamchangers.h"
|
||||
#include "rtimage.h"
|
||||
#include "threadutils.h"
|
||||
#include "thumbnail.h"
|
||||
|
||||
#include "../rtengine/dfmanager.h"
|
||||
#include "../rtengine/ffmanager.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
|
||||
extern Options options;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -89,41 +91,36 @@ ThumbBrowserEntryBase* selectOriginalEntry (ThumbBrowserEntryBase* original, Thu
|
||||
|
||||
void findOriginalEntries (const std::vector<ThumbBrowserEntryBase*>& entries)
|
||||
{
|
||||
typedef std::vector<ThumbBrowserEntryBase*> EntryVector;
|
||||
typedef EntryVector::const_iterator EntryIterator;
|
||||
typedef std::map<Glib::ustring, EntryVector> BasenameMap;
|
||||
typedef BasenameMap::const_iterator BasenameIterator;
|
||||
|
||||
// Sort all entries into buckets by basename without extension
|
||||
BasenameMap byBasename;
|
||||
std::map<Glib::ustring, std::vector<ThumbBrowserEntryBase*>> byBasename;
|
||||
|
||||
for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) {
|
||||
const Glib::ustring basename = Glib::path_get_basename ((*entry)->filename.lowercase());
|
||||
for (const auto entry : entries) {
|
||||
const auto basename = Glib::path_get_basename(entry->filename.lowercase());
|
||||
|
||||
const Glib::ustring::size_type pos = basename.find_last_of ('.');
|
||||
if (pos >= basename.length () - 1) {
|
||||
(*entry)->setOriginal (nullptr);
|
||||
const auto pos = basename.find_last_of('.');
|
||||
if (pos >= basename.length() - 1) {
|
||||
entry->setOriginal(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
const Glib::ustring withoutExtension = basename.substr (0, pos);
|
||||
const auto withoutExtension = basename.substr(0, pos);
|
||||
|
||||
byBasename[withoutExtension].push_back (*entry);
|
||||
byBasename[withoutExtension].push_back(entry);
|
||||
}
|
||||
|
||||
// Find the original image for each bucket
|
||||
for (BasenameIterator bucket = byBasename.begin (); bucket != byBasename.end (); ++bucket) {
|
||||
const EntryVector& entries = bucket->second;
|
||||
for (const auto& bucket : byBasename) {
|
||||
const auto& lentries = bucket.second;
|
||||
ThumbBrowserEntryBase* original = nullptr;
|
||||
|
||||
// Select the most likely original in a first pass...
|
||||
for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) {
|
||||
original = selectOriginalEntry (original, *entry);
|
||||
for (const auto entry : lentries) {
|
||||
original = selectOriginalEntry(original, entry);
|
||||
}
|
||||
|
||||
// ...and link all other images to it in a second pass.
|
||||
for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) {
|
||||
(*entry)->setOriginal (*entry != original ? original : nullptr);
|
||||
for (const auto entry : lentries) {
|
||||
entry->setOriginal(entry != original ? original : nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -486,7 +483,7 @@ FileBrowser::~FileBrowser ()
|
||||
delete[] amiExtProg;
|
||||
}
|
||||
|
||||
void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry)
|
||||
void FileBrowser::rightClicked ()
|
||||
{
|
||||
|
||||
{
|
||||
@@ -622,7 +619,7 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry)
|
||||
|
||||
initEntry(entry);
|
||||
}
|
||||
redraw(false);
|
||||
redraw(entry);
|
||||
}
|
||||
|
||||
FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname)
|
||||
@@ -839,10 +836,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mselected.size(); i++) {
|
||||
rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams();
|
||||
pp.raw.dark_frame = fc.get_filename();
|
||||
pp.raw.df_autoselect = false;
|
||||
mselected[i]->thumbnail->setProcParams(pp, nullptr, FILEBROWSER, false);
|
||||
rtengine::procparams::ProcParams lpp = mselected[i]->thumbnail->getProcParams();
|
||||
lpp.raw.dark_frame = fc.get_filename();
|
||||
lpp.raw.df_autoselect = false;
|
||||
mselected[i]->thumbnail->setProcParams(lpp, nullptr, FILEBROWSER, false);
|
||||
}
|
||||
|
||||
if (bppcl) {
|
||||
@@ -915,10 +912,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mselected.size(); i++) {
|
||||
rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams();
|
||||
pp.raw.ff_file = fc.get_filename();
|
||||
pp.raw.ff_AutoSelect = false;
|
||||
mselected[i]->thumbnail->setProcParams(pp, nullptr, FILEBROWSER, false);
|
||||
rtengine::procparams::ProcParams lpp = mselected[i]->thumbnail->getProcParams();
|
||||
lpp.raw.ff_file = fc.get_filename();
|
||||
lpp.raw.ff_AutoSelect = false;
|
||||
mselected[i]->thumbnail->setProcParams(lpp, nullptr, FILEBROWSER, false);
|
||||
}
|
||||
|
||||
if (bppcl) {
|
||||
@@ -1080,17 +1077,17 @@ void FileBrowser::partPasteProfile ()
|
||||
bppcl->beginBatchPParamsChange(mselected.size());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < mselected.size(); i++) {
|
||||
for (auto entry : mselected) {
|
||||
// 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
|
||||
entry->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file
|
||||
const rtengine::procparams::PartialProfile& cbPartProf = clipboard.getPartialProfile();
|
||||
rtengine::procparams::PartialProfile pastedPartProf(&mselected[i]->thumbnail->getProcParams (), nullptr);
|
||||
rtengine::procparams::PartialProfile pastedPartProf(&entry->thumbnail->getProcParams (), nullptr);
|
||||
|
||||
// pushing the selected values of the clipboard PartialProfile to the temporary PartialProfile
|
||||
partialPasteDlg.applyPaste (pastedPartProf.pparams, pastedPartProf.pedited, cbPartProf.pparams, cbPartProf.pedited);
|
||||
|
||||
// applying the temporary PartialProfile to the thumb's ProcParams
|
||||
mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
||||
entry->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER);
|
||||
pastedPartProf.deleteInstance();
|
||||
}
|
||||
|
||||
@@ -1474,12 +1471,12 @@ void FileBrowser::applyFilter (const BrowserFilter& filter)
|
||||
redraw ();
|
||||
}
|
||||
|
||||
bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry complies filter
|
||||
bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) const // true -> entry complies filter
|
||||
{
|
||||
|
||||
FileBrowserEntry* entry = static_cast<FileBrowserEntry*>(entryb);
|
||||
|
||||
if (filter.showOriginal && entry->getOriginal() != nullptr) {
|
||||
if (filter.showOriginal && entry->getOriginal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1498,44 +1495,22 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry
|
||||
return false;
|
||||
}
|
||||
|
||||
// return false is query is not satisfied
|
||||
if (!filter.queryFileName.empty()) {
|
||||
// return false if query is not satisfied
|
||||
if (!filter.vFilterStrings.empty()) {
|
||||
// check if image's FileName contains queryFileName (case insensitive)
|
||||
// TODO should we provide case-sensitive search option via preferences?
|
||||
Glib::ustring FileName;
|
||||
FileName = Glib::path_get_basename (entry->thumbnail->getFileName());
|
||||
FileName = FileName.uppercase();
|
||||
//printf("FileBrowser::checkFilter FileName = '%s'; find() result= %i \n",FileName.c_str(), FileName.find(filter.queryFileName.uppercase()));
|
||||
|
||||
Glib::ustring decodedQueryFileName;
|
||||
bool MatchEqual;
|
||||
|
||||
// Determine the match mode - check if the first 2 characters are equal to "!="
|
||||
if (filter.queryFileName.find("!=") == 0) {
|
||||
decodedQueryFileName = filter.queryFileName.substr (2, filter.queryFileName.length() - 2);
|
||||
MatchEqual = false;
|
||||
} else {
|
||||
decodedQueryFileName = filter.queryFileName;
|
||||
MatchEqual = true;
|
||||
}
|
||||
|
||||
// Consider that queryFileName consist of comma separated values (FilterString)
|
||||
// Evaluate if ANY of these FilterString are contained in the filename
|
||||
// This will construct OR filter within the filter.queryFileName
|
||||
std::string FileName = Glib::path_get_basename(entry->thumbnail->getFileName());
|
||||
std::transform(FileName.begin(), FileName.end(), FileName.begin(), ::toupper);
|
||||
int iFilenameMatch = 0;
|
||||
std::vector<Glib::ustring> vFilterStrings = Glib::Regex::split_simple(",", decodedQueryFileName.uppercase());
|
||||
|
||||
for(size_t i = 0; i < vFilterStrings.size(); i++) {
|
||||
// ignore empty vFilterStrings. Otherwise filter will always return true if
|
||||
// e.g. filter.queryFileName ends on "," and will stop being a filter
|
||||
if (!vFilterStrings.at(i).empty()) {
|
||||
if (FileName.find(vFilterStrings.at(i)) != Glib::ustring::npos) {
|
||||
iFilenameMatch++;
|
||||
}
|
||||
for (const auto& filterString : filter.vFilterStrings) {
|
||||
if (FileName.find(filterString) != std::string::npos) {
|
||||
++iFilenameMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MatchEqual) {
|
||||
if (filter.matchEqual) {
|
||||
if (iFilenameMatch == 0) { //none of the vFilterStrings found in FileName
|
||||
return false;
|
||||
}
|
||||
@@ -1544,10 +1519,10 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*experimental Regex support, this is unlikely to be useful to photographers*/
|
||||
//bool matchfound=Glib::Regex::match_simple(filter.queryFileName.uppercase(),FileName);
|
||||
//if (!matchfound) return false;
|
||||
if (!filter.exifFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check exif filter
|
||||
@@ -1555,17 +1530,12 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry
|
||||
double tol = 0.01;
|
||||
double tol2 = 1e-8;
|
||||
|
||||
if (!filter.exifFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Glib::ustring camera(cfs->getCamera());
|
||||
|
||||
if (!cfs->exifValid)
|
||||
return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0)
|
||||
if (!cfs->exifValid) {
|
||||
return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->getCamera()) > 0)
|
||||
&& (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0)
|
||||
&& (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0)
|
||||
&& (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0);
|
||||
}
|
||||
|
||||
return
|
||||
(!filter.exifFilter.filterShutter || (rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2))
|
||||
@@ -1573,7 +1543,7 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry
|
||||
&& (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom - tol && cfs->focalLen <= filter.exifFilter.focalTo + tol))
|
||||
&& (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo))
|
||||
&& (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0)
|
||||
&& (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0)
|
||||
&& (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->getCamera()) > 0)
|
||||
&& (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0)
|
||||
&& (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user