31 Commitit
v0.3 ... v0.4

Tekijä SHA1 Viesti Päivämäärä
5f19328679 Release v0.4 2022-06-29 19:31:40 +02:00
5ffd7ae97e shared: common: setPdfViewer(): Fix missing spaces between viewer and args 2022-06-29 19:31:40 +02:00
9ed28df09c README.me: Minor changes 2022-06-29 18:00:05 +02:00
69e028daf5 gui: mainwindow: Open new AboutDialog 2022-06-29 18:00:05 +02:00
d4b0c1feae gui: Add new AboutDialog to show our licenses "paperwork" 2022-06-29 18:00:05 +02:00
990888efc1 shared: Include license texts as resource 2022-06-29 18:00:05 +02:00
3f8c147182 Add LICENSE-3RD-PARTY 2022-06-29 18:00:05 +02:00
ba030169aa gui: previews: Allow filtering file for which to show preview 2022-06-29 18:00:05 +02:00
1636e39c5b shared: ParallelDirScanner: Fix missing progress report from top-level scan 2022-06-27 23:11:26 +02:00
bda23670e3 shared: ParallelDirScanner: Correct filter to 'NoDotAndDotDot' from 'NoDotDot' 2022-06-27 23:10:53 +02:00
d0fe51c666 README: Mention prebuilt tarball, add sig verification, minor improvements 2022-06-24 19:17:50 +02:00
a561032668 shared: Indexer: Adjust for OK_WASEMPTY 2022-06-24 19:17:50 +02:00
b8006bde7b shared: FileSaver: Don't launch SandboxedProcessor for empty files 2022-06-24 19:17:50 +02:00
614238edda shared: FileSaver: Print message for OK_WASEMPTY 2022-06-24 19:17:50 +02:00
83ed935790 shared: FileSaver: Return OK_WASEMPTY
We get OK_WASEMPTY from the processor when there
usually should be something. Rarely, this is not the case.

Let the callers know about this state at least
2022-06-24 19:17:50 +02:00
69837ed60f shared: SaveFileResult: Add OK_WASEMPTY when processor could not extract anything 2022-06-24 19:17:50 +02:00
2ad99699bf shared: FileSaver: Adjust to SandboxedProcessor new SaveFileResult value 2022-06-24 19:17:50 +02:00
b6b3e2f3c0 shared SandBoxedProcessor: Return SaveFileResult, remove defines
Not entirely ideal as SandboxedProcessor does not save anything,
but an improvement nevertheless over the current mess
2022-06-24 19:17:50 +02:00
cf0c940b15 shared: Move SaveFileResult enum to own header 2022-06-24 19:17:50 +02:00
9c41d531b0 gui: mainwindow: Add button to save log of failed paths 2022-06-24 19:17:50 +02:00
780318db6d shared: Indexer: Consider new NOACCESS too 2022-06-24 19:17:50 +02:00
9fd48d4664 shared: FileSaver: Return NOACCESS when no read access 2022-06-24 19:17:50 +02:00
e99b2ba091 shared: Indexer: IndexResult: Introduce failedResults() 2022-06-24 19:17:50 +02:00
0867ab294d shared: SandboxedProcessor: Return NO_ACCESS when file not readable 2022-06-24 19:17:50 +02:00
01a6a499c5 shared: SqliteDBService: Add 'NOACCESS'. Add function to convert enum to str 2022-06-24 19:17:50 +02:00
b3c6ce3899 cli: main: Improve usage text, print it when unknown command given 2022-06-24 19:17:50 +02:00
72dae1f7be cli: CommandAdd: Mention we read from stdin when no path is given 2022-06-24 19:17:50 +02:00
e01f5d6490 shared: ParallelDirScanner: Perform first pass to collect paths
Scan the top directory to collect paths for the threads. This
way we don't launch threads for paths without subdirs. Secondly,
large trees like usually $HOME will be scanned by multiple threads
at first.

Nevertheless, ParallelDirScanner can be improved still as threads may
run quickly out of work, so we may end up with only one anyway again
2022-06-24 19:17:50 +02:00
759d2a7924 Fix builds with quazip 1.X
Sigh. quazip changed the lib name, include locations, etc. from version 1.
Some distributions only have 0.9. Some only  1.x and so some packages break,
so they simply patch it when building the package.

Luckily, nothing we use from quazip is affected from an API perspective.

So detect if there is quazip1, then use pkg-config to link that, else do it like before.
2022-06-21 22:33:50 +02:00
a820183477 README.md: Add voidlinux build instructions 2022-06-20 23:24:10 +02:00
8c5825439a USAGE.md: Update to better reflect current state 2022-06-14 18:50:26 +02:00
28 muutettua tiedostoa jossa 1649 lisäystä ja 112 poistoa

Näytä tiedosto

@ -1,5 +1,19 @@
# looqs: Release notes
## 2022-06-29 - v0.4
This release makes several minor improvements and begins prebuilt binaries of looqs that (should) run
on any recent Linux distribution.
- General: Begin new, experimental distro-agnostic tarball containing prebuilt binaries and libs. See the README for more information.
- GUI: In the "Previews" tab, allow filtering by file, to only show previews for a specific file.
- GUI: Add "Show previews" context menu option to files in result (if available)
- General: Fix build with libquazip 1.X
- General: Properly report access errors as a failure during indexing
- GUI: Add button to export a list of all paths that failed
- General: Improve dir scan threading
- CLI: Improve helptext
- General: Add voidlinux build instructions
## 2022-06-14 - v0.3
CHANGES:
- GUI: Add settings tab to configure various settings

1119
LICENSE-3RD-PARTY Normal file

File diff suppressed because it is too large Load Diff

Näytä tiedosto

@ -3,8 +3,6 @@ looqs is a tool that creates a full-text search index for your files. It allows
search terms have been found, as shown in the screenshots below.
## Screenshots
The screenshots in this section may occasionally be slightly outdated, but they are usually recent enough to get an overall impression of the current state of the GUI.
### Preview
looqs allow you to look inside files. It marks what you have searched for.
@ -28,9 +26,10 @@ There is no need to write the long form of filters. There are also booleans avai
![Screenshot looqs results](https://garage.quitesimple.org/assets/looqs/looqs_beatles_marley.png)
The screenshots in this section may occasionally be slightly outdated, but they are usually recent enough to get an overall impression of the current state of the GUI.
## Current status
Last version: 2022-06-14, v0.3
Latest version: 2022-06-29, v0.4
Please see [Changelog](CHANGELOG.md) for a human readable list of changes.
@ -58,6 +57,8 @@ Linux (on amd64) is currently the main focus. Currently, I don't plan on support
### Licence
GPLv3.
For the dependencies/third-party libraries, see: LICENSE-3RD-PARTY
### Contributing
Please see the [Contribution guidelines](CONTRIBUTING.md) file.
@ -78,6 +79,17 @@ qmake
make
```
### Void
```
# as root
xbps-install qt5-devel poppler-qt5-devel quazip-qt5-devel uchardet-devel gcc make
# as user
git submodule init
git submodule update
qmake
make
```
The GUI is located in `gui/looqs-gui`, the binary for the CLI is in `cli/looqs`
## Packages
@ -95,7 +107,35 @@ sudo apt-get update
sudo apt-get install looqs
```
### Prebuilt tarball (distro-agnostic) (EXPERIMENTAL)
looqs is also distributed as a tarball containing prebuilt binaries and its library dependencies. The tarball is
built using the Gentoo Hardened toolchain and the Qt version is smaller than what distributions usually
include. It does not include libraries that should mess with fontrendering or the graphics stack. The binaries should run on any recent Linux distribution (requires glibc 2.34 or newer at least) and expects
dependencies such as libGL to be provided by your distribution already (should be the case).
It's considered experimental for two reasons. Firstly, looqs has no updater (yet). You will have to manually check for updates. Secondly, I can't guarantee that I'll be quick with updates of the tarball specifically if the library versions become outdated between looqs updates.
You are therefore encouraged to use distro-native packages or to build it yourself if possible.
The tarball can be obtained here: https://repo.quitesimple.org/tarball/looqs
Quick start:
```
# Verify sig, see the end of this document: gpg --verify looqs-v0.4.tar.xz.sig
tar xf looqs-v0.4.tar.xz # Replace with the actual version you have obtained
cd looqs-v0.4
./looqs-gui # or ./looqs for the CLI
```
An AppImage may accompany the tarball in the future.
### Other distros
I'll probably add a package for voidlinux at some point and maybe will provide a Gentoo ebuild. However, I would appreciate help for others distros. If you create a package, let me know!
As for distro-agnostic packages, I will also take a look into appimage / flatpak etc. and/or maybe just provide a self-contained archive.
### Signature verification
Release tags can be verified with [my PGP public key](https://quitesimple.org/share/pubkey). For what little it's worth, its fingerprint is: `C342 CA02 D2EC 2E14 F3C3 D5FF 7F7B 4C08 02CD 02F2`
Packages can be verified with the [repo-specific public key](https://repo.quitesimple.org/repo.quitesimple.org.asc). For what little it's worth, its fingerprint is: `1B49 45B3 16B2 468A 3DAC C1E0 75EF 3FE8 D753 C8F9`

Näytä tiedosto

@ -20,15 +20,12 @@ To give you some idea: At the time this section was written, 167874 files were i
has changed.
## Config
The config file is in `$HOME/.config/quitesimple.org/looqs.conf`. It will be created on first execution of the CLI or GUI
interface. The GUI has a menu entry to quickly open this config file. This is to be considered temporary and will be removed once the GUI itself can edit all settings.
The config file is in `$HOME/.config/quitesimple.org/looqs.conf`. It will be created on first execution of the CLI or GUI interface. Generally, you should not edit this file directly. Instead, use the "Settings" tab in the GUI.
Database default path: `$HOME/.local/share/quitesimple.org/looqs/looqs.sqlite`. If this does not work for
you, move it and adjust adjust the path in the config file.
Database default path: `$HOME/.local/share/quitesimple.org/looqs/looqs.sqlite`. If you prefer a different path, move it and adjust the path.
## GUI
The GUI is minimal at this point. Depending on what you want to do, you may need to open the config file and change the settings there. Chances are that you may not need to do that.
### First run
You will be presented with an empty list. Go to the **"Index"** tab, add some directories and click **"Start indexing"**.
@ -47,8 +44,7 @@ see this document at the end. By default, both the full path and the content are
### Configuring PDF viewer
It's most convenient if, when you click on a preview, the PDF reader opens the page you clicked. For that, looqs needs to know which viewer you want to launch.
It tries to auto detect some common viewers. You must set the value of the ```pdfviewer=``` config entry yourself if it doesn't do something you
like, such as not opening your favorite viewer. In the command line options, "%f" represents the filepath, "%p" the page number.
It tries to auto detect some common viewers. You must set the value in the "Settings" tab yourself if it doesn't do something you like, such as not opening your favorite viewer. In the command line options, "%f" represents the filepath, "%p" the page number.
### Preview tab
The preview tab shows previews. It marks your search keywords too. Click on a preview to open the file.

Näytä tiedosto

@ -37,6 +37,12 @@ else:unix: LIBS += -L$$OUT_PWD/../shared/ -lshared
LIBS += -luchardet -lpoppler-qt5 -lquazip5
packagesExist(quazip1-qt5) {
PKGCONFIG += quazip1-qt5
CONFIG += link_pkgconfig
LIBS -= -lquazip5
}
INCLUDEPATH += $$PWD/../shared
DEPENDPATH += $$PWD/../shared

Näytä tiedosto

@ -47,7 +47,8 @@ int CommandAdd::handle(QStringList arguments)
{{"t", "threads"}, "Number of threads to use.", "threads"}});
parser.addHelpOption();
parser.addPositionalArgument("add", "Add paths to the index", "add [paths...]");
parser.addPositionalArgument("add", "Add paths to the index",
"add [paths...]. If no path is given, read from stdin, one path per line.");
parser.process(arguments);
this->keepGoing = parser.isSet("continue");

Näytä tiedosto

@ -30,6 +30,7 @@
void printUsage(QString argv0)
{
qInfo() << "Usage:" << argv0 << "command";
qInfo() << "Valid commands: add, update, delete, search, list. Each command has a --help option.";
}
Command *commandFromName(QString name, SqliteDbService &dbService)
@ -97,7 +98,7 @@ int main(int argc, char *argv[])
QString file = args.at(1);
SandboxedProcessor processor(file);
return processor.process();
return static_cast<int>(processor.process());
}
Command *cmd = commandFromName(commandName, dbService);
if(cmd != nullptr)
@ -116,7 +117,7 @@ int main(int argc, char *argv[])
}
else
{
Logger::error() << "Unknown command:" << commandName << Qt::endl;
printUsage(argv0);
return 1;
}

