Commit afe577f0 authored by Gilles Caulier's avatar Gilles Caulier 🗼
Browse files

Apply big patch #101176 from Mario Frank

This one extended the findduplicatesview and fuzzysearchview with an
additional QSpinBox which denotes the maximum similarity. The new QSpinBox
has a minimum value that is the current value of the minimal similarity
threshold. When the minimum threshold is altered, the range of the new
QSpinBox is updated. If the minimum threshold is increased beyond the current
value of the new QSpinBox, the value of the new QSpinBox is increased
automatically. In the fuzzysearchview, altering the maximum similarity also
triggers the reuild of the similar images album. The extension can be highly
valuable if you knowingly want to ignore almost identical images but want to
find images that have a similarity of, let's say 50-60%, due to resizing,
cropping or something similar, without bloating your image pane.

BUGS: 369051
FIXED-IN: 5.4.0
CCMAIL: frank@uni-potsdam.de
parent 171fa0a2
......@@ -264,6 +264,7 @@ void SearchModificationHelper::slotCreateFuzzySearchFromSketch(const QString& pr
SAlbum* SearchModificationHelper::createFuzzySearchFromImage(const QString& proposedName,
const ImageInfo& image,
float threshold,
float maxThreshold,
bool overwriteIfExisting)
{
if (image.isNull())
......@@ -289,6 +290,7 @@ SAlbum* SearchModificationHelper::createFuzzySearchFromImage(const QString& prop
writer.writeField(QLatin1String("similarity"), SearchXml::Like);
writer.writeAttribute(QLatin1String("type"), QLatin1String("imageid"));
writer.writeAttribute(QLatin1String("threshold"), QString::number(threshold));
writer.writeAttribute(QLatin1String("maxthreshold"), QString::number(maxThreshold));
writer.writeAttribute(QLatin1String("sketchtype"), QLatin1String("scanned"));
writer.writeValue(image.id());
writer.finishField();
......
......@@ -90,6 +90,7 @@ public:
SAlbum* createFuzzySearchFromImage(const QString& name,
const ImageInfo& image,
float threshold,
float maxThreshold,
bool overwriteIfExisting = false);
public Q_SLOTS:
......
......@@ -269,9 +269,9 @@ void SearchesJob::run()
return;
}
if (m_jobInfo.threshold() == 0)
if (m_jobInfo.minThreshold() == 0)
{
m_jobInfo.setThreshold(0.4);
m_jobInfo.setMinThreshold(0.4);
}
DuplicatesProgressObserver observer(this);
......@@ -280,7 +280,8 @@ void SearchesJob::run()
HaarIface iface;
iface.rebuildDuplicatesAlbums(m_jobInfo.albumsIds(),
m_jobInfo.tagsIds(),
m_jobInfo.threshold(),
m_jobInfo.minThreshold(),
m_jobInfo.maxThreshold(),
&observer);
}
......
......@@ -197,7 +197,8 @@ SearchesDBJobInfo::SearchesDBJobInfo()
: DBJobInfo()
{
m_duplicates = false;
m_threshold = 0;
m_minThreshold = 0;
m_maxThreshold = 1;
m_searchId = -1;
}
......@@ -221,14 +222,24 @@ int SearchesDBJobInfo::searchId() const
return m_searchId;
}
void SearchesDBJobInfo::setThreshold(double t)
void SearchesDBJobInfo::setMinThreshold(double t)
{
m_threshold = t;
m_minThreshold = t;
}
double SearchesDBJobInfo::threshold() const
double SearchesDBJobInfo::minThreshold() const
{
return m_threshold;
return m_minThreshold;
}
void SearchesDBJobInfo::setMaxThreshold(double t)
{
m_maxThreshold = t;
}
double SearchesDBJobInfo::maxThreshold() const
{
return m_maxThreshold;
}
void SearchesDBJobInfo::setAlbumsIds(const QList<int>& albumsIds)
......
......@@ -150,8 +150,11 @@ public:
void setSearchId(int id);
int searchId() const;
void setThreshold(double t);
double threshold() const;
void setMinThreshold(double t);
double minThreshold() const;
void setMaxThreshold(double t);
double maxThreshold() const;
void setAlbumsIds(const QList<int>& albumsIds);
QList<int> albumsIds() const;
......@@ -163,7 +166,8 @@ public:
bool m_duplicates;
int m_searchId;
double m_threshold;
double m_minThreshold;
double m_maxThreshold;
QList<int> m_albumsIds;
QList<int> m_tagsIds;
};
......
......@@ -424,7 +424,7 @@ QList<qlonglong> HaarIface::bestMatchesForImage(qlonglong imageid, int numberOfR
}
QList<qlonglong> HaarIface::bestMatchesForImageWithThreshold(qlonglong imageid, double requiredPercentage,
SketchType type)
double maximumPercentage, SketchType type)
{
if ( !d->useSignatureCache || (d->signatureCache->isEmpty() && d->useSignatureCache) )
{
......@@ -435,14 +435,14 @@ QList<qlonglong> HaarIface::bestMatchesForImageWithThreshold(qlonglong imageid,
return QList<qlonglong>();
}
return bestMatchesWithThreshold(&sig, requiredPercentage, type);
return bestMatchesWithThreshold(imageid, &sig, requiredPercentage, maximumPercentage, type);
}
else
{
// reference for easier access
SignatureCache& signatureCache = *d->signatureCache;
Haar::SignatureData& sig = signatureCache[imageid];
return bestMatchesWithThreshold(&sig, requiredPercentage, type);
return bestMatchesWithThreshold(imageid, &sig, requiredPercentage, maximumPercentage, type);
}
}
......@@ -526,14 +526,19 @@ QList<qlonglong> HaarIface::bestMatches(Haar::SignatureData* const querySig, int
return bestMatches.values();
}
QList<qlonglong> HaarIface::bestMatchesWithThreshold(Haar::SignatureData* const querySig, double requiredPercentage, SketchType type)
QList<qlonglong> HaarIface::bestMatchesWithThreshold(qlonglong imageid,Haar::SignatureData* const querySig, double requiredPercentage, double maximumPercentage, SketchType type)
{
QMap<qlonglong, double> scores = searchDatabase(querySig, type);
double lowest, highest;
getBestAndWorstPossibleScore(querySig, type, &lowest, &highest);
double range = highest - lowest;
double requiredScore = lowest + range * (1.0 - requiredPercentage);
// The range between the highest (worst) and lowest (best) score
// example: 0.2 and 0.5 -> 0.3
double scoreRange = highest - lowest;
// The lower the requiredPercentage is, the higher will the result be.
// example: 0.7 -> 0.3
double percentageRange = 1.0 - requiredPercentage;
// example: 0.2 + (0.3 * 0.3) = 0.2 + 0.09 = 0.29
double requiredScore = lowest + scoreRange * percentageRange;
QMultiMap<double, qlonglong> bestMatches;
double score, percentage;
......@@ -543,11 +548,14 @@ QList<qlonglong> HaarIface::bestMatchesWithThreshold(Haar::SignatureData* const
{
score = it.value();
id = it.key();
// If the score of the picture is at most the required (maximum) score
if (score <= requiredScore)
{
percentage = 1.0 - (score - lowest) / range;
bestMatches.insert(percentage, id);
percentage = 1.0 - (score - lowest) / scoreRange;
// If the found image is the original one (check by id) or the percentage is below the maximum.
if ((id == imageid) || (percentage <= maximumPercentage)){
bestMatches.insert(percentage, id);
}
}
}
......@@ -747,10 +755,10 @@ void HaarIface::getBestAndWorstPossibleScore(Haar::SignatureData* const sig, Ske
}
void HaarIface::rebuildDuplicatesAlbums(const QList<int>& albums2Scan, const QList<int>& tags2Scan,
double requiredPercentage, HaarProgressObserver* const observer)
double requiredPercentage, double maximumPercentage, HaarProgressObserver* const observer)
{
// Carry out search. This takes long.
QMap< qlonglong, QList<qlonglong> > results = findDuplicatesInAlbumsAndTags(albums2Scan, tags2Scan, requiredPercentage, observer);
QMap< qlonglong, QList<qlonglong> > results = findDuplicatesInAlbumsAndTags(albums2Scan, tags2Scan, requiredPercentage, maximumPercentage, observer);
// Build search XML from the results. Store list of ids of similar images.
QMap<QString, QString> queries;
......@@ -786,6 +794,7 @@ void HaarIface::rebuildDuplicatesAlbums(const QList<int>& albums2Scan, const QLi
QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicatesInAlbums(const QList<int>& albums2Scan,
double requiredPercentage,
double maximumPercentage,
HaarProgressObserver* const observer)
{
QSet<qlonglong> idList;
......@@ -796,12 +805,13 @@ QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicatesInAlbums(const QLis
idList.unite(CoreDbAccess().db()->getItemIDsInAlbum(albumId).toSet());
}
return findDuplicates(idList, requiredPercentage, observer);
return findDuplicates(idList, requiredPercentage, maximumPercentage, observer);
}
QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicatesInAlbumsAndTags(const QList<int>& albums2Scan,
const QList<int>& tags2Scan,
double requiredPercentage,
double maximumPercentage,
HaarProgressObserver* const observer)
{
QSet<qlonglong> idList;
......@@ -818,11 +828,12 @@ QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicatesInAlbumsAndTags(con
idList.unite(CoreDbAccess().db()->getItemIDsInTag(albumId).toSet());
}
return findDuplicates(idList, requiredPercentage, observer);
return findDuplicates(idList, requiredPercentage, maximumPercentage, observer);
}
QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicates(const QSet<qlonglong>& images2Scan,
double requiredPercentage,
double maximumPercentage,
HaarProgressObserver* const observer)
{
QMap< qlonglong, QList<qlonglong> > resultsMap;
......@@ -849,8 +860,8 @@ QMap< qlonglong, QList<qlonglong> > HaarIface::findDuplicates(const QSet<qlonglo
if (!resultsCandidates.contains(*it))
{
// find images with required similarity
bestMatchesList = bestMatchesForImageWithThreshold(*it, requiredPercentage, ScannedSketch);
bestMatchesList = bestMatchesForImageWithThreshold(*it, requiredPercentage, maximumPercentage, ScannedSketch);
if (!bestMatchesList.isEmpty())
{
// the list will usually contain one image: the original. Filter out.
......
......@@ -94,11 +94,11 @@ public:
QList<qlonglong> bestMatchesForSignature(const QString& signature, int numberOfResults=20, SketchType type=ScannedSketch);
/** Searches the database for the best matches for the specified query image.
* All matches with a similarity above a given threshold are returned.
* The threshold is in the range 0..1, with 1 meaning identical signature.
* All matches with a similarity in a given threshold interval are returned.
* The threshold is in the range requiredPercentage..maximumPercentage.
*/
QList<qlonglong> bestMatchesForImageWithThreshold(qlonglong imageid,
double requiredPercentage, SketchType type=ScannedSketch);
double requiredPercentage, double maximumPercentage, SketchType type=ScannedSketch);
/** Calculates the Haar signature, bring it in a form as stored in the DB,
* and encode it to Ascii data. Can be used for bestMatchesForSignature.
......@@ -117,23 +117,24 @@ public:
* The threshold is in the range 0..1, with 1 meaning identical signature.
*/
QMap< qlonglong, QList<qlonglong> > findDuplicates(const QSet<qlonglong>& images2Scan, double requiredPercentage,
HaarProgressObserver* const observer = 0);
double maximumPercentage, HaarProgressObserver* const observer = 0);
/** Calls findDuplicates with all images in the given album ids */
QMap< qlonglong, QList<qlonglong> > findDuplicatesInAlbums(const QList<int>& albums2Scan, double requiredPercentage,
HaarProgressObserver* const observer = 0);
double maximumPercentage, HaarProgressObserver* const observer = 0);
/** Calls findDuplicates with all images in the given album and tag ids */
QMap< qlonglong, QList<qlonglong> > findDuplicatesInAlbumsAndTags(const QList<int>& albums2Scan,
const QList<int>& tags2Scan,
double requiredPercentage,
double maximumPercentage,
HaarProgressObserver* const observer = 0);
/** Rebuilds the special search albums in the database that contain a list of possible candidates
* for duplicate images (one album per group of duplicates)
*/
void rebuildDuplicatesAlbums(const QList<int>& albums2Scan, const QList<int>& tags2Scan,
double requiredPercentage, HaarProgressObserver* const observer = 0);
double requiredPercentage, double maximumPercentage, HaarProgressObserver* const observer = 0);
/** Retrieve the Haar signature from database using image id.
* Return true if item signature exist else false.
......@@ -153,8 +154,8 @@ private:
bool indexImage(qlonglong imageid);
QList<qlonglong> bestMatches(Haar::SignatureData* const data, int numberOfResults, SketchType type);
QList<qlonglong> bestMatchesWithThreshold(Haar::SignatureData* const querySig,
double requiredPercentage, SketchType type);
QList<qlonglong> bestMatchesWithThreshold(qlonglong imageid,Haar::SignatureData* const querySig,
double requiredPercentage, double maximumPercentage, SketchType type);
QMap<qlonglong, double> searchDatabase(Haar::SignatureData* const data, SketchType type);
double calculateScore(Haar::SignatureData& querySig, Haar::SignatureData& targetSig,
......
......@@ -752,9 +752,11 @@ void ImageLister::listHaarSearch(ImageListerReceiver* const receiver, const QStr
QStringRef type = reader.attributes().value(QLatin1String("type"));
QStringRef numResultsString = reader.attributes().value(QLatin1String("numberofresults"));
QStringRef thresholdString = reader.attributes().value(QLatin1String("threshold"));
QStringRef maxThresholdString = reader.attributes().value(QLatin1String("maxthreshold"));
QStringRef sketchTypeString = reader.attributes().value(QLatin1String("sketchtype"));
double threshold = 0.9;
double maxThreshold = 1.0;
int numberOfResults = 20;
HaarIface::SketchType sketchType = HaarIface::ScannedSketch;
......@@ -767,7 +769,12 @@ void ImageLister::listHaarSearch(ImageListerReceiver* const receiver, const QStr
{
threshold = qMax(thresholdString.toString().toDouble(), 0.1);
}
if (!maxThresholdString.isNull())
{
maxThreshold = qMax(maxThresholdString.toString().toDouble(), 0.1);
}
if (sketchTypeString == QLatin1String("handdrawn"))
{
sketchType = HaarIface::HanddrawnSketch;
......@@ -801,7 +808,7 @@ void ImageLister::listHaarSearch(ImageListerReceiver* const receiver, const QStr
iface.setAlbumRootsToSearch(albumRootsToList());
}
list = iface.bestMatchesForImageWithThreshold(id, threshold, sketchType);
list = iface.bestMatchesForImageWithThreshold(id, threshold,maxThreshold, sketchType);
}
listFromIdList(receiver, list);
......
......@@ -62,21 +62,25 @@ public:
Private()
{
includeAlbumsLabel = 0;
listView = 0;
scanDuplicatesBtn = 0;
updateFingerPrtBtn = 0;
progressItem = 0;
similarityLabel = 0;
similarity = 0;
albumSelectors = 0;
includeAlbumsLabel = 0;
listView = 0;
scanDuplicatesBtn = 0;
updateFingerPrtBtn = 0;
progressItem = 0;
similarityLabel = 0;
similarityIntervalLabel = 0;
minSimilarity = 0;
maxSimilarity = 0;
albumSelectors = 0;
}
QLabel* includeAlbumsLabel;
QLabel* similarityLabel;
QLabel* similarityIntervalLabel;
QSpinBox* similarity;
QSpinBox* minSimilarity;
QSpinBox* maxSimilarity;
QPushButton* scanDuplicatesBtn;
QPushButton* updateFingerPrtBtn;
......@@ -113,24 +117,34 @@ FindDuplicatesView::FindDuplicatesView(QWidget* const parent)
// ---------------------------------------------------------------
d->similarity = new QSpinBox();
d->similarity->setRange(0, 100);
d->similarity->setValue(90);
d->similarity->setSingleStep(1);
d->similarity->setSuffix(QLatin1String("%"));
d->minSimilarity = new QSpinBox();
d->minSimilarity->setRange(0, 100);
d->minSimilarity->setValue(90);
d->minSimilarity->setSingleStep(1);
d->minSimilarity->setSuffix(QLatin1String("%"));
d->maxSimilarity = new QSpinBox();
d->maxSimilarity->setRange(90, 100);
d->maxSimilarity->setValue(100);
d->maxSimilarity->setSingleStep(1);
d->maxSimilarity->setSuffix(QLatin1String("%"));
d->similarityLabel = new QLabel(i18n("Similarity:"));
d->similarityLabel->setBuddy(d->similarity);
d->similarityLabel->setBuddy(d->minSimilarity);
d->similarityIntervalLabel = new QLabel("-");
// ---------------------------------------------------------------
QGridLayout* const mainLayout = new QGridLayout();
mainLayout->addWidget(d->listView, 0, 0, 1, -1);
mainLayout->addWidget(d->albumSelectors, 1, 0, 1, -1);
mainLayout->addWidget(d->similarityLabel, 2, 0, 1, 1);
mainLayout->addWidget(d->similarity, 2, 2, 1, 1);
mainLayout->addWidget(d->updateFingerPrtBtn, 3, 0, 1, -1);
mainLayout->addWidget(d->scanDuplicatesBtn, 4, 0, 1, -1);
mainLayout->addWidget(d->listView, 0, 0, 1, -1);
mainLayout->addWidget(d->albumSelectors, 1, 0, 1, -1);
mainLayout->addWidget(d->similarityLabel, 2, 0, 1, 1);
mainLayout->addWidget(d->minSimilarity, 2, 2, 1, 1);
mainLayout->addWidget(d->similarityIntervalLabel,2, 3, 1, 1);
mainLayout->addWidget(d->maxSimilarity, 2, 4, 1, -1);
mainLayout->addWidget(d->updateFingerPrtBtn, 3, 0, 1, -1);
mainLayout->addWidget(d->scanDuplicatesBtn, 4, 0, 1, -1);
mainLayout->setRowStretch(0, 10);
mainLayout->setColumnStretch(1, 10);
mainLayout->setContentsMargins(spacing, spacing, spacing, spacing);
......@@ -165,6 +179,8 @@ FindDuplicatesView::FindDuplicatesView(QWidget* const parent)
connect(AlbumManager::instance(), SIGNAL(signalAlbumsCleared()),
this, SLOT(slotClear()));
connect(d->minSimilarity, SIGNAL(valueChanged(int)),this,SLOT(slotMinimumChanged(int)));
}
FindDuplicatesView::~FindDuplicatesView()
......@@ -281,7 +297,8 @@ void FindDuplicatesView::enableControlWidgets(bool val)
d->updateFingerPrtBtn->setEnabled(val);
d->albumSelectors->setEnabled(val);
d->similarityLabel->setEnabled(val);
d->similarity->setEnabled(val);
d->minSimilarity->setEnabled(val);
d->maxSimilarity->setEnabled(val);
}
void FindDuplicatesView::slotFindDuplicates()
......@@ -290,7 +307,7 @@ void FindDuplicatesView::slotFindDuplicates()
slotClear();
enableControlWidgets(false);
DuplicatesFinder* const finder = new DuplicatesFinder(d->albumSelectors->selectedPAlbums(), d->albumSelectors->selectedTAlbums(), d->similarity->value());
DuplicatesFinder* const finder = new DuplicatesFinder(d->albumSelectors->selectedPAlbums(), d->albumSelectors->selectedTAlbums(), d->minSimilarity->value(), d->maxSimilarity->value());
connect(finder, SIGNAL(signalComplete()),
this, SLOT(slotComplete()));
......@@ -298,6 +315,17 @@ void FindDuplicatesView::slotFindDuplicates()
finder->start();
}
void FindDuplicatesView::slotMinimumChanged(int newValue)
{
// Set the new minimum value of the maximum similarity
d->maxSimilarity->setMinimum(newValue);
// If the new value of the mimimum is now higher than the maximum similarity,
// set the maximum similarity to the new value.
if (newValue > d->maxSimilarity->value()){
d->maxSimilarity->setValue(d->minSimilarity->value());
}
}
void FindDuplicatesView::slotComplete()
{
enableControlWidgets(true);
......
......@@ -65,6 +65,7 @@ private Q_SLOTS:
void slotComplete();
void slotUpdateFingerPrints();
void slotCheckForValidSettings();
void slotMinimumChanged(int);
private:
......
......@@ -106,6 +106,7 @@ public:
penSize(0),
resultsSketch(0),
levelImage(0),
maxLevelImage(0),
imageWidget(0),
timerSketch(0),
timerImage(0),
......@@ -136,6 +137,7 @@ public:
static const QString configPenSketchSaturationEntry;
static const QString configPenSkethValueEntry;
static const QString configSimilarsThresholdEntry;
static const QString configSimilarsMaxThresholdEntry;
bool active;
bool fingerprintsChecked;
......@@ -151,6 +153,7 @@ public:
QSpinBox* penSize;
QSpinBox* resultsSketch;
QSpinBox* levelImage;
QSpinBox* maxLevelImage;
QLabel* imageWidget;
......@@ -197,6 +200,7 @@ const QString FuzzySearchView::Private::configPenSketchHueEntry(QLatin1String("P
const QString FuzzySearchView::Private::configPenSketchSaturationEntry(QLatin1String("Pen Sketch Saturation"));
const QString FuzzySearchView::Private::configPenSkethValueEntry(QLatin1String("Pen Sketch Value"));
const QString FuzzySearchView::Private::configSimilarsThresholdEntry(QLatin1String("Similars Threshold"));
const QString FuzzySearchView::Private::configSimilarsMaxThresholdEntry(QLatin1String("Similars Maximum Threshold"));
// --------------------------------------------------------
......@@ -302,6 +306,18 @@ QWidget* FuzzySearchView::setupFindSimilarPanel() const
"value, as a percentage. "
"This value is used by the algorithm to distinguish two "
"similar images. The default value is 90."));
QLabel* const levelIntervalLabel = new QLabel("-");
d->maxLevelImage = new QSpinBox();
d->maxLevelImage->setSuffix(QLatin1String("%"));
d->maxLevelImage->setRange(90, 100);
d->maxLevelImage->setSingleStep(1);
d->maxLevelImage->setValue(100);
d->maxLevelImage->setWhatsThis(i18n("Select here the approximate maximum similarity threshold "
"value, as a percentage. "
"This value is used by the algorithm to restrict "
"similar images. The default value is 100."));
// ---------------------------------------------------------------
......@@ -327,14 +343,16 @@ QWidget* FuzzySearchView::setupFindSimilarPanel() const
QWidget* const mainWidget = new QWidget();
QGridLayout* const mainLayout = new QGridLayout();
mainLayout->addWidget(imageBox, 0, 0, 1, -1);
mainLayout->addWidget(file, 1, 0, 1, 1);
mainLayout->addWidget(d->labelFile, 1, 1, 1, -1);
mainLayout->addWidget(folder, 2, 0, 1, 1);
mainLayout->addWidget(d->labelFolder, 2, 1, 1, -1);
mainLayout->addWidget(resultsLabel, 3, 0, 1, 1);
mainLayout->addWidget(d->levelImage, 3, 2, 1, -1);
mainLayout->addWidget(saveBox, 4, 0, 1, 3);
mainLayout->addWidget(imageBox, 0, 0, 1, -1);
mainLayout->addWidget(file, 1, 0, 1, 1);
mainLayout->addWidget(d->labelFile, 1, 1, 1, -1);
mainLayout->addWidget(folder, 2, 0, 1, 1);
mainLayout->addWidget(d->labelFolder, 2, 1, 1, -1);
mainLayout->addWidget(resultsLabel, 3, 0, 1, 1);
mainLayout->addWidget(d->levelImage, 3, 2, 1, 1);
mainLayout->addWidget(levelIntervalLabel, 3, 3, 1, 1);
mainLayout->addWidget(d->maxLevelImage, 3, 4, 1, -1);
mainLayout->addWidget(saveBox, 4, 0, 1, 3);
mainLayout->setRowStretch(5, 10);
mainLayout->setColumnStretch(1, 10);
mainLayout->setContentsMargins(spacing, spacing, spacing, spacing);
......@@ -474,8 +492,11 @@ void FuzzySearchView::setupConnections()
this, SLOT(slotDirtySketch()));
connect(d->levelImage, SIGNAL(valueChanged(int)),
this, SLOT(slotLevelImageChanged()));
this, SLOT(slotLevelImageChanged(int)));
connect(d->maxLevelImage, SIGNAL(valueChanged(int)),
this, SLOT(slotMaxLevelImageChanged(int)));
connect(d->resetButton, SIGNAL(clicked()),
this, SLOT(slotClearSketch()));
......@@ -570,6 +591,7 @@ void FuzzySearchView::doLoadState()
d->hsSelector->setSaturation(group.readEntry(entryName(d->configPenSketchSaturationEntry), 128));
d->vSelector->setValue(group.readEntry(entryName(d->configPenSkethValueEntry), 255));
d->levelImage->setValue(group.readEntry(entryName(d->configSimilarsThresholdEntry), 90));
d->maxLevelImage->setValue(group.readEntry(entryName(d->configSimilarsMaxThresholdEntry), 100));
d->hsSelector->updateContents();
QColor col;
......@@ -593,6 +615,7 @@ void FuzzySearchView::doSaveState()
group.writeEntry(entryName(d->configPenSketchSaturationEntry), d->hsSelector->saturation());
group.writeEntry(entryName(d->configPenSkethValueEntry), d->vSelector->value());
group.writeEntry(entryName(d->configSimilarsThresholdEntry), d->levelImage->value());
group.writeEntry(entryName(d->configSimilarsMaxThresholdEntry),d->maxLevelImage->value());
d->searchTreeView->saveState();
group.sync();
}
......@@ -695,6 +718,7 @@ void FuzzySearchView::slotAlbumSelected(Album* album)
QStringRef type = reader.attributes().value(QLatin1String("type"));
QStringRef numResultsString = reader.attributes().value(QLatin1String("numberofresults"));
QStringRef thresholdString = reader.attributes().value(QLatin1String("threshold"));
QStringRef maxThresholdString = reader.attributes().value(QLatin1String("maxthreshold"));
QStringRef sketchTypeString = reader.attributes().value(QLatin1String("sketchtype"));
if (type == QLatin1String("imageid"))
......@@ -876,8 +900,31 @@ void FuzzySearchView::dropEvent(QDropEvent* e)
}
}
void FuzzySearchView::slotLevelImageChanged()
void FuzzySearchView::slotMaxLevelImageChanged(int newValue)
{
if (d->timerImage)
{
d->timerImage->stop();
}
else
{
d->timerImage = new QTimer(this);
connect(d->timerImage, SIGNAL(timeout()),
this, SLOT(slotTimerImageDone()));
d->timerImage->setSingleShot(true);
d->timerImage->setInterval(500);
}
d->timerImage->start();
}