GUI: implemented sidebar for filtering on directory location
This commit is contained in:
parent
4ca4bf21db
commit
064018ea69
@ -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 \
|
||||
|
||||
@ -211,6 +211,7 @@ void ConfIndexW::acceptChanges()
|
||||
delete m_conf;
|
||||
m_conf = 0;
|
||||
m_rclconf->updateMainConfig();
|
||||
emit idxConfigPossiblyChanged();
|
||||
}
|
||||
|
||||
void ConfIndexW::initPanels()
|
||||
|
||||
@ -50,6 +50,9 @@ public slots:
|
||||
void showPrefs(bool modal);
|
||||
void acceptChanges();
|
||||
QWidget *getDialog() {return m_w;}
|
||||
|
||||
signals:
|
||||
void idxConfigPossiblyChanged();
|
||||
|
||||
private:
|
||||
void initPanels();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
109
src/qtgui/idxmodel.cpp
Normal 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
42
src/qtgui/idxmodel.h
Normal 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
|
||||
54
src/qtgui/rclm_sidefilters.cpp
Normal file
54
src/qtgui/rclm_sidefilters.cpp
Normal 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;
|
||||
}
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user