74
gui/aboutdialog.cpp Normal file
Näytä tiedosto

@ -0,0 +1,74 @@
#include <QTabWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QTextBrowser>
#include <QPushButton>
#include "aboutdialog.h"
#include "common.h"
AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
QTabWidget *tabWidget = new QTabWidget(this);
this->setWindowTitle("About looqs");
QHBoxLayout *closeLayout = new QHBoxLayout();
QPushButton *closeButton = new QPushButton(this);
closeButton->setText("Close");
closeButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
connect(closeButton, &QPushButton::clicked, this, &QDialog::close);
closeLayout->setMargin(10);
closeLayout->addStretch(10);
closeLayout->addWidget(closeButton);
layout->addWidget(tabWidget);
layout->addLayout(closeLayout);
QFrame *frame = new QFrame(this);
QVBoxLayout *aboutLayout = new QVBoxLayout(frame);
frame->setLayout(aboutLayout);
QLabel *aboutLooqs = new QLabel(this);
QString html = "<h2>looqs</h2>";
html += "Full-text search with previews for your files<br><br>";
html += "Copyright (c) 2018-2022: Albert Schwarzkopf<br><br>";
html += QString("Version: %1<br><br>").arg(Common::versionText());
html += "Contact: looqs at quitesimple dot org<br><br>";
html += "Website: <a href=\"https://quitesimple.org\">https://quitesimple.org</a><br><br>";
html += "Source code: <a "
"href=\"https://github.com/quitesimpleorg/looqs\">https://github.com/quitesimpleorg/looqs</a><br><br>";
html += "License: GPLv3<br><br>";
html += "looqs is open source and free of charge in the hope it will be useful. The author(s) do not "
"give any warranty. In the unlikely event of any damage, the author(s) cannot be held responsible. "
"You are using looqs at your own risk<br><br>";
html += "looqs uses third-party libraries, please see the corresponding tab.";
aboutLooqs->setText(html);
aboutLooqs->setTextFormat(Qt::RichText);
QLabel *logo = new QLabel(this);
QImage image(QString(":/looqs.svg"));
logo->setPixmap(QPixmap::fromImage(image));
aboutLayout->addWidget(logo);
aboutLayout->addWidget(aboutLooqs);
tabWidget->addTab(frame, "About");
QFile license(QString(":/LICENSE"));
license.open(QIODevice::ReadOnly);
QString licenseText = license.readAll();
QFile thirdPartyLicense(QString(":./LICENSE-3RD-PARTY"));
thirdPartyLicense.open(QIODevice::ReadOnly);
QString thirdPartyLicenseInfo = thirdPartyLicense.readAll();
QTextBrowser *licenseTextBrowser = new QTextBrowser(this);
licenseTextBrowser->setText(licenseText);
QTextBrowser *thirdPartyLicenceTextBrowser = new QTextBrowser(this);
thirdPartyLicenceTextBrowser->setText(thirdPartyLicenseInfo);
tabWidget->addTab(licenseTextBrowser, "License");
tabWidget->addTab(thirdPartyLicenceTextBrowser, "Third-party libraries");
}

