forked from organicmaps/organicmaps
Merge pull request #6077 from ygorshenin/implement-deletion-of-samples
[assessment-tool] Impemented deletion of non-found samples.
This commit is contained in:
commit
6e4b1c0be8
14 changed files with 284 additions and 103 deletions
|
@ -31,14 +31,14 @@ search::Sample Context::MakeSample(search::FeatureLoader & loader) const
|
|||
if (!m_initialized)
|
||||
return outSample;
|
||||
|
||||
auto const & foundRelevances = m_foundResultsEdits.GetRelevances();
|
||||
auto const & nonFoundRelevances = m_nonFoundResultsEdits.GetRelevances();
|
||||
auto const & foundEntries = m_foundResultsEdits.GetEntries();
|
||||
auto const & nonFoundEntries = m_nonFoundResultsEdits.GetEntries();
|
||||
|
||||
auto & outResults = outSample.m_results;
|
||||
outResults.clear();
|
||||
|
||||
CHECK_EQUAL(m_goldenMatching.size(), m_sample.m_results.size(), ());
|
||||
CHECK_EQUAL(m_actualMatching.size(), foundRelevances.size(), ());
|
||||
CHECK_EQUAL(m_actualMatching.size(), foundEntries.size(), ());
|
||||
CHECK_EQUAL(m_actualMatching.size(), m_foundResults.GetCount(), ());
|
||||
|
||||
// Iterates over original (loaded from the file with search samples)
|
||||
|
@ -53,8 +53,10 @@ search::Sample Context::MakeSample(search::FeatureLoader & loader) const
|
|||
// assessor. But we want to keep them.
|
||||
if (j == search::Matcher::kInvalidId)
|
||||
{
|
||||
auto const relevance = nonFoundRelevances[k++];
|
||||
if (relevance != search::Sample::Result::Relevance::Irrelevant)
|
||||
auto const & entry = nonFoundEntries[k++];
|
||||
auto const deleted = entry.m_deleted;
|
||||
auto const relevance = entry.m_curr;
|
||||
if (!deleted && relevance != search::Sample::Result::Relevance::Irrelevant)
|
||||
{
|
||||
auto result = m_sample.m_results[i];
|
||||
result.m_relevance = relevance;
|
||||
|
@ -64,11 +66,11 @@ search::Sample Context::MakeSample(search::FeatureLoader & loader) const
|
|||
}
|
||||
|
||||
// No need to keep irrelevant results.
|
||||
if (foundRelevances[j] == search::Sample::Result::Relevance::Irrelevant)
|
||||
if (foundEntries[j].m_curr == search::Sample::Result::Relevance::Irrelevant)
|
||||
continue;
|
||||
|
||||
auto result = m_sample.m_results[i];
|
||||
result.m_relevance = foundRelevances[j];
|
||||
result.m_relevance = foundEntries[j].m_curr;
|
||||
outResults.push_back(move(result));
|
||||
}
|
||||
|
||||
|
@ -83,7 +85,7 @@ search::Sample Context::MakeSample(search::FeatureLoader & loader) const
|
|||
}
|
||||
|
||||
// No need to keep irrelevant results.
|
||||
if (foundRelevances[i] == search::Sample::Result::Relevance::Irrelevant)
|
||||
if (foundEntries[i].m_curr == search::Sample::Result::Relevance::Irrelevant)
|
||||
continue;
|
||||
|
||||
auto const & result = m_foundResults[i];
|
||||
|
@ -93,7 +95,7 @@ search::Sample Context::MakeSample(search::FeatureLoader & loader) const
|
|||
|
||||
FeatureType ft;
|
||||
CHECK(loader.Load(result.GetFeatureID(), ft), ());
|
||||
outResults.push_back(search::Sample::Result::Build(ft, foundRelevances[i]));
|
||||
outResults.push_back(search::Sample::Result::Build(ft, foundEntries[i].m_curr));
|
||||
}
|
||||
|
||||
return outSample;
|
||||
|
@ -103,8 +105,8 @@ void Context::ApplyEdits()
|
|||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
m_foundResultsEdits.ResetRelevances(m_foundResultsEdits.GetRelevances());
|
||||
m_nonFoundResultsEdits.ResetRelevances(m_nonFoundResultsEdits.GetRelevances());
|
||||
m_foundResultsEdits.Apply();
|
||||
m_nonFoundResultsEdits.Apply();
|
||||
}
|
||||
|
||||
// ContextList -------------------------------------------------------------------------------------
|
||||
|
|
|
@ -15,52 +15,82 @@ bool Edits::RelevanceEditor::Set(Relevance relevance)
|
|||
|
||||
Edits::Relevance Edits::RelevanceEditor::Get() const
|
||||
{
|
||||
auto const & relevances = m_parent.GetRelevances();
|
||||
CHECK_LESS(m_index, relevances.size(), ());
|
||||
return relevances[m_index];
|
||||
return m_parent.Get(m_index).m_curr;
|
||||
}
|
||||
|
||||
bool Edits::RelevanceEditor::HasChanges() const
|
||||
{
|
||||
return m_parent.HasChanges(m_index);
|
||||
}
|
||||
bool Edits::RelevanceEditor::HasChanges() const { return m_parent.HasChanges(m_index); }
|
||||
|
||||
// Edits -------------------------------------------------------------------------------------------
|
||||
void Edits::ResetRelevances(std::vector<Relevance> const & relevances)
|
||||
void Edits::Apply()
|
||||
{
|
||||
WithObserver(Update::AllRelevancesUpdate(), [this, &relevances]() {
|
||||
m_origRelevances = relevances;
|
||||
m_currRelevances = relevances;
|
||||
WithObserver(Update::MakeAll(), [this]() {
|
||||
for (auto & entry : m_entries)
|
||||
entry.m_orig = entry.m_curr;
|
||||
m_numEdits = 0;
|
||||
});
|
||||
}
|
||||
|
||||
void Edits::Reset(std::vector<Relevance> const & relevances)
|
||||
{
|
||||
WithObserver(Update::MakeAll(), [this, &relevances]() {
|
||||
m_entries.resize(relevances.size());
|
||||
for (size_t i = 0; i < relevances.size(); ++i)
|
||||
{
|
||||
m_entries[i].m_orig = relevances[i];
|
||||
m_entries[i].m_curr = relevances[i];
|
||||
m_entries[i].m_deleted = false;
|
||||
}
|
||||
m_numEdits = 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool Edits::SetRelevance(size_t index, Relevance relevance)
|
||||
{
|
||||
return WithObserver(Update::SingleRelevanceUpdate(index), [this, index, relevance]() {
|
||||
CHECK_LESS(index, m_currRelevances.size(), ());
|
||||
CHECK_EQUAL(m_currRelevances.size(), m_origRelevances.size(), ());
|
||||
return WithObserver(Update::MakeSingle(index), [this, index, relevance]() {
|
||||
CHECK_LESS(index, m_entries.size(), ());
|
||||
|
||||
if (m_currRelevances[index] != m_origRelevances[index] && relevance == m_origRelevances[index])
|
||||
{
|
||||
auto & entry = m_entries[index];
|
||||
|
||||
if (entry.m_curr != entry.m_orig && relevance == entry.m_orig)
|
||||
--m_numEdits;
|
||||
}
|
||||
else if (m_currRelevances[index] == m_origRelevances[index] &&
|
||||
relevance != m_origRelevances[index])
|
||||
{
|
||||
else if (entry.m_curr == entry.m_orig && relevance != entry.m_orig)
|
||||
++m_numEdits;
|
||||
}
|
||||
|
||||
m_currRelevances[index] = relevance;
|
||||
return m_currRelevances[index] != m_origRelevances[index];
|
||||
entry.m_curr = relevance;
|
||||
return entry.m_curr != entry.m_orig;
|
||||
});
|
||||
}
|
||||
|
||||
void Edits::Delete(size_t index)
|
||||
{
|
||||
return WithObserver(Update::MakeDelete(index), [this, index]() {
|
||||
CHECK_LESS(index, m_entries.size(), ());
|
||||
|
||||
auto & entry = m_entries[index];
|
||||
CHECK(!entry.m_deleted, ());
|
||||
entry.m_deleted = true;
|
||||
++m_numEdits;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<Edits::Relevance> Edits::GetRelevances() const
|
||||
{
|
||||
std::vector<Relevance> relevances(m_entries.size());
|
||||
for (size_t i = 0; i < m_entries.size(); ++i)
|
||||
relevances[i] = m_entries[i].m_curr;
|
||||
return relevances;
|
||||
}
|
||||
|
||||
Edits::Entry const & Edits::Get(size_t index) const
|
||||
{
|
||||
CHECK_LESS(index, m_entries.size(), ());
|
||||
return m_entries[index];
|
||||
}
|
||||
|
||||
void Edits::Clear()
|
||||
{
|
||||
WithObserver(Update::AllRelevancesUpdate(), [this]() {
|
||||
m_origRelevances.clear();
|
||||
m_currRelevances.clear();
|
||||
WithObserver(Update::MakeAll(), [this]() {
|
||||
m_entries.clear();
|
||||
m_numEdits = 0;
|
||||
});
|
||||
}
|
||||
|
@ -69,7 +99,7 @@ bool Edits::HasChanges() const { return m_numEdits != 0; }
|
|||
|
||||
bool Edits::HasChanges(size_t index) const
|
||||
{
|
||||
CHECK_LESS(index, m_currRelevances.size(), ());
|
||||
CHECK_LESS(index, m_origRelevances.size(), ());
|
||||
return m_currRelevances[index] != m_origRelevances[index];
|
||||
CHECK_LESS(index, m_entries.size(), ());
|
||||
auto const & entry = m_entries[index];
|
||||
return entry.m_curr != entry.m_orig;
|
||||
}
|
||||
|
|
|
@ -13,32 +13,42 @@
|
|||
class Edits
|
||||
{
|
||||
public:
|
||||
using Relevance = search::Sample::Result::Relevance;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Entry() = default;
|
||||
|
||||
Relevance m_curr = Relevance::Irrelevant;
|
||||
Relevance m_orig = Relevance::Irrelevant;
|
||||
bool m_deleted = false;
|
||||
};
|
||||
|
||||
struct Update
|
||||
{
|
||||
static auto constexpr kInvalidIndex = std::numeric_limits<size_t>::max();
|
||||
|
||||
enum class Type
|
||||
{
|
||||
SingleRelevance,
|
||||
AllRelevances
|
||||
Single,
|
||||
All,
|
||||
Delete
|
||||
};
|
||||
|
||||
static Update AllRelevancesUpdate() { return Update{}; }
|
||||
Update() = default;
|
||||
Update(Type type, size_t index): m_type(type), m_index(index) {}
|
||||
|
||||
static Update SingleRelevanceUpdate(size_t index)
|
||||
{
|
||||
Update result;
|
||||
result.m_index = index;
|
||||
result.m_type = Type::SingleRelevance;
|
||||
return result;
|
||||
}
|
||||
static Update MakeAll() { return Update{}; }
|
||||
|
||||
static Update MakeSingle(size_t index) { return Update{Type::Single, index}; }
|
||||
|
||||
static Update MakeDelete(size_t index) { return Update{Type::Delete, index}; }
|
||||
|
||||
Type m_type = Type::All;
|
||||
size_t m_index = kInvalidIndex;
|
||||
Type m_type = Type::AllRelevances;
|
||||
};
|
||||
|
||||
using OnUpdate = std::function<void(Update const & update)>;
|
||||
using Relevance = search::Sample::Result::Relevance;
|
||||
|
||||
class RelevanceEditor
|
||||
{
|
||||
|
@ -58,13 +68,21 @@ public:
|
|||
|
||||
explicit Edits(OnUpdate onUpdate) : m_onUpdate(onUpdate) {}
|
||||
|
||||
void ResetRelevances(std::vector<Relevance> const & relevances);
|
||||
void Apply();
|
||||
void Reset(std::vector<Relevance> const & relevances);
|
||||
|
||||
// Sets relevance at |index| to |relevance|. Returns true iff
|
||||
// |relevance| differs from the original one.
|
||||
bool SetRelevance(size_t index, Relevance relevance);
|
||||
|
||||
std::vector<Relevance> const & GetRelevances() const { return m_currRelevances; }
|
||||
// Marks entry at |index| as deleted.
|
||||
void Delete(size_t index);
|
||||
|
||||
std::vector<Entry> const & GetEntries() const { return m_entries; }
|
||||
std::vector<Relevance> GetRelevances() const;
|
||||
|
||||
Entry const & Get(size_t index) const;
|
||||
|
||||
|
||||
void Clear();
|
||||
bool HasChanges() const;
|
||||
|
@ -81,8 +99,7 @@ private:
|
|||
return fn();
|
||||
}
|
||||
|
||||
std::vector<Relevance> m_origRelevances;
|
||||
std::vector<Relevance> m_currRelevances;
|
||||
std::vector<Entry> m_entries;
|
||||
|
||||
size_t m_numEdits = 0;
|
||||
|
||||
|
|
|
@ -232,6 +232,14 @@ void MainModel::OnUpdate(View::ResultType type, size_t sampleIndex, Edits::Updat
|
|||
m_view->OnResultChanged(sampleIndex, type, update);
|
||||
m_view->OnSampleChanged(sampleIndex, context.HasChanges());
|
||||
m_view->OnSamplesChanged(m_contexts.HasChanges());
|
||||
|
||||
if (update.m_type == Edits::Update::Type::Delete)
|
||||
{
|
||||
CHECK(context.m_initialized, ());
|
||||
|
||||
CHECK_EQUAL(type, View::ResultType::NonFound, ());
|
||||
ShowMarks(context);
|
||||
}
|
||||
}
|
||||
|
||||
void MainModel::OnResults(uint64_t timestamp, size_t sampleIndex, search::Results const & results,
|
||||
|
@ -256,7 +264,7 @@ void MainModel::OnResults(uint64_t timestamp, size_t sampleIndex, search::Result
|
|||
|
||||
if (!context.m_initialized)
|
||||
{
|
||||
context.m_foundResultsEdits.ResetRelevances(relevances);
|
||||
context.m_foundResultsEdits.Reset(relevances);
|
||||
context.m_goldenMatching = goldenMatching;
|
||||
context.m_actualMatching = actualMatching;
|
||||
|
||||
|
@ -273,20 +281,21 @@ void MainModel::OnResults(uint64_t timestamp, size_t sampleIndex, search::Result
|
|||
nonFound.push_back(context.m_sample.m_results[i]);
|
||||
relevances.push_back(nonFound.back().m_relevance);
|
||||
}
|
||||
context.m_nonFoundResultsEdits.ResetRelevances(relevances);
|
||||
context.m_nonFoundResultsEdits.Reset(relevances);
|
||||
}
|
||||
|
||||
context.m_initialized = true;
|
||||
}
|
||||
|
||||
m_view->ShowNonFoundResults(context.m_nonFoundResults);
|
||||
m_view->ShowNonFoundResults(context.m_nonFoundResults,
|
||||
context.m_nonFoundResultsEdits.GetEntries());
|
||||
ShowMarks(context);
|
||||
m_view->OnResultChanged(sampleIndex, View::ResultType::Found,
|
||||
Edits::Update::AllRelevancesUpdate());
|
||||
Edits::Update::MakeAll());
|
||||
m_view->OnResultChanged(sampleIndex, View::ResultType::NonFound,
|
||||
Edits::Update::AllRelevancesUpdate());
|
||||
Edits::Update::MakeAll());
|
||||
m_view->OnSampleChanged(sampleIndex, context.HasChanges());
|
||||
m_view->EnableSampleEditing(sampleIndex, context.m_foundResultsEdits,
|
||||
context.m_nonFoundResultsEdits);
|
||||
m_view->SetEdits(sampleIndex, context.m_foundResultsEdits, context.m_nonFoundResultsEdits);
|
||||
m_view->OnSearchCompleted();
|
||||
}
|
||||
|
||||
|
@ -296,3 +305,11 @@ void MainModel::ResetSearch()
|
|||
if (auto handle = m_queryHandle.lock())
|
||||
handle->Cancel();
|
||||
}
|
||||
|
||||
void MainModel::ShowMarks(Context const & context)
|
||||
{
|
||||
m_view->ClearSearchResultMarks();
|
||||
m_view->ShowFoundResultsMarks(context.m_foundResults.begin(), context.m_foundResults.end());
|
||||
m_view->ShowNonFoundResultsMarks(context.m_nonFoundResults,
|
||||
context.m_nonFoundResultsEdits.GetEntries());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ private:
|
|||
std::vector<size_t> const & actualMatching);
|
||||
|
||||
void ResetSearch();
|
||||
void ShowMarks(Context const & context);
|
||||
|
||||
Framework & m_framework;
|
||||
Index const & m_index;
|
||||
|
|
|
@ -72,8 +72,8 @@ void MainView::ShowSample(size_t sampleIndex, search::Sample const & sample, boo
|
|||
m_sampleView->SetContents(sample, positionAvailable);
|
||||
m_sampleView->show();
|
||||
|
||||
OnResultChanged(sampleIndex, ResultType::Found, Edits::Update::AllRelevancesUpdate());
|
||||
OnResultChanged(sampleIndex, ResultType::NonFound, Edits::Update::AllRelevancesUpdate());
|
||||
OnResultChanged(sampleIndex, ResultType::Found, Edits::Update::MakeAll());
|
||||
OnResultChanged(sampleIndex, ResultType::NonFound, Edits::Update::MakeAll());
|
||||
OnSampleChanged(sampleIndex, hasEdits);
|
||||
}
|
||||
|
||||
|
@ -82,11 +82,27 @@ void MainView::ShowFoundResults(search::Results::ConstIter begin, search::Result
|
|||
m_sampleView->ShowFoundResults(begin, end);
|
||||
}
|
||||
|
||||
void MainView::ShowNonFoundResults(std::vector<search::Sample::Result> const & results)
|
||||
void MainView::ShowNonFoundResults(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries)
|
||||
{
|
||||
m_sampleView->ShowNonFoundResults(results);
|
||||
m_sampleView->ShowNonFoundResults(results, entries);
|
||||
}
|
||||
|
||||
void MainView::ShowFoundResultsMarks(search::Results::ConstIter begin,
|
||||
search::Results::ConstIter end)
|
||||
|
||||
{
|
||||
m_sampleView->ShowFoundResultsMarks(begin, end);
|
||||
}
|
||||
|
||||
void MainView::ShowNonFoundResultsMarks(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries)
|
||||
{
|
||||
m_sampleView->ShowNonFoundResultsMarks(results, entries);
|
||||
}
|
||||
|
||||
void MainView::ClearSearchResultMarks() { m_sampleView->ClearSearchResultMarks(); }
|
||||
|
||||
void MainView::MoveViewportToResult(search::Result const & result)
|
||||
{
|
||||
m_framework.SelectSearchResult(result, false /* animation */);
|
||||
|
@ -132,11 +148,10 @@ void MainView::OnSamplesChanged(bool hasEdits)
|
|||
m_saveAs->setEnabled(hasEdits);
|
||||
}
|
||||
|
||||
void MainView::EnableSampleEditing(size_t sampleIndex, Edits & foundResultsEdits,
|
||||
Edits & nonFoundResultsEdits)
|
||||
void MainView::SetEdits(size_t sampleIndex, Edits & foundResultsEdits, Edits & nonFoundResultsEdits)
|
||||
{
|
||||
CHECK(m_samplesView->IsSelected(sampleIndex), ());
|
||||
m_sampleView->EnableEditing(foundResultsEdits, nonFoundResultsEdits);
|
||||
m_sampleView->SetEdits(foundResultsEdits, nonFoundResultsEdits);
|
||||
}
|
||||
|
||||
void MainView::ShowError(std::string const & msg)
|
||||
|
|
|
@ -32,16 +32,24 @@ public:
|
|||
void OnSearchCompleted() override;
|
||||
void ShowSample(size_t sampleIndex, search::Sample const & sample, bool positionAvailable,
|
||||
bool hasEdits) override;
|
||||
|
||||
void ShowFoundResults(search::Results::ConstIter begin, search::Results::ConstIter end) override;
|
||||
void ShowNonFoundResults(std::vector<search::Sample::Result> const & results) override;
|
||||
void ShowNonFoundResults(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries) override;
|
||||
|
||||
void ShowFoundResultsMarks(search::Results::ConstIter begin,
|
||||
search::Results::ConstIter end) override;
|
||||
void ShowNonFoundResultsMarks(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries) override;
|
||||
void ClearSearchResultMarks() override;
|
||||
|
||||
void MoveViewportToResult(search::Result const & result) override;
|
||||
void MoveViewportToResult(search::Sample::Result const & result) override;
|
||||
void MoveViewportToRect(m2::RectD const & rect) override;
|
||||
|
||||
void OnResultChanged(size_t sampleIndex, ResultType type, Edits::Update const & update) override;
|
||||
void EnableSampleEditing(size_t sampleIndex, Edits & foundResultsEdits,
|
||||
Edits & nonFoundResultsEdits) override;
|
||||
void SetEdits(size_t sampleIndex, Edits & foundResultsEdits,
|
||||
Edits & nonFoundResultsEdits) override;
|
||||
void OnSampleChanged(size_t sampleIndex, bool hasEdits) override;
|
||||
void OnSamplesChanged(bool hasEdits) override;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ ResultView::ResultView(search::Sample::Result const & result, QWidget & parent)
|
|||
{
|
||||
}
|
||||
|
||||
void ResultView::EnableEditing(Edits::RelevanceEditor && editor)
|
||||
void ResultView::SetEditor(Edits::RelevanceEditor && editor)
|
||||
{
|
||||
m_editor = my::make_unique<Edits::RelevanceEditor>(std::move(editor));
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
ResultView(search::Result const & result, QWidget & parent);
|
||||
ResultView(search::Sample::Result const & result, QWidget & parent);
|
||||
|
||||
void EnableEditing(Edits::RelevanceEditor && editor);
|
||||
void SetEditor(Edits::RelevanceEditor && editor);
|
||||
|
||||
void Update();
|
||||
|
||||
|
|
|
@ -21,12 +21,12 @@ ResultsView::ResultsView(QWidget & parent) : QListWidget(&parent) { setAlternati
|
|||
|
||||
void ResultsView::Add(search::Result const & result)
|
||||
{
|
||||
AddImpl(result);
|
||||
AddImpl(result, false /* hidden */);
|
||||
}
|
||||
|
||||
void ResultsView::Add(search::Sample::Result const & result)
|
||||
void ResultsView::Add(search::Sample::Result const & result, Edits::Entry const & entry)
|
||||
{
|
||||
AddImpl(result);
|
||||
AddImpl(result, entry.m_deleted /* hidden */);
|
||||
}
|
||||
|
||||
ResultView & ResultsView::Get(size_t i)
|
||||
|
@ -45,15 +45,26 @@ void ResultsView::Update(Edits::Update const & update)
|
|||
{
|
||||
switch (update.m_type)
|
||||
{
|
||||
case Edits::Update::Type::SingleRelevance:
|
||||
case Edits::Update::Type::Single:
|
||||
{
|
||||
CHECK_LESS(update.m_index, m_results.size(), ());
|
||||
m_results[update.m_index]->Update();
|
||||
break;
|
||||
case Edits::Update::Type::AllRelevances:
|
||||
}
|
||||
case Edits::Update::Type::All:
|
||||
{
|
||||
for (auto * result : m_results)
|
||||
result->Update();
|
||||
break;
|
||||
}
|
||||
case Edits::Update::Type::Delete:
|
||||
{
|
||||
auto const index = update.m_index;
|
||||
CHECK_LESS(index, Size(), ());
|
||||
item(static_cast<int>(index))->setHidden(true);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void ResultsView::Clear()
|
||||
|
@ -63,9 +74,10 @@ void ResultsView::Clear()
|
|||
}
|
||||
|
||||
template <typename Result>
|
||||
void ResultsView::AddImpl(Result const & result)
|
||||
void ResultsView::AddImpl(Result const & result, bool hidden)
|
||||
{
|
||||
auto * item = new QListWidgetItem(this /* parent */);
|
||||
item->setHidden(hidden);
|
||||
addItem(item);
|
||||
|
||||
auto * view = new ResultView(result, *this /* parent */);
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
explicit ResultsView(QWidget & parent);
|
||||
|
||||
void Add(search::Result const & result);
|
||||
void Add(search::Sample::Result const & result);
|
||||
void Add(search::Sample::Result const & result, Edits::Entry const & entry);
|
||||
|
||||
ResultView & Get(size_t i);
|
||||
ResultView const & Get(size_t i) const;
|
||||
|
@ -38,7 +38,7 @@ signals:
|
|||
|
||||
private:
|
||||
template <typename Result>
|
||||
void AddImpl(Result const & result);
|
||||
void AddImpl(Result const & result, bool hidden);
|
||||
|
||||
std::vector<ResultView *> m_results;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
|
@ -125,6 +126,22 @@ SampleView::SampleView(QWidget * parent, Framework & framework)
|
|||
layout->addWidget(new QLabel(tr("Non found results")));
|
||||
|
||||
m_nonFoundResults = new ResultsView(*this /* parent */);
|
||||
m_nonFoundResults->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_nonFoundResults, &ResultsView::customContextMenuRequested, [&](QPoint pos) {
|
||||
pos = m_nonFoundResults->mapToGlobal(pos);
|
||||
|
||||
auto const items = m_nonFoundResults->selectedItems();
|
||||
for (auto const * item : items)
|
||||
{
|
||||
int const row = m_nonFoundResults->row(item);
|
||||
|
||||
QMenu menu;
|
||||
auto const * action = menu.addAction("Remove result");
|
||||
connect(action, &QAction::triggered, [this, row]() { OnRemoveNonFoundResult(row); });
|
||||
|
||||
menu.exec(pos);
|
||||
}
|
||||
});
|
||||
layout->addWidget(m_nonFoundResults);
|
||||
}
|
||||
|
||||
|
@ -165,41 +182,73 @@ void SampleView::ShowFoundResults(search::Results::ConstIter begin, search::Resu
|
|||
{
|
||||
for (auto it = begin; it != end; ++it)
|
||||
m_foundResults->Add(*it /* result */);
|
||||
m_framework.FillSearchResultsMarks(begin, end);
|
||||
}
|
||||
|
||||
void SampleView::ShowNonFoundResults(std::vector<search::Sample::Result> const & results)
|
||||
void SampleView::ShowNonFoundResults(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries)
|
||||
{
|
||||
CHECK_EQUAL(results.size(), entries.size(), ());
|
||||
|
||||
auto & bookmarkManager = m_framework.GetBookmarkManager();
|
||||
UserMarkControllerGuard guard(bookmarkManager, UserMarkType::SEARCH_MARK);
|
||||
guard.m_controller.SetIsVisible(true);
|
||||
guard.m_controller.SetIsDrawable(true);
|
||||
|
||||
for (auto const & result : results)
|
||||
bool allDeleted = true;
|
||||
for (size_t i = 0; i < results.size(); ++i)
|
||||
{
|
||||
m_nonFoundResults->Add(result);
|
||||
m_nonFoundResults->Add(results[i], entries[i]);
|
||||
if (!entries[i].m_deleted)
|
||||
allDeleted = false;
|
||||
}
|
||||
if (!allDeleted)
|
||||
m_nonFoundResultsBox->show();
|
||||
}
|
||||
|
||||
void SampleView::ShowFoundResultsMarks(search::Results::ConstIter begin, search::Results::ConstIter end)
|
||||
{
|
||||
m_framework.FillSearchResultsMarks(begin, end);
|
||||
}
|
||||
|
||||
void SampleView::ShowNonFoundResultsMarks(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries)
|
||||
|
||||
{
|
||||
CHECK_EQUAL(results.size(), entries.size(), ());
|
||||
|
||||
auto & bookmarkManager = m_framework.GetBookmarkManager();
|
||||
UserMarkControllerGuard guard(bookmarkManager, UserMarkType::SEARCH_MARK);
|
||||
guard.m_controller.SetIsVisible(true);
|
||||
guard.m_controller.SetIsDrawable(true);
|
||||
|
||||
for (size_t i = 0; i < results.size(); ++i)
|
||||
{
|
||||
auto const & result = results[i];
|
||||
auto const & entry = entries[i];
|
||||
if (entry.m_deleted)
|
||||
continue;
|
||||
|
||||
SearchMarkPoint * mark =
|
||||
static_cast<SearchMarkPoint *>(guard.m_controller.CreateUserMark(result.m_pos));
|
||||
mark->SetCustomSymbol("non-found-search-result");
|
||||
}
|
||||
|
||||
if (!results.empty())
|
||||
m_nonFoundResultsBox->show();
|
||||
}
|
||||
|
||||
void SampleView::ClearSearchResultMarks() { m_framework.ClearSearchResultsMarks(); }
|
||||
|
||||
void SampleView::ClearAllResults()
|
||||
{
|
||||
m_foundResults->Clear();
|
||||
m_nonFoundResults->Clear();
|
||||
m_nonFoundResultsBox->hide();
|
||||
m_framework.ClearSearchResultsMarks();
|
||||
ClearSearchResultMarks();
|
||||
}
|
||||
|
||||
void SampleView::EnableEditing(Edits & resultsEdits, Edits & nonFoundResultsEdits)
|
||||
void SampleView::SetEdits(Edits & resultsEdits, Edits & nonFoundResultsEdits)
|
||||
{
|
||||
EnableEditing(*m_foundResults, resultsEdits);
|
||||
EnableEditing(*m_nonFoundResults, nonFoundResultsEdits);
|
||||
SetEdits(*m_foundResults, resultsEdits);
|
||||
SetEdits(*m_nonFoundResults, nonFoundResultsEdits);
|
||||
m_nonFoundResultsEdits = &nonFoundResultsEdits;
|
||||
}
|
||||
|
||||
void SampleView::Clear()
|
||||
|
@ -224,10 +273,12 @@ void SampleView::OnLocationChanged(Qt::DockWidgetArea area)
|
|||
layout()->setContentsMargins(m_defaultMargins);
|
||||
}
|
||||
|
||||
void SampleView::EnableEditing(ResultsView & results, Edits & edits)
|
||||
void SampleView::SetEdits(ResultsView & results, Edits & edits)
|
||||
{
|
||||
size_t const numRelevances = edits.GetRelevances().size();
|
||||
CHECK_EQUAL(results.Size(), numRelevances, ());
|
||||
for (size_t i = 0; i < numRelevances; ++i)
|
||||
results.Get(i).EnableEditing(Edits::RelevanceEditor(edits, i));
|
||||
results.Get(i).SetEditor(Edits::RelevanceEditor(edits, i));
|
||||
}
|
||||
|
||||
void SampleView::OnRemoveNonFoundResult(int row) { m_nonFoundResultsEdits->Delete(row); }
|
||||
|
|
|
@ -26,10 +26,17 @@ public:
|
|||
void SetContents(search::Sample const & sample, bool positionAvailable);
|
||||
void OnSearchStarted();
|
||||
void OnSearchCompleted();
|
||||
void ShowFoundResults(search::Results::ConstIter begin, search::Results::ConstIter end);
|
||||
void ShowNonFoundResults(std::vector<search::Sample::Result> const & results);
|
||||
|
||||
void EnableEditing(Edits & resultsEdits, Edits & nonFoundResultsEdits);
|
||||
void ShowFoundResults(search::Results::ConstIter begin, search::Results::ConstIter end);
|
||||
void ShowNonFoundResults(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries);
|
||||
|
||||
void ShowFoundResultsMarks(search::Results::ConstIter begin, search::Results::ConstIter end);
|
||||
void ShowNonFoundResultsMarks(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries);
|
||||
void ClearSearchResultMarks();
|
||||
|
||||
void SetEdits(Edits & resultsEdits, Edits & nonFoundResultsEdits);
|
||||
|
||||
void Clear();
|
||||
|
||||
|
@ -44,7 +51,8 @@ signals:
|
|||
|
||||
private:
|
||||
void ClearAllResults();
|
||||
void EnableEditing(ResultsView & results, Edits & edits);
|
||||
void SetEdits(ResultsView & results, Edits & edits);
|
||||
void OnRemoveNonFoundResult(int row);
|
||||
|
||||
Framework & m_framework;
|
||||
|
||||
|
@ -58,12 +66,15 @@ private:
|
|||
|
||||
QPushButton * m_showViewport = nullptr;
|
||||
QPushButton * m_showPosition = nullptr;
|
||||
|
||||
ResultsView * m_foundResults = nullptr;
|
||||
QWidget * m_foundResultsBox = nullptr;
|
||||
|
||||
ResultsView * m_nonFoundResults = nullptr;
|
||||
QWidget * m_nonFoundResultsBox = nullptr;
|
||||
|
||||
Edits * m_nonFoundResultsEdits = nullptr;
|
||||
|
||||
QMargins m_rightAreaMargins;
|
||||
QMargins m_defaultMargins;
|
||||
};
|
||||
|
|
|
@ -32,9 +32,17 @@ public:
|
|||
virtual void OnSearchCompleted() = 0;
|
||||
virtual void ShowSample(size_t index, search::Sample const & sample, bool positionAvailable,
|
||||
bool hasEdits) = 0;
|
||||
|
||||
virtual void ShowFoundResults(search::Results::ConstIter begin,
|
||||
search::Results::ConstIter end) = 0;
|
||||
virtual void ShowNonFoundResults(std::vector<search::Sample::Result> const & results) = 0;
|
||||
virtual void ShowNonFoundResults(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries) = 0;
|
||||
|
||||
virtual void ShowFoundResultsMarks(search::Results::ConstIter begin,
|
||||
search::Results::ConstIter end) = 0;
|
||||
virtual void ShowNonFoundResultsMarks(std::vector<search::Sample::Result> const & results,
|
||||
std::vector<Edits::Entry> const & entries) = 0;
|
||||
virtual void ClearSearchResultMarks() = 0;
|
||||
|
||||
virtual void MoveViewportToResult(search::Result const & result) = 0;
|
||||
virtual void MoveViewportToResult(search::Sample::Result const & result) = 0;
|
||||
|
@ -42,8 +50,7 @@ public:
|
|||
|
||||
virtual void OnResultChanged(size_t sampleIndex, ResultType type,
|
||||
Edits::Update const & update) = 0;
|
||||
virtual void EnableSampleEditing(size_t index, Edits & foundResultsEdits,
|
||||
Edits & nonFoundResultsEdits) = 0;
|
||||
virtual void SetEdits(size_t index, Edits & foundResultsEdits, Edits & nonFoundResultsEdits) = 0;
|
||||
virtual void OnSampleChanged(size_t sampleIndex, bool hasEdits) = 0;
|
||||
virtual void OnSamplesChanged(bool hasEdits) = 0;
|
||||
|
||||
|
@ -54,3 +61,13 @@ public:
|
|||
protected:
|
||||
Model * m_model = nullptr;
|
||||
};
|
||||
|
||||
inline std::string DebugPrint(View::ResultType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case View::ResultType::Found: return "Found";
|
||||
case View::ResultType::NonFound: return "NonFound";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue