From 5f76c2527decd752c15efef50bf40abddf332931 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Tue, 19 May 2020 14:20:21 +0200 Subject: [PATCH] GUI searching with saved query: restore external indexes from saved query --- src/qtgui/guiutils.h | 3 + src/qtgui/main.cpp | 20 ++- src/qtgui/rclmain_w.cpp | 6 +- src/qtgui/recoll.h | 3 +- src/qtgui/spell_w.cpp | 328 ++++++++++++++++++++-------------------- src/qtgui/ssearch_w.cpp | 34 ++++- src/qtgui/ssearch_w.h | 1 + src/rcldb/rcldb.cpp | 53 ++++--- src/rcldb/rcldb.h | 2 + 9 files changed, 250 insertions(+), 200 deletions(-) diff --git a/src/qtgui/guiutils.h b/src/qtgui/guiutils.h index c721d976..535b20d8 100644 --- a/src/qtgui/guiutils.h +++ b/src/qtgui/guiutils.h @@ -109,6 +109,9 @@ class PrefsPack { // Extra query indexes. This are stored in the history file, not qt prefs vector allExtraDbs; vector activeExtraDbs; + // Temporary value while we run a saved query. Erased right after use. + bool useTmpActiveExtraDbs{false}; + vector tmpActiveExtraDbs; // Advanced search subdir restriction: we don't activate the last value // but just remember previously entered values QStringList asearchSubdirHist; diff --git a/src/qtgui/main.cpp b/src/qtgui/main.cpp index badaf396..25fb4672 100644 --- a/src/qtgui/main.cpp +++ b/src/qtgui/main.cpp @@ -98,16 +98,22 @@ void startManual(const string& helpindex) bool maybeOpenDb(string &reason, bool force, bool *maindberror) { - LOGDEB2("maybeOpenDb: force " << force << "\n"); + LOGDEB1("maybeOpenDb: force " << force << "\n"); - if (force) { + if (force || nullptr == rcldb) { rcldb = std::shared_ptr(new Rcl::Db(theconfig)); } rcldb->rmQueryDb(""); - for (const auto& dbdir : prefs.activeExtraDbs) { - LOGDEB("main: adding [" << dbdir << "]\n"); - rcldb->addQueryDb(dbdir); + auto edbs = &prefs.activeExtraDbs; + if (prefs.useTmpActiveExtraDbs) { + edbs = &prefs.tmpActiveExtraDbs; + } + if (!edbs->empty()) { + rcldb->setExtraQueryDbs(*edbs); } + prefs.useTmpActiveExtraDbs = false; + prefs.tmpActiveExtraDbs.clear(); + Rcl::Db::OpenError error; if (!rcldb->isopen() && !rcldb->open(Rcl::Db::DbRO, &error)) { reason = "Could not open database"; @@ -130,7 +136,7 @@ bool getStemLangs(vector& vlangs) { // Try from db string reason; - if (maybeOpenDb(reason)) { + if (maybeOpenDb(reason, false)) { vlangs = rcldb->getStemLangs(); LOGDEB0("getStemLangs: from index: " << stringsToString(vlangs) <<"\n"); return true; @@ -385,7 +391,7 @@ int main(int argc, char **argv) exit(1); } - maybeOpenDb(reason); + maybeOpenDb(reason, false); if (op_flags & OPT_w) { mainWindow->showMinimized(); diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index a4f635ef..3b1bc37d 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -717,7 +717,7 @@ void RclMain::startSearch(std::shared_ptr sdata, bool issimple) string reason; // If indexing is being performed, we reopen the db at each query. if (!maybeOpenDb(reason, m_idxproc != 0)) { - QMessageBox::critical(0, "Recoll", QString(reason.c_str())); + QMessageBox::critical(0, "Recoll", u8s2qs(reason)); m_queryActive = false; restable->setEnabled(true); return; @@ -952,7 +952,7 @@ void RclMain::showSubDocs(Rcl::Doc doc) { LOGDEB("RclMain::showSubDocs\n"); string reason; - if (!maybeOpenDb(reason)) { + if (!maybeOpenDb(reason, false)) { QMessageBox::critical(0, "Recoll", QString(reason.c_str())); return; } @@ -1010,7 +1010,7 @@ void RclMain::showDocHistory() curPreview = 0; string reason; - if (!maybeOpenDb(reason)) { + if (!maybeOpenDb(reason, false)) { QMessageBox::critical(0, "Recoll", QString(reason.c_str())); return; } diff --git a/src/qtgui/recoll.h b/src/qtgui/recoll.h index 9f2204ba..e26902ed 100644 --- a/src/qtgui/recoll.h +++ b/src/qtgui/recoll.h @@ -29,8 +29,7 @@ // Misc declarations in need of sharing between the UI files // Open the database if needed. We now force a close/open by default -extern bool maybeOpenDb(std::string &reason, bool force = true, - bool *maindberror = 0); +extern bool maybeOpenDb(std::string &reason, bool force, bool *maindberror = 0); /** Retrieve configured stemming languages */ bool getStemLangs(vector& langs); diff --git a/src/qtgui/spell_w.cpp b/src/qtgui/spell_w.cpp index 201cb785..78e0b417 100644 --- a/src/qtgui/spell_w.cpp +++ b/src/qtgui/spell_w.cpp @@ -77,21 +77,21 @@ void SpellW::init() stemLangCMB->clear(); vector langs; if (!getStemLangs(langs)) { - QMessageBox::warning(0, "Recoll", - tr("error retrieving stemming languages")); + QMessageBox::warning(0, "Recoll", + tr("error retrieving stemming languages")); } for (vector::const_iterator it = langs.begin(); - it != langs.end(); it++) { - stemLangCMB->addItem(u8s2qs(*it)); + it != langs.end(); it++) { + stemLangCMB->addItem(u8s2qs(*it)); } (void)new HelpClient(this); HelpClient::installMap((const char *)this->objectName().toUtf8(), - "RCL.SEARCH.GUI.TERMEXPLORER"); + "RCL.SEARCH.GUI.TERMEXPLORER"); // signals and slots connections connect(baseWordLE, SIGNAL(textChanged(const QString&)), - this, SLOT(wordChanged(const QString&))); + this, SLOT(wordChanged(const QString&))); connect(baseWordLE, SIGNAL(returnPressed()), this, SLOT(doExpand())); connect(expandPB, SIGNAL(clicked()), this, SLOT(doExpand())); connect(dismissPB, SIGNAL(clicked()), this, SLOT(close())); @@ -105,7 +105,7 @@ void SpellW::init() #endif resTW->verticalHeader()->setDefaultSectionSize(20); connect(resTW, - SIGNAL(cellDoubleClicked(int, int)), + SIGNAL(cellDoubleClicked(int, int)), this, SLOT(textDoubleClicked(int, int))); resTW->setColumnWidth(0, 200); @@ -120,9 +120,9 @@ void SpellW::init() int SpellW::cmbIdx(comboboxchoice mode) { vector::const_iterator it = - std::find(m_c2t.begin(), m_c2t.end(), mode); + std::find(m_c2t.begin(), m_c2t.end(), mode); if (it == m_c2t.end()) - it = m_c2t.begin(); + it = m_c2t.begin(); return it - m_c2t.begin(); } @@ -133,19 +133,19 @@ void SpellW::doExpand() { int idx = expTypeCMB->currentIndex(); if (idx < 0 || idx >= int(m_c2t.size())) - idx = 0; + idx = 0; comboboxchoice mode = m_c2t[idx]; // Can't clear qt4 table widget: resets column headers too resTW->setRowCount(0); if (baseWordLE->text().isEmpty() && !wordlessMode(mode)) - return; + return; string reason; - if (!maybeOpenDb(reason)) { - QMessageBox::critical(0, "Recoll", QString(reason.c_str())); - LOGDEB("SpellW::doExpand: db error: " << (reason) << "\n" ); - return; + if (!maybeOpenDb(reason, false)) { + QMessageBox::critical(0, "Recoll", QString(reason.c_str())); + LOGDEB("SpellW::doExpand: db error: " << (reason) << "\n" ); + return; } int mt; @@ -156,10 +156,10 @@ void SpellW::doExpand() default: mt = Rcl::Db::ET_WILD; } if (caseSensCB->isChecked()) { - mt |= Rcl::Db::ET_CASESENS; + mt |= Rcl::Db::ET_CASESENS; } if (diacSensCB->isChecked()) { - mt |= Rcl::Db::ET_DIACSENS; + mt |= Rcl::Db::ET_DIACSENS; } Rcl::TermMatchResult res; string expr = string((const char *)baseWordLE->text().toUtf8()); @@ -172,29 +172,29 @@ void SpellW::doExpand() case TYPECMB_REG: case TYPECMB_STEM: { - string l_stemlang = qs2utf8s(stemLangCMB->currentText()); + string l_stemlang = qs2utf8s(stemLangCMB->currentText()); - if (!rcldb->termMatch(mt, l_stemlang, expr, res, maxexpand)) { - LOGERR("SpellW::doExpand:rcldb::termMatch failed\n" ); - return; - } + if (!rcldb->termMatch(mt, l_stemlang, expr, res, maxexpand)) { + LOGERR("SpellW::doExpand:rcldb::termMatch failed\n" ); + return; + } statsLBL->setText(tr("Index: %1 documents, average length %2 terms." - "%3 results") + "%3 results") .arg(dbs.dbdoccount).arg(dbs.dbavgdoclen, 0, 'f', 0) - .arg(res.entries.size())); + .arg(res.entries.size())); } break; case TYPECMB_SPELL: { - LOGDEB("SpellW::doExpand: spelling [" << expr << "]\n" ); - vector suggs; - if (!rcldb->getSpellingSuggestions(expr, suggs)) { - QMessageBox::warning(0, "Recoll", tr("Spell expansion error. ")); - } - for (const auto& it : suggs) { - res.entries.push_back(Rcl::TermMatchEntry(it)); + LOGDEB("SpellW::doExpand: spelling [" << expr << "]\n" ); + vector suggs; + if (!rcldb->getSpellingSuggestions(expr, suggs)) { + QMessageBox::warning(0, "Recoll", tr("Spell expansion error. ")); + } + for (const auto& it : suggs) { + res.entries.push_back(Rcl::TermMatchEntry(it)); } statsLBL->setText(tr("%1 results").arg(res.entries.size())); } @@ -202,14 +202,14 @@ void SpellW::doExpand() case TYPECMB_STATS: { - showStats(); - return; + showStats(); + return; } break; case TYPECMB_FAILED: { - showFailed(); - return; + showFailed(); + return; } break; } @@ -219,35 +219,35 @@ void SpellW::doExpand() } else { int row = 0; - if (maxexpand > 0 && int(res.entries.size()) >= maxexpand) { - resTW->setRowCount(row + 1); - resTW->setSpan(row, 0, 1, 2); - resTW->setItem(row++, 0, - new QTableWidgetItem( - tr("List was truncated alphabetically, " - "some frequent "))); - resTW->setRowCount(row + 1); - resTW->setSpan(row, 0, 1, 2); - resTW->setItem(row++, 0, new QTableWidgetItem( - tr("terms may be missing. " - "Try using a longer root."))); - resTW->setRowCount(row + 1); - resTW->setItem(row++, 0, new QTableWidgetItem("")); - } + if (maxexpand > 0 && int(res.entries.size()) >= maxexpand) { + resTW->setRowCount(row + 1); + resTW->setSpan(row, 0, 1, 2); + resTW->setItem(row++, 0, + new QTableWidgetItem( + tr("List was truncated alphabetically, " + "some frequent "))); + resTW->setRowCount(row + 1); + resTW->setSpan(row, 0, 1, 2); + resTW->setItem(row++, 0, new QTableWidgetItem( + tr("terms may be missing. " + "Try using a longer root."))); + resTW->setRowCount(row + 1); + resTW->setItem(row++, 0, new QTableWidgetItem("")); + } - for (vector::iterator it = res.entries.begin(); - it != res.entries.end(); it++) { - LOGDEB2("SpellW::expand: " << it->wcf << " [" << it->term << "]\n"); - char num[30]; - if (it->wcf) - sprintf(num, "%d / %d", it->docs, it->wcf); - else - num[0] = 0; - resTW->setRowCount(row+1); + for (vector::iterator it = res.entries.begin(); + it != res.entries.end(); it++) { + LOGDEB2("SpellW::expand: " << it->wcf << " [" << it->term << "]\n"); + char num[30]; + if (it->wcf) + sprintf(num, "%d / %d", it->docs, it->wcf); + else + num[0] = 0; + resTW->setRowCount(row+1); resTW->setItem(row, 0, new QTableWidgetItem(u8s2qs(it->term))); resTW->setItem(row++, 1, - new QTableWidgetItem(QString::fromUtf8(num))); - } + new QTableWidgetItem(QString::fromUtf8(num))); + } } } @@ -258,57 +258,57 @@ void SpellW::showStats() Rcl::DbStats res; if (!rcldb->dbStats(res, false)) { - LOGERR("SpellW::doExpand:rcldb::dbStats failed\n" ); - return; + LOGERR("SpellW::doExpand:rcldb::dbStats failed\n" ); + return; } resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Number of documents"))); + new QTableWidgetItem(tr("Number of documents"))); resTW->setItem(row++, 1, new QTableWidgetItem( - QString::number(res.dbdoccount))); + QString::number(res.dbdoccount))); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Average terms per document"))); + new QTableWidgetItem(tr("Average terms per document"))); resTW->setItem(row++, 1, new QTableWidgetItem( - QString::number(res.dbavgdoclen, 'f', 0))); + QString::number(res.dbavgdoclen, 'f', 0))); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Smallest document length (terms)"))); + new QTableWidgetItem(tr("Smallest document length (terms)"))); resTW->setItem(row++, 1, new QTableWidgetItem( - QString::number(res.mindoclen))); + QString::number(res.mindoclen))); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Longest document length (terms)"))); + new QTableWidgetItem(tr("Longest document length (terms)"))); resTW->setItem(row++, 1, new QTableWidgetItem( - QString::number(res.maxdoclen))); + QString::number(res.maxdoclen))); if (!theconfig) - return; + return; DbIxStatus st; readIdxStatus(theconfig, st); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Results from last indexing:"))); + new QTableWidgetItem(tr("Results from last indexing:"))); resTW->setItem(row++, 1, new QTableWidgetItem("")); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr(" Documents created/updated"))); + new QTableWidgetItem(tr(" Documents created/updated"))); resTW->setItem(row++, 1, new QTableWidgetItem(QString::number(st.docsdone))); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr(" Files tested"))); + new QTableWidgetItem(tr(" Files tested"))); resTW->setItem(row++, 1, new QTableWidgetItem(QString::number(st.filesdone))); resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr(" Unindexed files"))); + new QTableWidgetItem(tr(" Unindexed files"))); resTW->setItem(row++, 1, new QTableWidgetItem(QString::number(st.fileerrors))); @@ -316,41 +316,41 @@ void SpellW::showStats() int64_t dbkbytes = fsTreeBytes(theconfig->getDbDir()) / 1024; if (dbkbytes < 0) { - dbkbytes = 0; + dbkbytes = 0; } resTW->setRowCount(row+1); resTW->setItem(row, 0, - new QTableWidgetItem(tr("Database directory size"))); + new QTableWidgetItem(tr("Database directory size"))); resTW->setItem(row++, 1, new QTableWidgetItem( - u8s2qs(displayableBytes(dbkbytes*1024)))); + u8s2qs(displayableBytes(dbkbytes*1024)))); vector allmimetypes = theconfig->getAllMimeTypes(); multimap mtbycnt; for (vector::const_iterator it = allmimetypes.begin(); - it != allmimetypes.end(); it++) { - string reason; - string q = string("mime:") + *it; - Rcl::SearchData *sd = wasaStringToRcl(theconfig, "", q, reason); - std::shared_ptr rq(sd); - Rcl::Query query(rcldb.get()); - if (!query.setQuery(rq)) { - LOGERR("Query setup failed: " << (query.getReason()) << "" ); - return; - } - int cnt = query.getResCnt(); - mtbycnt.insert(pair(cnt,*it)); + it != allmimetypes.end(); it++) { + string reason; + string q = string("mime:") + *it; + Rcl::SearchData *sd = wasaStringToRcl(theconfig, "", q, reason); + std::shared_ptr rq(sd); + Rcl::Query query(rcldb.get()); + if (!query.setQuery(rq)) { + LOGERR("Query setup failed: " << (query.getReason()) << "" ); + return; + } + int cnt = query.getResCnt(); + mtbycnt.insert(pair(cnt,*it)); } resTW->setRowCount(row+1); resTW->setItem(row, 0, new QTableWidgetItem(tr("MIME types:"))); resTW->setItem(row++, 1, new QTableWidgetItem("")); for (multimap::const_reverse_iterator it = mtbycnt.rbegin(); - it != mtbycnt.rend(); it++) { - resTW->setRowCount(row+1); - resTW->setItem(row, 0, new QTableWidgetItem(QString(" ") + + it != mtbycnt.rend(); it++) { + resTW->setRowCount(row+1); + resTW->setItem(row, 0, new QTableWidgetItem(QString(" ") + u8s2qs(it->second))); - resTW->setItem(row++, 1, new QTableWidgetItem( - QString::number(it->first))); + resTW->setItem(row++, 1, new QTableWidgetItem( + QString::number(it->first))); } } @@ -361,23 +361,23 @@ void SpellW::showFailed() Rcl::DbStats res; if (!rcldb->dbStats(res, true)) { - LOGERR("SpellW::doExpand:rcldb::dbStats failed\n" ); - return; + LOGERR("SpellW::doExpand:rcldb::dbStats failed\n" ); + return; } for (auto entry : res.failedurls) { - resTW->setRowCount(row+1); - resTW->setItem(row, 0, new QTableWidgetItem(u8s2qs(entry))); - resTW->setItem(row++, 1, new QTableWidgetItem("")); + resTW->setRowCount(row+1); + resTW->setItem(row, 0, new QTableWidgetItem(u8s2qs(entry))); + resTW->setItem(row++, 1, new QTableWidgetItem("")); } } void SpellW::wordChanged(const QString &text) { if (text.isEmpty()) { - expandPB->setEnabled(false); + expandPB->setEnabled(false); resTW->setRowCount(0); } else { - expandPB->setEnabled(true); + expandPB->setEnabled(true); } } @@ -392,7 +392,7 @@ void SpellW::textDoubleClicked(int row, int) void SpellW::onModeChanged(int idx) { if (idx < 0 || idx > int(m_c2t.size())) - return; + return; comboboxchoice mode = m_c2t[idx]; setModeCommon(mode); } @@ -411,96 +411,96 @@ void SpellW::setModeCommon(comboboxchoice mode) m_prevmode = mode; resTW->setRowCount(0); if (o_index_stripchars) { - caseSensCB->setEnabled(false); - diacSensCB->setEnabled(false); + caseSensCB->setEnabled(false); + diacSensCB->setEnabled(false); } else { - caseSensCB->setEnabled(true); - diacSensCB->setEnabled(true); + caseSensCB->setEnabled(true); + diacSensCB->setEnabled(true); } if (mode == TYPECMB_STEM) { - stemLangCMB->setEnabled(true); - diacSensCB->setChecked(false); - diacSensCB->setEnabled(false); - caseSensCB->setChecked(false); - caseSensCB->setEnabled(false); + stemLangCMB->setEnabled(true); + diacSensCB->setChecked(false); + diacSensCB->setEnabled(false); + caseSensCB->setChecked(false); + caseSensCB->setEnabled(false); } else { - stemLangCMB->setEnabled(false); + stemLangCMB->setEnabled(false); } if (wordlessMode(mode)) { - baseWordLE->setEnabled(false); - QStringList labels(tr("Item")); - labels.push_back(tr("Value")); - resTW->setHorizontalHeaderLabels(labels); - diacSensCB->setEnabled(false); - caseSensCB->setEnabled(false); - doExpand(); + baseWordLE->setEnabled(false); + QStringList labels(tr("Item")); + labels.push_back(tr("Value")); + resTW->setHorizontalHeaderLabels(labels); + diacSensCB->setEnabled(false); + caseSensCB->setEnabled(false); + doExpand(); } else { - baseWordLE->setEnabled(true); - QStringList labels(tr("Term")); - labels.push_back(tr("Doc. / Tot.")); - resTW->setHorizontalHeaderLabels(labels); - prefs.termMatchType = mode; + baseWordLE->setEnabled(true); + QStringList labels(tr("Term")); + labels.push_back(tr("Doc. / Tot.")); + resTW->setHorizontalHeaderLabels(labels); + prefs.termMatchType = mode; } } void SpellW::copy() { - QItemSelectionModel * selection = resTW->selectionModel(); - QModelIndexList indexes = selection->selectedIndexes(); + QItemSelectionModel * selection = resTW->selectionModel(); + QModelIndexList indexes = selection->selectedIndexes(); - if(indexes.size() < 1) - return; + if(indexes.size() < 1) + return; - // QModelIndex::operator < sorts first by row, then by column. - // this is what we need - std::sort(indexes.begin(), indexes.end()); + // QModelIndex::operator < sorts first by row, then by column. + // this is what we need + std::sort(indexes.begin(), indexes.end()); - // You need a pair of indexes to find the row changes - QModelIndex previous = indexes.first(); - indexes.removeFirst(); - QString selected_text; - QModelIndex current; - Q_FOREACH(current, indexes) - { - QVariant data = resTW->model()->data(previous); - QString text = data.toString(); - // At this point `text` contains the text in one cell - selected_text.append(text); - // If you are at the start of the row the row number of the previous index - // isn't the same. Text is followed by a row separator, which is a newline. - if (current.row() != previous.row()) + // You need a pair of indexes to find the row changes + QModelIndex previous = indexes.first(); + indexes.removeFirst(); + QString selected_text; + QModelIndex current; + Q_FOREACH(current, indexes) { - selected_text.append(QLatin1Char('\n')); + QVariant data = resTW->model()->data(previous); + QString text = data.toString(); + // At this point `text` contains the text in one cell + selected_text.append(text); + // If you are at the start of the row the row number of the previous index + // isn't the same. Text is followed by a row separator, which is a newline. + if (current.row() != previous.row()) + { + selected_text.append(QLatin1Char('\n')); + } + // Otherwise it's the same row, so append a column separator, which is a tab. + else + { + selected_text.append(QLatin1Char('\t')); + } + previous = current; } - // Otherwise it's the same row, so append a column separator, which is a tab. - else - { - selected_text.append(QLatin1Char('\t')); - } - previous = current; - } - // add last element - selected_text.append(resTW->model()->data(current).toString()); - selected_text.append(QLatin1Char('\n')); - qApp->clipboard()->setText(selected_text, QClipboard::Selection); - qApp->clipboard()->setText(selected_text, QClipboard::Clipboard); + // add last element + selected_text.append(resTW->model()->data(current).toString()); + selected_text.append(QLatin1Char('\n')); + qApp->clipboard()->setText(selected_text, QClipboard::Selection); + qApp->clipboard()->setText(selected_text, QClipboard::Clipboard); } bool SpellW::eventFilter(QObject *target, QEvent *event) { if (event->type() != QEvent::KeyPress || - (target != resTW && target != resTW->viewport())) - return false; + (target != resTW && target != resTW->viewport())) + return false; QKeyEvent *keyEvent = (QKeyEvent *)event; if(keyEvent->matches(QKeySequence::Copy) ) { - copy(); - return true; + copy(); + return true; } return false; } diff --git a/src/qtgui/ssearch_w.cpp b/src/qtgui/ssearch_w.cpp index 179c5fa3..36c029a8 100644 --- a/src/qtgui/ssearch_w.cpp +++ b/src/qtgui/ssearch_w.cpp @@ -535,6 +535,20 @@ bool SSearch::startSimpleSearch(const string& u8, int maxexp) return true; } +bool SSearch::checkExtIndexes(const std::vector& dbs) +{ + std::string reason; + if (!maybeOpenDb(reason, false)) { + QMessageBox::critical(0, "Recoll", tr("Can't open index") + + u8s2qs(reason)); + return false; + } + if (!rcldb->setExtraQueryDbs(dbs)) { + return false; + } + return true; +} + bool SSearch::fromXML(const SSearchDef& fxml) { string asString; @@ -565,14 +579,20 @@ bool SSearch::fromXML(const SSearchDef& fxml) tr(" differ from current preferences (kept)")); } - cur = set(prefs.activeExtraDbs.begin(), prefs.activeExtraDbs.end()); - stored = set(fxml.extindexes.begin(), fxml.extindexes.end()); - stringsToString(fxml.extindexes, asString); - if (cur != stored) { + + if (!checkExtIndexes(fxml.extindexes)) { + std::string asString; + stringsToString(fxml.extindexes, asString); QMessageBox::warning( - 0, "Recoll", tr("External indexes for stored query: ") + - QString::fromUtf8(asString.c_str()) + - tr(" differ from current preferences (kept)")); + 0, "Recoll", + tr("Could not restore external indexes for stored query:
") + + (rcldb ? u8s2qs(rcldb->getReason()) : tr("???")) + QString("
") + + tr("Using current preferences.")); + string s; + maybeOpenDb(s, true); + } else { + prefs.useTmpActiveExtraDbs = true; + prefs.tmpActiveExtraDbs = fxml.extindexes; } if (prefs.ssearchAutoPhrase && !fxml.autophrase) { diff --git a/src/qtgui/ssearch_w.h b/src/qtgui/ssearch_w.h index 6e8be1bb..afe53e56 100644 --- a/src/qtgui/ssearch_w.h +++ b/src/qtgui/ssearch_w.h @@ -113,6 +113,7 @@ signals: private: int getPartialWord(QString& word); bool startSimpleSearch(const string& q, int maxexp = -1); + bool checkExtIndexes(const std::vector& dbs); RclCompleterModel *m_completermodel{nullptr}; QCompleter *m_completer{nullptr}; diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index 2445a46c..023bb59d 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -1055,23 +1055,6 @@ bool Db::i_close(bool final) return false; } -// Reopen the db with a changed list of additional dbs -bool Db::adjustdbs() -{ - if (m_mode != DbRO) { - LOGERR("Db::adjustdbs: mode not RO\n"); - return false; - } - if (m_ndb && m_ndb->m_isopen) { - if (!close()) - return false; - if (!open(m_mode)) { - return false; - } - } - return true; -} - int Db::docCnt() { int res = -1; @@ -1114,6 +1097,42 @@ int Db::termDocCnt(const string& _term) return res; } +// Reopen the db with a changed list of additional dbs +bool Db::adjustdbs() +{ + if (m_mode != DbRO) { + LOGERR("Db::adjustdbs: mode not RO\n"); + return false; + } + if (m_ndb && m_ndb->m_isopen) { + if (!close()) + return false; + if (!open(m_mode)) { + return false; + } + } + return true; +} + +// Set the extra indexes to the input list. +bool Db::setExtraQueryDbs(const std::vector& dbs) +{ + LOGDEB0("Db::setExtraQueryDbs: ndb " << m_ndb << " iswritable " << + ((m_ndb)?m_ndb->m_iswritable:0) << " dbs [" << + stringsToString(dbs) << "]\n"); + if (!m_ndb) { + return false; + } + if (m_ndb->m_iswritable) { + return false; + } + m_extraDbs.clear(); + for (const auto& dir : dbs) { + m_extraDbs.push_back(path_canon(dir)); + } + return adjustdbs(); +} + bool Db::addQueryDb(const string &_dir) { string dir = _dir; diff --git a/src/rcldb/rcldb.h b/src/rcldb/rcldb.h index 520f516f..5bd199ff 100644 --- a/src/rcldb/rcldb.h +++ b/src/rcldb/rcldb.h @@ -338,6 +338,8 @@ public: bool addQueryDb(const string &dir); /** Remove extra database. if dir == "", remove all. */ bool rmQueryDb(const string &dir); + /** Set the extra indexes to the input list. */ + bool setExtraQueryDbs(const std::vector& dbs); /** Check if document comes from the main index (this is used to decide if we can update the index for it */