12
gui/aboutdialog.h Normal file
Näytä tiedosto

@ -0,0 +1,12 @@
#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H
#include <QDialog>
class AboutDialog : public QDialog
{
Q_OBJECT
public:
AboutDialog(QWidget *parent = nullptr);
};
#endif // ABOUTDIALOG_H

Näytä tiedosto

@ -7,7 +7,11 @@
QT += core concurrent gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
TARGET = looqs-gui
TEMPLATE = app
@ -23,6 +27,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
aboutdialog.cpp \
ipcpreviewclient.cpp \
ipcpreviewworker.cpp \
ipcserver.cpp \
@ -40,6 +45,7 @@ SOURCES += \
rendertarget.cpp
HEADERS += \
aboutdialog.h \
ipc.h \
ipcpreviewclient.h \
ipcpreviewworker.h \
@ -69,6 +75,12 @@ else:unix: LIBS += -L$$OUT_PWD/../shared/ -lshared
LIBS += -luchardet -lpoppler-qt5 -lquazip5
packagesExist(quazip1-qt5) {
PKGCONFIG += quazip1-qt5
CONFIG += link_pkgconfig
LIBS -= -lquazip5
}
INCLUDEPATH += $$PWD/../shared
DEPENDPATH += $$PWD/../shared

Näytä tiedosto

@ -114,7 +114,7 @@ int main(int argc, char *argv[])
QString file = args.at(2);
SandboxedProcessor processor(file);
return processor.process();
return static_cast<int>(processor.process());
}
}
QString ipcSocketPath = Common::ipcSocketPath();

Näytä tiedosto

