GUI: implemented sidebar for filtering on directory location

This commit is contained in:
Jean-Francois Dockes 2022-02-26 12:12:36 +01:00
parent 4ca4bf21db
commit 064018ea69
17 changed files with 416 additions and 126 deletions

View File

@ -410,6 +410,8 @@ qtgui/fragbuts.h \
qtgui/guiutils.cpp \
qtgui/guiutils.h \
qtgui/i18n/*.qm qtgui/i18n/*.ts \
qtgui/idxmodel.cpp \
qtgui/idxmodel.h \
qtgui/idxsched.h \
qtgui/idxsched.ui \
qtgui/images/asearch.png \
@ -478,6 +480,7 @@ qtgui/rclm_idx.cpp \
qtgui/rclm_menus.cpp \
qtgui/rclm_preview.cpp \
qtgui/rclm_saveload.cpp \
qtgui/rclm_sidefilters.cpp \
qtgui/rclm_view.cpp \
qtgui/rclm_wins.cpp \
qtgui/rclmain.ui \

View File

@ -211,6 +211,7 @@ void ConfIndexW::acceptChanges()
delete m_conf;
m_conf = 0;
m_rclconf->updateMainConfig();
emit idxConfigPossiblyChanged();
}
void ConfIndexW::initPanels()

View File

@ -50,6 +50,9 @@ public slots:
void showPrefs(bool modal);
void acceptChanges();
QWidget *getDialog() {return m_w;}
signals:
void idxConfigPossiblyChanged();
private:
void initPanels();

View File

@ -108,11 +108,10 @@ void rwSettings(bool writing)
SETTING_RW(prefs.pvheight, "/Recoll/geometry/pvheight", Int, 0);
SETTING_RW(prefs.ssearchTypSav, "/Recoll/prefs/ssearchTypSav", Bool, 0);
SETTING_RW(prefs.ssearchTyp, "/Recoll/prefs/simpleSearchTyp", Int, 3);
SETTING_RW(prefs.startWithAdvSearchOpen,
"/Recoll/prefs/startWithAdvSearchOpen", Bool, false);
SETTING_RW(prefs.startWithAdvSearchOpen, "/Recoll/prefs/startWithAdvSearchOpen", Bool, false);
SETTING_RW(prefs.previewHtml, "/Recoll/prefs/previewHtml", Bool, true);
SETTING_RW(prefs.previewActiveLinks,
"/Recoll/prefs/previewActiveLinks", Bool, false);
SETTING_RW(prefs.previewActiveLinks, "/Recoll/prefs/previewActiveLinks", Bool, false);
SETTING_RW(prefs.idxFilterTreeDepth, "/Recoll/prefs/ssearch/idxfiltertreedepth", Int, 2);
QString advSearchClauses;
const int maxclauselistsize = 20;
@ -149,24 +148,18 @@ void rwSettings(bool writing)
}
}
SETTING_RW(prefs.ssearchNoComplete,
"/Recoll/prefs/ssearch/noComplete", Bool, false);
SETTING_RW(prefs.ssearchStartOnComplete,
"/Recoll/prefs/ssearch/startOnComplete", Bool, true);
SETTING_RW(prefs.ssearchNoComplete, "/Recoll/prefs/ssearch/noComplete", Bool, false);
SETTING_RW(prefs.ssearchStartOnComplete, "/Recoll/prefs/ssearch/startOnComplete", Bool, true);
SETTING_RW(prefs.filterCtlStyle, "/Recoll/prefs/filterCtlStyle", Int, 0);
SETTING_RW(prefs.ssearchAutoPhrase,
"/Recoll/prefs/ssearchAutoPhrase", Bool, true);
SETTING_RW(prefs.ssearchAutoPhraseThreshPC,
SETTING_RW(prefs.ssearchAutoPhrase, "/Recoll/prefs/ssearchAutoPhrase", Bool, true);
SETTING_RW(prefs.ssearchAutoPhraseThreshPC,
"/Recoll/prefs/ssearchAutoPhraseThreshPC", Double, 2.0);
SETTING_RW(prefs.respagesize, "/Recoll/prefs/reslist/pagelen", Int, 8);
SETTING_RW(prefs.historysize, "/Recoll/prefs/historysize", Int, -1);
SETTING_RW(prefs.collapseDuplicates,
"/Recoll/prefs/reslist/collapseDuplicates", Bool, false);
SETTING_RW(prefs.showResultsAsTable,
"/Recoll/prefs/showResultsAsTable", Bool, false);
SETTING_RW(prefs.collapseDuplicates, "/Recoll/prefs/reslist/collapseDuplicates", Bool, false);
SETTING_RW(prefs.showResultsAsTable, "/Recoll/prefs/showResultsAsTable", Bool, false);
SETTING_RW(prefs.maxhltextkbs, "/Recoll/prefs/preview/maxhltextkbs", Int,
3000);
SETTING_RW(prefs.maxhltextkbs, "/Recoll/prefs/preview/maxhltextkbs", Int, 3000);
// Compat: if maxhltextkbs is not set but old maxhltextmbs is set use it
if (!writing && !settings.contains("/Recoll/prefs/preview/maxhltextkbs") &&
settings.contains("/Recoll/prefs/preview/maxhltextmbs")) {
@ -174,14 +167,12 @@ void rwSettings(bool writing)
"/Recoll/prefs/preview/maxhltextmbs").toInt() * 1024;
}
SETTING_RW(prefs.previewPlainPre,
"/Recoll/prefs/preview/plainPre", Int, PrefsPack::PP_PREWRAP);
SETTING_RW(prefs.previewPlainPre, "/Recoll/prefs/preview/plainPre", Int, PrefsPack::PP_PREWRAP);
// History: used to be able to only set a bare color name. Can now
// set any CSS style. Hack on ':' presence to keep compat with old
// values
SETTING_RW(prefs.qtermstyle, "/Recoll/prefs/qtermcolor", String,
"color: blue");
SETTING_RW(prefs.qtermstyle, "/Recoll/prefs/qtermcolor", String, "color: blue");
if (!writing && prefs.qtermstyle == "")
prefs.qtermstyle = "color: blue";
{ // histo compatibility hack
@ -225,23 +216,17 @@ void rwSettings(bool writing)
prefs.creslistformat = qs2utf8s(prefs.reslistformat);
}
SETTING_RW(prefs.reslistheadertext, "/Recoll/prefs/reslist/headertext",
String, "");
SETTING_RW(prefs.reslistheadertext, "/Recoll/prefs/reslist/headertext", String, "");
SETTING_RW(prefs.darkMode, "/Recoll/prefs/darkMode", Bool, 0);
SETTING_RW(prefs.qssFile, "/Recoll/prefs/stylesheet", String, "");
SETTING_RW(prefs.snipCssFile, "/Recoll/prefs/snippets/cssfile", String, "");
SETTING_RW(prefs.queryStemLang, "/Recoll/prefs/query/stemLang", String,
"english");
SETTING_RW(prefs.useDesktopOpen, "/Recoll/prefs/useDesktopOpen",
Bool, true);
SETTING_RW(prefs.queryStemLang, "/Recoll/prefs/query/stemLang", String, "english");
SETTING_RW(prefs.useDesktopOpen, "/Recoll/prefs/useDesktopOpen", Bool, true);
SETTING_RW(prefs.keepSort,
"/Recoll/prefs/keepSort", Bool, false);
SETTING_RW(prefs.keepSort, "/Recoll/prefs/keepSort", Bool, false);
SETTING_RW(prefs.sortField, "/Recoll/prefs/sortField", String, "");
SETTING_RW(prefs.sortActive,
"/Recoll/prefs/sortActive", Bool, false);
SETTING_RW(prefs.sortDesc,
"/Recoll/prefs/query/sortDesc", Bool, 0);
SETTING_RW(prefs.sortActive, "/Recoll/prefs/sortActive", Bool, false);
SETTING_RW(prefs.sortDesc, "/Recoll/prefs/query/sortDesc", Bool, 0);
if (!writing) {
// Handle transition from older prefs which did not store sortColumn
// (Active always meant sort by date).
@ -249,29 +234,22 @@ void rwSettings(bool writing)
prefs.sortField = "mtime";
}
SETTING_RW(prefs.queryBuildAbstract,
"/Recoll/prefs/query/buildAbstract", Bool, true);
SETTING_RW(prefs.queryReplaceAbstract,
"/Recoll/prefs/query/replaceAbstract", Bool, false);
SETTING_RW(prefs.syntAbsLen, "/Recoll/prefs/query/syntAbsLen",
Int, 250);
SETTING_RW(prefs.syntAbsCtx, "/Recoll/prefs/query/syntAbsCtx",
Int, 4);
SETTING_RW(prefs.queryBuildAbstract, "/Recoll/prefs/query/buildAbstract", Bool, true);
SETTING_RW(prefs.queryReplaceAbstract, "/Recoll/prefs/query/replaceAbstract", Bool, false);
SETTING_RW(prefs.syntAbsLen, "/Recoll/prefs/query/syntAbsLen", Int, 250);
SETTING_RW(prefs.syntAbsCtx, "/Recoll/prefs/query/syntAbsCtx", Int, 4);
// Abstract snippet separator
SETTING_RW(prefs.abssep, "/Recoll/prefs/reslist/abssep", String,"…");
if (!writing && prefs.abssep == "")
prefs.abssep = "…";
SETTING_RW(prefs.snipwMaxLength, "/Recoll/prefs/snipwin/maxlen", Int, 1000);
SETTING_RW(prefs.snipwSortByPage,"/Recoll/prefs/snipwin/bypage", Bool,false);
SETTING_RW(prefs.alwaysSnippets, "/Recoll/prefs/reslist/alwaysSnippets",
Bool,false);
SETTING_RW(prefs.alwaysSnippets, "/Recoll/prefs/reslist/alwaysSnippets", Bool,false);
SETTING_RW(prefs.autoSuffs, "/Recoll/prefs/query/autoSuffs", String, "");
SETTING_RW(prefs.autoSuffsEnable,
"/Recoll/prefs/query/autoSuffsEnable", Bool, false);
SETTING_RW(prefs.autoSuffsEnable, "/Recoll/prefs/query/autoSuffsEnable", Bool, false);
SETTING_RW(prefs.synFileEnable,
"/Recoll/prefs/query/synFileEnable", Bool, false);
SETTING_RW(prefs.synFileEnable, "/Recoll/prefs/query/synFileEnable", Bool, false);
SETTING_RW(prefs.synFile, "/Recoll/prefs/query/synfile", String, "");
SETTING_RW(prefs.termMatchType, "/Recoll/prefs/query/termMatchType",
@ -284,20 +262,17 @@ void rwSettings(bool writing)
// Ssearch combobox history list
if (writing) {
settings.setValue("/Recoll/prefs/query/ssearchHistory",
prefs.ssearchHistory);
settings.setValue("/Recoll/prefs/query/ssearchHistory",prefs.ssearchHistory);
} else {
prefs.ssearchHistory =
settings.value("/Recoll/prefs/query/ssearchHistory").toStringList();
prefs.ssearchHistory = settings.value("/Recoll/prefs/query/ssearchHistory").toStringList();
}
// Ignored file types (advanced search)
if (writing) {
settings.setValue("/Recoll/prefs/query/asearchIgnFilTyps",
prefs.asearchIgnFilTyps);
settings.setValue("/Recoll/prefs/query/asearchIgnFilTyps", prefs.asearchIgnFilTyps);
} else {
prefs.asearchIgnFilTyps = settings.value(
"/Recoll/prefs/query/asearchIgnFilTyps").toStringList();
prefs.asearchIgnFilTyps =
settings.value("/Recoll/prefs/query/asearchIgnFilTyps").toStringList();
}
SETTING_RW(prefs.fileTypesByCats, "/Recoll/prefs/query/asearchFilTypByCat", Bool, false);

View File

@ -45,6 +45,7 @@ public:
// toolbar+combobox or as a button group under simple search
enum FilterCtlStyle {FCS_BT, FCS_CMB, FCS_MN};
int filterCtlStyle;
int idxFilterTreeDepth{2};
int respagesize{8};
int historysize{0};
int maxhltextkbs;

109
src/qtgui/idxmodel.cpp Normal file
View File

@ -0,0 +1,109 @@
#include <string>
#include <iostream>
#include <stack>
#include <QStandardItemModel>
#include "recoll.h"
#include "rclconfig.h"
#include "fstreewalk.h"
#include "idxmodel.h"
class WalkerCB : public FsTreeWalkerCB {
public:
WalkerCB(RclConfig *config, const std::string& topstring, FsTreeWalker& walker,
IdxTreeModel *model, const QModelIndex& index)
: m_config(config), m_topstring(topstring), m_walker(walker), m_model(model)
{
m_indexes.push(index);
m_rows.push(0);
}
virtual FsTreeWalker::Status processone(
const std::string& path, const struct PathStat *, FsTreeWalker::CbFlag flg) override;
RclConfig *m_config;
std::string m_topstring;
FsTreeWalker& m_walker;
IdxTreeModel *m_model;
std::stack<QModelIndex> m_indexes;
std::stack<int> m_rows;
};
FsTreeWalker::Status WalkerCB::processone(
const std::string& path, const struct PathStat *, FsTreeWalker::CbFlag flg)
{
if (flg == FsTreeWalker::FtwDirEnter || flg == FsTreeWalker::FtwDirReturn) {
m_config->setKeyDir(path);
// Set up filter/skipped patterns for this subtree.
m_walker.setOnlyNames(m_config->getOnlyNames());
m_walker.setSkippedNames(m_config->getSkippedNames());
}
if (flg == FsTreeWalker::FtwDirReturn) {
m_indexes.pop();
m_rows.pop();
return FsTreeWalker::FtwOk;
}
if (flg == FsTreeWalker::FtwDirEnter) {
if (m_model->columnCount(m_indexes.top()) == 0) {
if (!m_model->insertColumn(0, m_indexes.top()))
return FsTreeWalker::FtwError;
}
if (!m_model->insertRow(m_rows.top(), m_indexes.top()))
return FsTreeWalker::FtwError;
const QModelIndex child = m_model->index(m_rows.top(), 0, m_indexes.top());
// Setting the short path in DisplayRole and the real one in EditRole does not seem to work,
// the treeview shows the EditRole?? So use the ToolTip to store the full value
std::string disp;
if (m_topstring.empty()) {
disp = path_getsimple(path);
} else {
disp = m_topstring;
m_topstring.clear();
}
m_model->setData(child, QVariant(path2qs(disp)), Qt::DisplayRole);
m_model->setData(child, QVariant(path2qs(path)), Qt::ToolTipRole);
++m_rows.top();
m_indexes.push(child);
m_rows.push(0);
}
return FsTreeWalker::FtwOk;
}
static void populateDir(RclConfig *config, const std::string& topstr, IdxTreeModel *model,
const QModelIndex& index, const std::string& path, int depth)
{
FsTreeWalker walker;
walker.setSkippedPaths(config->getSkippedPaths());
// walker.setOpts(walker.getOpts() | FsTreeWalker::FtwSkipDotFiles);
walker.setMaxDepth(depth);
WalkerCB cb(config, topstr, walker, model, index);
walker.walk(path, cb);
}
void IdxTreeModel::populate()
{
QModelIndex index = this->index(0,0);
auto topdirs = m_config->getTopdirs();
auto prefix = commonprefix(topdirs);
if (this->columnCount(index) == 0) {
if (!this->insertColumn(0, index))
return;
}
int row = 0;
for (const auto& topdir : topdirs) {
const QModelIndex child = this->index(row, 0, index);
std::string topdisp;
if (prefix.size() > 1) {
topdisp = topdir.substr(prefix.size());
} else {
topdisp = topdir;
}
populateDir(m_config, topdisp, this, child, topdir, m_depth);
++row;
}
sort(0, Qt::AscendingOrder);
}

42
src/qtgui/idxmodel.h Normal file
View File

@ -0,0 +1,42 @@
/* Copyright (C) 2022 J.F.Dockes
*
* License: GPL 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _IDXMODEL_H
#define _IDXMODEL_H
#include <QStandardItemModel>
class RclConfig;
class IdxTreeModel : public QStandardItemModel {
Q_OBJECT;
public:
IdxTreeModel(RclConfig *config, int depth, QWidget *parent = nullptr)
: QStandardItemModel(0, 0, (QObject*)parent), m_config(config), m_depth(depth) {
}
~IdxTreeModel() {}
void populate();
int getDepth() {return m_depth;}
private:
RclConfig *m_config{nullptr};
int m_depth;
};
#endif // _IDXMODEL_H

View File

@ -0,0 +1,54 @@
/* Copyright (C) 2022 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "autoconfig.h"
#include <vector>
#include <string>
#include "log.h"
#include "rclmain_w.h"
#include "idxmodel.h"
#include "guiutils.h"
void RclMain::populateFilters()
{
m_idxtreemodel = new IdxTreeModel(theconfig, prefs.idxFilterTreeDepth, idxTreeView);
m_idxtreemodel->populate();
m_idxtreemodel->setHeaderData(0, Qt::Horizontal, QVariant(tr("Filter directories")));
idxTreeView->setModel(m_idxtreemodel);
idxTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
idxTreeView->setSelectionMode(QAbstractItemView::MultiSelection);
}
void RclMain::clearDirFilter()
{
idxTreeView->clearSelection();
}
std::vector<std::string> RclMain::idxTreeGetDirs()
{
std::vector<std::string> out;
auto selmodel = idxTreeView->selectionModel();
if (nullptr != selmodel) {
auto selected = selmodel->selectedIndexes();
std::string clause;
for (int i = 0; i < selected.size(); i++) {
out.push_back(qs2path(selected[i].data(Qt::ToolTipRole).toString()));
}
}
return out;
}

View File

@ -190,6 +190,7 @@ void RclMain::showIndexConfig(bool modal)
if (created) {
connect(new QShortcut(quitKeySeq, indexConfig->getDialog()),
SIGNAL (activated()), this, SLOT (fileExit()));
connect(indexConfig, SIGNAL(idxConfigPossiblyChanged()), this, SLOT(populateFilters()));
}
}

View File

@ -20,41 +20,36 @@
<string>Recoll</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="SSearch" name="sSearch" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="ResList" name="reslist" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="SSearch" name="sSearch" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="sideFiltersSPLT">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeView" name="idxTreeView"/>
<widget class="ResList" name="reslist" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -43,6 +43,7 @@
#include <QToolBar>
#include <QSettings>
#include <QToolTip>
#include <QStandardItemModel>
#include "recoll.h"
#include "log.h"
@ -71,10 +72,12 @@
#include "readfile.h"
#include "moc_rclmain_w.cpp"
#include "scbase.h"
#include "idxmodel.h"
QString g_stringAllStem, g_stringNoStem;
static const char *settingskey_toolarea="/Recoll/geometry/toolArea";
static const char *settingskey_resarea="/Recoll/geometry/resArea";
static const char *settingskey_sidefilterssize = "/Recoll/geometry/sideFilters";
static Qt::ToolBarArea int2area(int in)
{
@ -277,6 +280,18 @@ void RclMain::init()
QSettings settings;
restoreGeometry(settings.value("/Recoll/geometry/maingeom").toByteArray());
QVariant saved = settings.value(settingskey_sidefilterssize);
if (saved != QVariant()) {
sideFiltersSPLT->restoreState(saved.toByteArray());
} else {
QList<int> sizes;
sizes << 200 << 600;
sideFiltersSPLT->setSizes(sizes);
}
populateFilters();
connect(idxTreeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(setFiltSpec()));
enableTrayIcon(prefs.showTrayIcon);
fileRebuildIndexAction->setEnabled(false);
@ -692,6 +707,7 @@ void RclMain::fileExit()
settings.setValue(settingskey_resarea, toolBarArea(m_resTB));
}
restable->saveColState();
settings.setValue(settingskey_sidefilterssize, sideFiltersSPLT->saveState());
if (prefs.ssearchTypSav) {
prefs.ssearchTyp = sSearch->searchTypCMB->currentIndex();
@ -769,13 +785,13 @@ class QueryThread : public QThread {
public:
QueryThread(std::shared_ptr<DocSequence> source)
: m_source(source)
{
}
{
}
~QueryThread() { }
virtual void run()
{
cnt = m_source->getResCnt();
}
{
cnt = m_source->getResCnt();
}
int cnt;
};
@ -1134,6 +1150,9 @@ void RclMain::setUIPrefs()
if (!uiprefs)
return;
LOGDEB("Recollmain::setUIPrefs\n");
if (nullptr != m_idxtreemodel && m_idxtreemodel->getDepth() != prefs.idxFilterTreeDepth) {
populateFilters();
}
emit uiPrefsChanged();
enbSynAction->setDisabled(prefs.synFile.isEmpty());
enbSynAction->setChecked(prefs.synFileEnable);
@ -1215,12 +1234,26 @@ void RclMain::setFiltSpec()
if (fragbuts) {
vector<string> frags;
fragbuts->getfrags(frags);
for (vector<string>::const_iterator it = frags.begin();
it != frags.end(); it++) {
m_filtspec.orCrit(DocSeqFiltSpec::DSFS_QLANG, *it);
for (const auto& frag : frags) {
m_filtspec.orCrit(DocSeqFiltSpec::DSFS_QLANG, frag);
}
}
auto treedirs = idxTreeGetDirs();
bool first{true};
const std::string prefix{"dir:"};
std::string clause;
for (const auto& dir : treedirs) {
if (first) {
first = false;
} else {
clause += " OR ";
}
clause += prefix + makeCString(dir);
}
LOGDEB0("Sidefilter dir clause: [" << clause << "]\n");
m_filtspec.orCrit(DocSeqFiltSpec::DSFS_QLANG, clause);
if (m_source)
m_source->setFiltSpec(m_filtspec);
initiateQuery();

View File

@ -51,6 +51,7 @@ class RclTrayIcon;
class QShortcut;
class QActionGroup;
class ActSearchW;
class IdxTreeModel;
#include "ui_rclmain.h"
@ -106,8 +107,7 @@ public slots:
virtual void bumpIndexing();
virtual void rebuildIndex();
virtual void specialIndex();
virtual void startSearch(std::shared_ptr<Rcl::SearchData> sdata,
bool issimple);
virtual void startSearch(std::shared_ptr<Rcl::SearchData> sdata, bool issimple);
virtual void previewClosed(Preview *w);
virtual void showAdvSearchDialog();
virtual void showSpellDialog();
@ -144,6 +144,7 @@ public slots:
virtual void startNativeViewer(Rcl::Doc, int pagenum = -1, QString term = QString());
virtual void openWith(Rcl::Doc, string);
virtual void saveDocToFile(Rcl::Doc);
virtual void populateFilters();
virtual void previewNextInTab(Preview *, int sid, int docnum);
virtual void previewPrevInTab(Preview *, int sid, int docnum);
virtual void previewExposed(Preview *, int sid, int docnum);
@ -171,9 +172,11 @@ public slots:
virtual void onSetDescription(QString);
virtual void onNewShortcuts();
virtual void toggleTable();
virtual void clearDirFilter();
virtual void hideToolTip();
virtual void zoomIn();
virtual void zoomOut();
virtual void setFiltSpec();
private slots:
virtual bool updateIdxStatus();
@ -230,6 +233,7 @@ private:
QShortcut *m_clearsearchsc{0};
QShortcut *m_toggletablesc{0};
QShortcut *m_actionssearchsc{0};
QShortcut *m_cleardirfiltersc{0};
QFileSystemWatcher m_watcher;
vector<ExecCmd*> m_viewers;
ExecCmd *m_idxproc{0}; // Indexing process
@ -257,7 +261,8 @@ private:
RclTrayIcon *m_trayicon{0};
// We sometimes take the indexer lock (e.g.: when editing the webcache)
Pidfile *m_pidfile{0};
IdxTreeModel *m_idxtreemodel{nullptr};
// Menu for the button version of the top menu.
QMenu *buttonTopMenu;
// Entries/submenus for the top menu.
@ -288,8 +293,8 @@ private:
virtual void updateIdxForDocs(vector<Rcl::Doc>&);
virtual void initiateQuery();
virtual bool containerUpToDate(Rcl::Doc& doc);
virtual void setFiltSpec();
virtual bool checkIdxPaths();
virtual std::vector<std::string> idxTreeGetDirs();
};
#endif // RCLMAIN_W_H

View File

@ -35,6 +35,7 @@ HEADERS += \
crontool.h \
firstidx.h \
fragbuts.h \
idxmodel.h \
idxsched.h \
preview_load.h \
preview_plaintorich.h \
@ -68,6 +69,7 @@ SOURCES += \
crontool.cpp \
fragbuts.cpp \
guiutils.cpp \
idxmodel.cpp \
main.cpp \
multisave.cpp \
preview_load.cpp \
@ -79,6 +81,7 @@ SOURCES += \
rclm_menus.cpp \
rclm_preview.cpp \
rclm_saveload.cpp \
rclm_sidefilters.cpp \
rclm_view.cpp \
rclm_wins.cpp \
rclmain_w.cpp \

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>731</width>
<height>652</height>
<height>684</height>
</rect>
</property>
<property name="windowTitle">
@ -137,6 +137,52 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" stretch="0,0,2">
<item>
<widget class="QLabel" name="textLabel20">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Depth of side filter directory tree</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="idxTreeDepthSB">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_20">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line2">
<property name="orientation">
@ -1531,12 +1577,12 @@ May be slow for big documents.</string>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="anchorTamilHackCB">
<property name="toolTip">
<string>The bug causes a strange circle characters to be displayed inside highlighted Tamil words. The workaround inserts an additional space character which appears to fix the problem.</string>
</property>
<property name="text">
<string>Work around Tamil QTBUG-78923 by inserting space before anchor text</string>
</property>
<property name="toolTip">
<string>The bug causes a strange circle characters to be displayed inside highlighted Tamil words. The workaround inserts an additional space character which appears to fix the problem.</string>
</property>
</widget>
</item>
<item>

View File

@ -79,28 +79,19 @@ void UIPrefsDialog::init()
connect(synFilePB, SIGNAL(clicked()),this, SLOT(showSynFileDialog()));
connect(resetSnipCssPB, SIGNAL(clicked()), this, SLOT(resetSnipCss()));
connect(idxLV, SIGNAL(itemSelectionChanged()),
this, SLOT(extradDbSelectChanged()));
connect(ptransPB, SIGNAL(clicked()),
this, SLOT(extraDbEditPtrans()));
connect(addExtraDbPB, SIGNAL(clicked()),
this, SLOT(addExtraDbPB_clicked()));
connect(delExtraDbPB, SIGNAL(clicked()),
this, SLOT(delExtraDbPB_clicked()));
connect(togExtraDbPB, SIGNAL(clicked()),
this, SLOT(togExtraDbPB_clicked()));
connect(actAllExtraDbPB, SIGNAL(clicked()),
this, SLOT(actAllExtraDbPB_clicked()));
connect(unacAllExtraDbPB, SIGNAL(clicked()),
this, SLOT(unacAllExtraDbPB_clicked()));
connect(idxLV, SIGNAL(itemSelectionChanged()), this, SLOT(extradDbSelectChanged()));
connect(ptransPB, SIGNAL(clicked()), this, SLOT(extraDbEditPtrans()));
connect(addExtraDbPB, SIGNAL(clicked()), this, SLOT(addExtraDbPB_clicked()));
connect(delExtraDbPB, SIGNAL(clicked()), this, SLOT(delExtraDbPB_clicked()));
connect(togExtraDbPB, SIGNAL(clicked()), this, SLOT(togExtraDbPB_clicked()));
connect(actAllExtraDbPB, SIGNAL(clicked()), this, SLOT(actAllExtraDbPB_clicked()));
connect(unacAllExtraDbPB, SIGNAL(clicked()), this, SLOT(unacAllExtraDbPB_clicked()));
connect(CLEditPara, SIGNAL(clicked()), this, SLOT(editParaFormat()));
connect(CLEditHeader, SIGNAL(clicked()), this, SLOT(editHeaderText()));
connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
connect(buildAbsCB, SIGNAL(toggled(bool)),
replAbsCB, SLOT(setEnabled(bool)));
connect(ssNoCompleteCB, SIGNAL(toggled(bool)),
ssSearchOnCompleteCB, SLOT(setDisabled(bool)));
connect(buildAbsCB, SIGNAL(toggled(bool)), replAbsCB, SLOT(setEnabled(bool)));
connect(ssNoCompleteCB, SIGNAL(toggled(bool)), ssSearchOnCompleteCB, SLOT(setDisabled(bool)));
connect(resetscPB, SIGNAL(clicked()), this, SLOT(resetShortcuts()));
(void)new HelpClient(this);
@ -117,6 +108,7 @@ void UIPrefsDialog::setFromPrefs()
// Entries per result page spinbox
pageLenSB->setValue(prefs.respagesize);
idxTreeDepthSB->setValue(prefs.idxFilterTreeDepth);
maxHistSizeSB->setValue(prefs.historysize);
collapseDupsCB->setChecked(prefs.collapseDuplicates);
maxHLTSB->setValue(prefs.maxhltextkbs);
@ -384,6 +376,7 @@ void UIPrefsDialog::accept()
m_mainWindow->setFilterCtlStyle(prefs.filterCtlStyle);
prefs.respagesize = pageLenSB->value();
prefs.idxFilterTreeDepth = idxTreeDepthSB->value();
prefs.historysize = maxHistSizeSB->value();
prefs.collapseDuplicates = collapseDupsCB->isChecked();
prefs.maxhltextkbs = maxHLTSB->value();

View File

@ -322,6 +322,30 @@ template <class T> void stringsToCSV(const T& tokens, string& s, char sep)
s.pop_back();
}
template <class T> std::string commonprefix(const T& values)
{
if (values.empty())
return std::string();
if (values.size() == 1)
return *values.begin();
unsigned int i = 0;
for (;;i++) {
auto it = values.begin();
if (it->size() <= i) {
goto out;
}
auto val = (*it)[i];
it++;
for (;it < values.end(); it++) {
if (it->size() <= i || (*it)[i] != val) {
goto out;
}
}
}
out:
return values.begin()->substr(0, i);
}
#ifdef SMALLUT_EXTERNAL_INSTANTIATIONS
#include "smallut_instantiate.h"
#else
@ -342,8 +366,8 @@ template string stringsToString<vector<string> >(const vector<string>&);
template string stringsToString<set<string> >(const set<string>&);
template string stringsToString<unordered_set<string> >(const unordered_set<string>&);
template void stringsToCSV<list<string> >(const list<string>&, string&, char);
template void stringsToCSV<vector<string> >(const vector<string>&, string&,
char);
template void stringsToCSV<vector<string> >(const vector<string>&, string&, char);
template string commonprefix<vector<string>>(const vector<string>&values);
#endif
void stringToTokens(const string& str, vector<string>& tokens,
@ -571,7 +595,6 @@ string makeCString(const string& in)
return out;
}
// Substitute printf-like percent cmds inside a string
bool pcSubst(const string& in, string& out, const map<char, string>& subs)
{

View File

@ -136,6 +136,9 @@ template <class T> std::string stringsToString(const T& tokens);
template <class T> void stringsToCSV(const T& tokens, std::string& s,
char sep = ',');
/** Find longest common prefix for bunch of strings */
template <class T> std::string commonprefix(const T& values);
/**
* Split input string. No handling of quoting.
*/