@ -23,6 +23,7 @@
#include "../shared/common.h"
#include "ipcpreviewclient.h"
#include "previewgenerator.h"
#include "aboutdialog.h"
MainWindow::MainWindow(QWidget *parent, QString socketPath)
: QMainWindow(parent), ui(new Ui::MainWindow), progressDialog(this)
@ -40,6 +41,7 @@ MainWindow::MainWindow(QWidget *parent, QString socketPath)
{
this->ui->previewProcessBar->setValue(this->ui->previewProcessBar->maximum());
this->ui->spinPreviewPage->setEnabled(true);
this->ui->comboPreviewFiles->setEnabled(true);
});
connect(&ipcPreviewClient, &IPCPreviewClient::error, this,
[this](QString msg)
@ -82,6 +84,13 @@ MainWindow::MainWindow(QWidget *parent, QString socketPath)
ui->spinPreviewPage->setValue(1);
ui->spinPreviewPage->setMinimum(1);
ui->btnOpenFailed->setVisible(false);
ui->comboPreviewFiles->setVisible(false);
auto policy = ui->btnOpenFailed->sizePolicy();
policy.setRetainSizeWhenHidden(true);
ui->btnOpenFailed->setSizePolicy(policy);
}
void MainWindow::addPathToIndex()
@ -172,26 +181,13 @@ void MainWindow::connectSignals()
}
}
});
connect(
ui->menuAboutAction, &QAction::triggered, this,
[this](bool checked)
{
QString html = "<h2>looqs</h2>";
html += "Full-text search with previews for your files<br><br>";
html += "Copyright (c) 2018-2022: Albert Schwarzkopf<br><br>";
html += QString("Version: %1<br><br>").arg(Common::versionText());
html += "Contact: looqs at quitesimple dot org<br><br>";
html += "Website: <a href=\"https://quitesimple.org\">https://quitesimple.org</a><br><br>";
html +=
"Source code: <a "
"href=\"https://github.com/quitesimpleorg/looqs\">https://github.com/quitesimpleorg/looqs</a><br><br>";
html += "License: GPLv3<br><br><br>";
html += "looqs is open source and free of charge in the hope it will be useful. The author(s) do not "
"give any warranty. In the unlikely event of any damage, the author(s) cannot be held responsible. "
"You are using looqs at your own risk";
connect(ui->menuAboutAction, &QAction::triggered, this,
[this](bool checked)
{
AboutDialog aboutDialog(this);
QMessageBox::about(this, "About looqs", html);
});
aboutDialog.exec();
});
connect(ui->menuAboutQtAction, &QAction::triggered, this,
[this](bool checked) { QMessageBox::aboutQt(this, "About Qt"); });
connect(ui->menuSyncIndexAction, &QAction::triggered, this, &MainWindow::startIndexSync);
@ -210,6 +206,35 @@ void MainWindow::connectSignals()
connect(this, &MainWindow::beginIndexSync, indexSyncer, &IndexSyncer::sync);
connect(&this->progressDialog, &QProgressDialog::canceled, indexSyncer, &IndexSyncer::cancel);
connect(ui->btnSaveSettings, &QPushButton::clicked, this, &MainWindow::saveSettings);
connect(ui->btnOpenFailed, &QPushButton::clicked, this, &MainWindow::exportFailedPaths);
connect(
ui->comboPreviewFiles, qOverload<int>(&QComboBox::currentIndexChanged), this, [&]() { makePreviews(1); },
Qt::QueuedConnection);
}
void MainWindow::exportFailedPaths()
{
QString filename =
QString("/tmp/looqs_indexresult_failed_%1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hhmmss"));
QFile outFile(filename);
if(!outFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QMessageBox::critical(this, "Failed to write log file", "An error occured while trying to create log file");
return;
}
QTextStream stream(&outFile);
IndexResult result = this->indexer->getResult();
stream << "Failed to index the following paths:\n";
for(FileScanResult &fsr : result.failedResults())
{
stream << fsr.first << " " << SaveFileResultToString(fsr.second) << '\n';
}
QDesktopServices::openUrl(filename);
}
void MainWindow::startIndexSync()
@ -254,6 +279,7 @@ void MainWindow::startIndexing()
ui->txtSearch->setEnabled(false);
ui->previewProcessBar->setValue(0);
ui->previewProcessBar->setVisible(true);
ui->btnOpenFailed->setVisible(false);
QVector<QString> paths;
QStringList pathSettingsValue;
@ -289,6 +315,10 @@ void MainWindow::finishIndexing()
ui->settingsTab->setEnabled(true);
ui->txtPathScanAdd->setEnabled(true);
ui->txtSearch->setEnabled(true);
if(result.erroredPaths > 0)
{
ui->btnOpenFailed->setVisible(true);
}
}
void MainWindow::comboScaleChanged(int i)
@ -477,6 +507,9 @@ void MainWindow::handleSearchResults(const QVector<SearchResult> &results)
{
this->previewableSearchResults.clear();
ui->treeResultsList->clear();
ui->comboPreviewFiles->clear();
ui->comboPreviewFiles->addItem("All previews");
ui->comboPreviewFiles->setVisible(true);
bool hasDeleted = false;
for(const SearchResult &result : results)
@ -505,6 +538,7 @@ void MainWindow::handleSearchResults(const QVector<SearchResult> &results)
if(PreviewGenerator::get(pathInfo) != nullptr)
{
this->previewableSearchResults.append(result);
ui->comboPreviewFiles->addItem(result.fileData.absPath);
}
}
}
@ -582,6 +616,13 @@ void MainWindow::makePreviews(int page)
QVector<RenderTarget> targets;
for(SearchResult &sr : this->previewableSearchResults)
{
if(ui->comboPreviewFiles->currentIndex() != 0)
{
if(sr.fileData.absPath != ui->comboPreviewFiles->currentText())
{
continue;
}
}
RenderTarget renderTarget;
renderTarget.path = sr.fileData.absPath;
@ -602,6 +643,7 @@ void MainWindow::makePreviews(int page)
ui->previewProcessBar->setVisible(this->previewableSearchResults.size() > 0);
++this->currentPreviewGeneration;
this->ui->spinPreviewPage->setEnabled(false);
this->ui->comboPreviewFiles->setEnabled(false);
emit startIpcPreviews(renderConfig, targets);
}
@ -617,6 +659,20 @@ void MainWindow::createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo)
menu.addAction("Copy full path to clipboard",
[&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.absoluteFilePath()); });
menu.addAction("Open containing folder", [this, &fileInfo] { this->openFile(fileInfo.absolutePath()); });
auto result =
std::find_if(this->previewableSearchResults.begin(), this->previewableSearchResults.end(),
[this, &fileInfo](SearchResult &a) { return fileInfo.absoluteFilePath() == a.fileData.absPath; });
if(result != this->previewableSearchResults.end())
{
menu.addAction("Show previews for this file",
[this, &fileInfo]
{
ui->tabWidget->setCurrentIndex(1);
this->ui->comboPreviewFiles->setCurrentText(fileInfo.absoluteFilePath());
});
}
}
void MainWindow::openDocument(QString path, int num)

Näytä tiedosto

@ -75,6 +75,7 @@ class MainWindow : public QMainWindow
void addPathToIndex();
void startIndexSync();
void saveSettings();
void exportFailedPaths();
signals:
void startIpcPreviews(RenderConfig config, const QVector<RenderTarget> &targets);

Näytä tiedosto

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>1280</width>
<height>736</height>
<height>855</height>
</rect>
</property>
<property name="windowTitle">
@ -27,7 +27,7 @@
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<widget class="QWidget" name="resultsTab">
<attribute name="title">
@ -82,7 +82,7 @@
<x>0</x>
<y>0</y>
<width>1244</width>
<height>446</height>
<height>565</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout"/>
@ -162,6 +162,16 @@
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboPreviewFiles">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@ -184,6 +194,16 @@
<string>Index</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="0">
<widget class="QLineEdit" name="txtIgnorePatterns"/>
</item>
<item row="11" column="0">
<widget class="QPushButton" name="btnStartIndexing">
<property name="text">
<string>Start indexing</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBoxPaths">
<property name="title">
@ -243,6 +263,12 @@
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="lblPathsFound">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Paths found:</string>
</property>
@ -250,17 +276,42 @@
</item>
<item>
<widget class="QLabel" name="lblPathsFoundValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<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>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblAdded">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
@ -274,17 +325,42 @@
</item>
<item>
<widget class="QLabel" name="lblAddedValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="lblSkipped">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
@ -298,17 +374,42 @@
</item>
<item>
<widget class="QLabel" name="lblSkippedValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="lblFailed">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
@ -322,26 +423,35 @@
</item>
<item>
<widget class="QLabel" name="lblFailedValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnOpenFailed">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Open log of failed paths</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="6" column="0">
<widget class="QLineEdit" name="txtIgnorePatterns"/>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="btnStartIndexing">
<property name="text">
<string>Start indexing</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="settingsTab">

Näytä tiedosto

@ -17,6 +17,7 @@
inline void initResources()
{
Q_INIT_RESOURCE(migrations);
Q_INIT_RESOURCE(plaintexts);
}
bool Common::initSqliteDatabase(QString path)
@ -68,11 +69,11 @@ void Common::setPdfViewer()
}
else if(evincePath != "")
{
value = evincePath + "-i %p %f";
value = evincePath + " -i %p %f";
}
else if(qpdfviewPath != "")
{
value = qpdfviewPath + "%f#%p";
value = qpdfviewPath + " %f#%p";
}
QSettings settings;

Näytä tiedosto

@ -19,9 +19,12 @@ void DirScanWorker::run()
QString path;
/* TODO: if we have e. g. only one path, then only one thread will scan this path.
*
* Thus, we must resubmit to the queue directories so other threads can help
the current one (requires a new logic for threads in ParallelDirScanner). Alterantively,
start new DirScanWorkers ourselves here... */
* Thus, we must submit new directory paths to the queue so other threads can help
the current one.
It also may not be guaranteed enqueuing new paths is faster than just scanning them,
at least not for dirs with a small number of files
*/
while(queue->dequeue(path))
{
if(wildcardMatcher.match(path))

Näytä tiedosto

@ -87,6 +87,10 @@ int FileSaver::processFiles(const QVector<QString> paths, std::function<SaveFile
{
Logger::info() << "Saved" << path << Qt::endl;
}
else if(result == OK_WASEMPTY)
{
Logger::info() << "Saved (but content was empty)" << path << Qt::endl;
}
}
}
});
@ -98,7 +102,12 @@ SaveFileResult FileSaver::saveFile(const QFileInfo &fileInfo)
QVector<PageData> pageData;
QString canonicalPath = fileInfo.canonicalFilePath();
int status = -1;
int processorReturnCode = -1;
if(!fileInfo.isReadable())
{
return NOACCESS;
}
if(!fileInfo.exists())
{
@ -115,44 +124,45 @@ SaveFileResult FileSaver::saveFile(const QFileInfo &fileInfo)
}
}
QProcess process;
QStringList args;
args << "process" << canonicalPath;
process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
process.start("/proc/self/exe", args);
process.waitForStarted();
process.waitForFinished();
/* TODO: This is suboptimal as it eats lots of mem
* but avoids a weird QDataStream/QProcess behaviour
* where it thinks the process has ended when it has not...
*
* Also, there seem to be issues with reads not being blocked, so
* the only reliable way appears to be waiting until the process
* finishes.
*/
QDataStream in(process.readAllStandardOutput());
while(!in.atEnd())
if(fileInfo.size() > 0)
{
PageData pd;
in >> pd;
pageData.append(pd);
}
status = process.exitCode();
if(status != 0 && status != NOTHING_PROCESSED)
{
Logger::error() << "FileSaver::saveFile(): Error while processing" << canonicalPath << ":"
<< "Exit code " << status << Qt::endl;
QProcess process;
QStringList args;
args << "process" << canonicalPath;
process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
process.start("/proc/self/exe", args);
process.waitForStarted();
process.waitForFinished();
return PROCESSFAIL;
/* TODO: This is suboptimal as it eats lots of mem
* but avoids a weird QDataStream/QProcess behaviour
* where it thinks the process has ended when it has not...
*
* Also, there seem to be issues with reads not being blocked, so
* the only reliable way appears to be waiting until the process
* finishes.
*/
QDataStream in(process.readAllStandardOutput());
while(!in.atEnd())
{
PageData pd;
in >> pd;
pageData.append(pd);
}
processorReturnCode = process.exitCode();
if(processorReturnCode != OK && processorReturnCode != OK_WASEMPTY)
{
Logger::error() << "FileSaver::saveFile(): Error while processing" << canonicalPath << ":"
<< "Exit code " << processorReturnCode << Qt::endl;
return static_cast<SaveFileResult>(processorReturnCode);
}
}
}
// Could happen if a file corrupted for example
if(pageData.isEmpty() && status != NOTHING_PROCESSED)
SaveFileResult result = this->dbService->saveFile(fileInfo, pageData);
if(result == OK && processorReturnCode == OK_WASEMPTY)
{
Logger::error() << "Could not get any content for " << canonicalPath << Qt::endl;
return OK_WASEMPTY;
}
return this->dbService->saveFile(fileInfo, pageData);
return result;
}

Näytä tiedosto

@ -120,7 +120,7 @@ void Indexer::dirScanProgress(int current, int total)
void Indexer::processFileScanResult(FileScanResult result)
{
if(result.second == DBFAIL || result.second == PROCESSFAIL || result.second == NOTFOUND)
if(result.second != OK || result.second != OK_WASEMPTY || result.second != SKIPPED)
{
this->currentIndexResult.results.append(result);
if(!keepGoing)
@ -138,7 +138,8 @@ void Indexer::processFileScanResult(FileScanResult result)
}
}
if(result.second == OK)
/* TODO: OK_WASEMPTY might need a special list */
if(result.second == OK || result.second == OK_WASEMPTY)
{
++this->currentIndexResult.addedPaths;
}

Näytä tiedosto

@ -22,19 +22,30 @@ class IndexResult
return addedPaths + skippedPaths + erroredPaths;
}
QVector<QString> failedPaths() const
QVector<FileScanResult> failedResults() const
{
QVector<QString> result;
QVector<FileScanResult> result;
std::for_each(results.begin(), results.end(),
[&result](FileScanResult res)
{
if(res.second == DBFAIL || res.second == PROCESSFAIL || res.second == NOTFOUND)
if(res.second == DBFAIL || res.second == PROCESSFAIL || res.second == NOTFOUND ||
res.second == NOACCESS)
{
result.append(res.first);
result.append(res);
}
});
return result;
}
QVector<QString> failedPaths() const
{
QVector<QString> result;
QVector<FileScanResult> results = failedResults();
std::for_each(results.begin(), results.end(), [&result](FileScanResult res) { result.append(res.first); });
return result;
}
};
class Indexer : public QObject

Näytä tiedosto

@ -1,5 +1,5 @@
#include <quazip5/quazip.h>
#include <quazip5/quazipfile.h>
#include <quazip.h>
#include <quazipfile.h>
#include "odtprocessor.h"
#include "tagstripperprocessor.h"

Näytä tiedosto

@ -71,7 +71,35 @@ void ParallelDirScanner::scan()
this->targetPathsQueue.clear();
this->resultPathsQueue.clear();
this->targetPathsQueue.enqueue(this->paths);
/* First scan without subdirs. This way we collect paths for the threads */
WildcardMatcher matcher;
matcher.setPatterns(this->ignorePatterns);
for(QString &path : this->paths)
{
QDirIterator iterator(path, QStringList{}, QDir::Dirs | QDir::QDir::Files | QDir::NoDotAndDotDot);
while(iterator.hasNext())
{
QString path = iterator.next();
if(matcher.match(path))
{
continue;
}
QFileInfo info = iterator.fileInfo();
if(!info.isSymLink())
{
if(info.isDir())
{
this->targetPathsQueue.enqueue(info.absoluteFilePath());
}
else
{
this->resultPathsQueue.enqueue(info.absoluteFilePath());
this->processedPaths += 1;
}
}
}
}
emit this->progress(this->processedPaths, this->processedPaths);
int threadsNum = getThreadsNum();
if(threadsNum == 0)
{

6
shared/plaintexts.qrc Normal file
Näytä tiedosto

@ -0,0 +1,6 @@
<RCC>
<qresource>
<file>../LICENSE</file>
<file>../LICENSE-3RD-PARTY</file>
</qresource>
</RCC>

Näytä tiedosto

@ -10,8 +10,6 @@ enum DataSource
ARRAY
};
#define NOTHING_PROCESSED 4
class Processor
{
public:

Näytä tiedosto

@ -80,7 +80,7 @@ void SandboxedProcessor::printResults(const QVector<PageData> &pageData)
fsstdout.close();
}
int SandboxedProcessor::process()
SaveFileResult SandboxedProcessor::process()
{
QFileInfo fileInfo(this->filePath);
Processor *processor = processors.value(fileInfo.suffix(), nullptr);
@ -92,10 +92,14 @@ int SandboxedProcessor::process()
processor = defaultTextProcessor;
}
}
if(!fileInfo.isReadable())
{
return NOACCESS;
}
if(processor == nullptr || processor == nothingProcessor)
{
/* Nothing to do */
return NOTHING_PROCESSED;
return OK;
}
QVector<PageData> pageData;
@ -119,9 +123,9 @@ int SandboxedProcessor::process()
catch(LooqsGeneralException &e)
{
Logger::error() << "SandboxedProcessor: Error while processing" << absPath << ":" << e.message << Qt::endl;
return 3 /* PROCESSFAIL */;
return PROCESSFAIL;
}
printResults(pageData);
return 0;
return pageData.isEmpty() ? OK_WASEMPTY : OK;
}

Näytä tiedosto

@ -3,6 +3,7 @@
#include <QString>
#include <QMimeDatabase>
#include "pagedata.h"
#include "savefileresult.h"
class SandboxedProcessor
{
@ -19,7 +20,7 @@ class SandboxedProcessor
this->filePath = filepath;
}
int process();
SaveFileResult process();
};
#endif // SANDBOXEDPROCESSOR_H

33
shared/savefileresult.h Normal file
Näytä tiedosto

@ -0,0 +1,33 @@
#ifndef SAVEFILERESULT_H
#define SAVEFILERESULT_H
#include <QStringList>
enum SaveFileResult
{
OK,
OK_WASEMPTY, /* The file was successfully read but no content could be extracted. Might be just an empty document or
so*/
SKIPPED, /* The file was not processed/saved, because it has not changed */
DBFAIL, /* A database error occured */
PROCESSFAIL, /* General processor failure */
NOTFOUND, /* The file was not found */
NOACCESS /* The process can't read the file */
};
static inline QString SaveFileResultToString(SaveFileResult sfr)
{
QStringList SaveFileResultStr;
SaveFileResultStr << "OK"
<< "OK_WASEMPTY"
<< "SKIPPED"
<< "DBFAIL"
<< "PROCESSFAIL"
<< "NOTFOUND"
<< "NOACCESS";
return SaveFileResultStr[(int)sfr];
}
#endif // SAVEFILERESULT_H

Näytä tiedosto

@ -16,7 +16,11 @@ CONFIG += c++17
INCLUDEPATH += $$PWD/../sandbox/exile.h/
INCLUDEPATH += /usr/include/poppler/qt5/ /usr/include/quazip5
# Dirty, we only need the includes here but well this magic works, so...
packagesExist(quazip1-qt5) {
PKGCONFIG += quazip1-qt5
CONFIG += link_pkgconfig
}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
@ -84,6 +88,7 @@ HEADERS += sqlitesearch.h \
pdfprocessor.h \
processor.h \
sandboxedprocessor.h \
savefileresult.h \
searchresult.h \
sqlitedbservice.h \
tagstripperprocessor.h \
@ -96,3 +101,4 @@ unix {
INSTALLS += target
}
RESOURCES = migrations/migrations.qrc
RESOURCES += plaintexts.qrc

Näytä tiedosto

@ -7,14 +7,7 @@
#include "filedata.h"
#include "../shared/sqlitesearch.h"
#include "../shared/token.h"
enum SaveFileResult
{
OK,
SKIPPED,
DBFAIL,
PROCESSFAIL,
NOTFOUND
};
#include "savefileresult.h"
class SqliteDbService
{