Rename project from 'qss' to 'looqs' #23
							
								
								
									
										29
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								README.md
									
									
									
									
									
								
							@@ -1,37 +1,30 @@
 | 
			
		||||
qss
 | 
			
		||||
=========
 | 
			
		||||
quite simple search (qss) creates a poor-man full-text search for your files using a sqlite database.
 | 
			
		||||
# looqs - Looks for files. And looks inside them
 | 
			
		||||
looqs creates a full text search for your files. It allows you to look at previews where your
 | 
			
		||||
search terms have been found. 
 | 
			
		||||
 | 
			
		||||
A simple gui renders the pages of the documents where your search keywords have been found. Currently, this allows you search all indexed pdfs and take a look at the pages side by side in an instant.
 | 
			
		||||
Currently, this allows you search all indexed pdfs and take a look at the pages side by side in an instant.
 | 
			
		||||
 | 
			
		||||
The name of the project will probably be changed.
 | 
			
		||||
 | 
			
		||||
Screenshots
 | 
			
		||||
-----------
 | 
			
		||||
## Screenshots
 | 
			
		||||
Coming soon™
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Goals
 | 
			
		||||
=====
 | 
			
		||||
## Goals
 | 
			
		||||
 * **Find & Preview**. Instead of merely telling you where your search phrase has been found, it should also render the corresponding portion/pages of the documents and highlight the searched words.
 | 
			
		||||
 * **No daemons**. As other solutions are prone to have annoying daemons running that eat system resources away, this solution should make do without daemons if possible.
 | 
			
		||||
 * **Easy setup**. Similiarly, there should be no need for heavy-weight databases. Instead, this solution tries to squeeze out the most from simple approaches. In particular, it relies on sqlite. 
 | 
			
		||||
 * **GUI & CLI**. Provide CLI interfaces and GUI interfaces
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Build
 | 
			
		||||
-----
 | 
			
		||||
### Ubuntu 20.04
 | 
			
		||||
## Build
 | 
			
		||||
### Ubuntu 21.04
 | 
			
		||||
```
 | 
			
		||||
sudo apt install build-essential qt5-default libpoppler-qt5-dev libuchardet-dev libquazip5-dev
 | 
			
		||||
sudo apt install build-essential qtbase5-dev libpoppler-qt5-dev libuchardet-dev libquazip5-dev
 | 
			
		||||
qmake
 | 
			
		||||
make
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Documentation
 | 
			
		||||
-------------
 | 
			
		||||
## Documentation
 | 
			
		||||
Coming soon™
 | 
			
		||||
 | 
			
		||||
Packages
 | 
			
		||||
-----
 | 
			
		||||
## Packages
 | 
			
		||||
Coming soon™
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ QT -= gui
 | 
			
		||||
QT += sql concurrent
 | 
			
		||||
CONFIG += c++17 console
 | 
			
		||||
CONFIG -= app_bundle
 | 
			
		||||
TARGET = looqs
 | 
			
		||||
 | 
			
		||||
# The following define makes your compiler emit warnings if you use
 | 
			
		||||
# any feature of Qt which as been marked deprecated (the exact warnings
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ int CommandAdd::handle(QStringList arguments)
 | 
			
		||||
{
 | 
			
		||||
    QCommandLineParser parser;
 | 
			
		||||
    parser.addOptions({
 | 
			
		||||
                          { { "c", "continue" }, "Continue adding files, don't exit on first error. If this option is not given, qss will exit asap, but it's possible that a few files will still be processed. "
 | 
			
		||||
                          { { "c", "continue" }, "Continue adding files, don't exit on first error. If this option is not given, looqs will exit asap, but it's possible that a few files will still be processed. "
 | 
			
		||||
                            "Set -t 1 to avoid this behavior, but processing will be slower. "},
 | 
			
		||||
                          { { "a", "all" }, "On error, no files should be added, even already processed ones" },
 | 
			
		||||
                          { { "v", "verbose" }, "Print skipped and added files" },
 | 
			
		||||
@@ -36,7 +36,7 @@ int CommandAdd::handle(QStringList arguments)
 | 
			
		||||
    bool verbose = parser.isSet("verbose");
 | 
			
		||||
    if(parser.isSet("all"))
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("To be implemented");
 | 
			
		||||
        throw LooqsGeneralException("To be implemented");
 | 
			
		||||
    }
 | 
			
		||||
    if(parser.isSet("threads"))
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,13 +19,13 @@ int CommandList::handle(QStringList arguments)
 | 
			
		||||
    bool reverse = parser.isSet("reverse");
 | 
			
		||||
    if(reverse)
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Reverse option to be implemented");
 | 
			
		||||
        throw LooqsGeneralException("Reverse option to be implemented");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    QStringList files = parser.positionalArguments();
 | 
			
		||||
    QString queryStrings = files.join(' ');
 | 
			
		||||
    auto results = dbService->search(QSSQuery::build(queryStrings));
 | 
			
		||||
    auto results = dbService->search(LooqsQuery::build(queryStrings));
 | 
			
		||||
 | 
			
		||||
    for(SearchResult &result : results)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ int CommandSearch::handle(QStringList arguments)
 | 
			
		||||
 | 
			
		||||
    QStringList files = parser.positionalArguments();
 | 
			
		||||
    QString queryStrings = files.join(' ');
 | 
			
		||||
    QSSQuery query = QSSQuery::build(queryStrings);
 | 
			
		||||
    LooqsQuery query = LooqsQuery::build(queryStrings);
 | 
			
		||||
    bool reverse = parser.isSet("reverse");
 | 
			
		||||
    if(reverse)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ int CommandUpdate::handle(QStringList arguments)
 | 
			
		||||
                          { { "n", "dry-run"}, "Only print which files would be updated, don't actually update them"},
 | 
			
		||||
                          { "pattern", "Only consider to update files in the index matching the pattern, e. g. */.git/*.", "pattern" },
 | 
			
		||||
                          { { "d", "delete" }, "If a file does not exist anymore, delete it" },
 | 
			
		||||
                          { { "c", "continue" }, "Continue adding files, don't exit on first error. If this option is not given, qss will exit asap, but it's possible that a few files will still be processed. "
 | 
			
		||||
                          { { "c", "continue" }, "Continue adding files, don't exit on first error. If this option is not given, looqs will exit asap, but it's possible that a few files will still be processed. "
 | 
			
		||||
                            "Set -t 1 to avoid this behavior, but processing will be slower."},
 | 
			
		||||
                          { { "a", "all" }, "On error, no files should be updated, even already processed ones" },
 | 
			
		||||
                          { { "t", "threads" }, "Number of threads to use.", "threads" }
 | 
			
		||||
@@ -34,7 +34,7 @@ int CommandUpdate::handle(QStringList arguments)
 | 
			
		||||
 | 
			
		||||
    if(parser.isSet("all"))
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("To be implemented");
 | 
			
		||||
        throw LooqsGeneralException("To be implemented");
 | 
			
		||||
    }
 | 
			
		||||
    if(parser.isSet("threads"))
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ QSqlDatabase DatabaseFactory::createNew()
 | 
			
		||||
    if(!db.open())
 | 
			
		||||
    {
 | 
			
		||||
        Logger::error() << "Failed to open the database: " << this->connectionString << endl;
 | 
			
		||||
        throw QSSGeneralException("Failed to create open new connection");
 | 
			
		||||
        throw LooqsGeneralException("Failed to create open new connection");
 | 
			
		||||
    }
 | 
			
		||||
    return db;
 | 
			
		||||
}
 | 
			
		||||
@@ -32,7 +32,7 @@ QSqlDatabase DatabaseFactory::forCurrentThread()
 | 
			
		||||
    if(!db.open())
 | 
			
		||||
    {
 | 
			
		||||
        Logger::error() << "Failed to open the database: " << this->connectionString << endl;
 | 
			
		||||
        throw QSSGeneralException("Failed to create open new connection");
 | 
			
		||||
        throw LooqsGeneralException("Failed to create open new connection");
 | 
			
		||||
    }
 | 
			
		||||
    dbStore.setLocalData(db);
 | 
			
		||||
    return db;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
#include <QDataStream>
 | 
			
		||||
#include "encodingdetector.h"
 | 
			
		||||
#include <qssgeneralexception.h>
 | 
			
		||||
#include <looqsgeneralexception.h>
 | 
			
		||||
EncodingDetector::EncodingDetector()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +13,7 @@ QString EncodingDetector::detectEncoding(const QByteArray &data) const
 | 
			
		||||
    if(uchardet_handle_data(detector, data.data(), data.size()) != 0 )
 | 
			
		||||
    {
 | 
			
		||||
      uchardet_delete(detector);
 | 
			
		||||
      throw QSSGeneralException("Decoder failed");
 | 
			
		||||
      throw LooqsGeneralException("Decoder failed");
 | 
			
		||||
    }
 | 
			
		||||
    uchardet_data_end(detector);
 | 
			
		||||
    QString encoding = uchardet_get_charset(detector);
 | 
			
		||||
@@ -33,13 +33,13 @@ QString EncodingDetector::detectEncoding(QDataStream &s) const
 | 
			
		||||
        {
 | 
			
		||||
            uchardet_delete(detector);
 | 
			
		||||
 | 
			
		||||
            throw QSSGeneralException("Decoder failed");
 | 
			
		||||
            throw LooqsGeneralException("Decoder failed");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(n == -1)
 | 
			
		||||
    {
 | 
			
		||||
        uchardet_delete(detector);
 | 
			
		||||
        throw QSSGeneralException("Read failed");
 | 
			
		||||
        throw LooqsGeneralException("Read failed");
 | 
			
		||||
    }
 | 
			
		||||
    uchardet_data_end(detector);
 | 
			
		||||
    QString encoding = uchardet_get_charset(detector);
 | 
			
		||||
 
 | 
			
		||||
@@ -131,7 +131,7 @@ SaveFileResult FileSaver::saveFile(const QFileInfo &fileInfo)
 | 
			
		||||
                pageData = processor->process(Utils::readFile(absPath));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch(QSSGeneralException &e)
 | 
			
		||||
        catch(LooqsGeneralException &e)
 | 
			
		||||
        {
 | 
			
		||||
            Logger::error() << "Error while processing" << absPath << ":" << e.message << endl;
 | 
			
		||||
            return PROCESSFAIL;
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	{
 | 
			
		||||
		Common::ensureConfigured();
 | 
			
		||||
	}
 | 
			
		||||
	catch(QSSGeneralException &e)
 | 
			
		||||
	catch(LooqsGeneralException &e)
 | 
			
		||||
	{
 | 
			
		||||
		Logger::error() << "Error: " << e.message;
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -86,7 +86,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
		{
 | 
			
		||||
			return cmd->handle(args);
 | 
			
		||||
		}
 | 
			
		||||
		catch(const QSSGeneralException &e)
 | 
			
		||||
		catch(const LooqsGeneralException &e)
 | 
			
		||||
		{
 | 
			
		||||
			Logger::error() << "Exception caught, message: " << e.message << endl;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
QVector<PageData> OdtProcessor::process(const QByteArray &data) const
 | 
			
		||||
{
 | 
			
		||||
    throw QSSGeneralException("Not implemented yet");
 | 
			
		||||
    throw LooqsGeneralException("Not implemented yet");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVector<PageData> OdtProcessor::process(QString path) const
 | 
			
		||||
@@ -15,12 +15,12 @@ QVector<PageData> OdtProcessor::process(QString path) const
 | 
			
		||||
    zipFile.setFileName("content.xml");
 | 
			
		||||
    if(!zipFile.open(QIODevice::ReadOnly))
 | 
			
		||||
    {
 | 
			
		||||
       throw QSSGeneralException("Error while opening file " + path);
 | 
			
		||||
       throw LooqsGeneralException("Error while opening file " + path);
 | 
			
		||||
    }
 | 
			
		||||
    QByteArray entireContent = zipFile.readAll();
 | 
			
		||||
    if(entireContent.isEmpty())
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Error while reading content.xml of " + path);
 | 
			
		||||
        throw LooqsGeneralException("Error while reading content.xml of " + path);
 | 
			
		||||
    }
 | 
			
		||||
    TagStripperProcessor tsp;
 | 
			
		||||
    return tsp.process(entireContent);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,11 @@ QVector<PageData> PdfProcessor::process(const QByteArray &data) const
 | 
			
		||||
    QScopedPointer<Poppler::Document> doc(Poppler::Document::loadFromData(data));
 | 
			
		||||
    if(doc.isNull())
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Failed to process pdf data");
 | 
			
		||||
        throw LooqsGeneralException("Failed to process pdf data");
 | 
			
		||||
    }
 | 
			
		||||
    if(doc->isLocked())
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Doc is locked");
 | 
			
		||||
        throw LooqsGeneralException("Doc is locked");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QRectF entirePage;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ bool SqliteDbService::fileExistsInDatabase(QString path, qint64 mtime)
 | 
			
		||||
    query.addBindValue(path);
 | 
			
		||||
    query.addBindValue(mtime);
 | 
			
		||||
    if(!query.exec())
 | 
			
		||||
    {        throw QSSGeneralException("Error while trying to query for file existance: " + query.lastError().text());
 | 
			
		||||
    {        throw LooqsGeneralException("Error while trying to query for file existance: " + query.lastError().text());
 | 
			
		||||
    }
 | 
			
		||||
    if(!query.next())
 | 
			
		||||
    {
 | 
			
		||||
@@ -20,7 +20,7 @@ bool SqliteDbService::fileExistsInDatabase(QString path, qint64 mtime)
 | 
			
		||||
    return query.value(0).toBool();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVector<SearchResult> SqliteDbService::search(const QSSQuery &query)
 | 
			
		||||
QVector<SearchResult> SqliteDbService::search(const LooqsQuery &query)
 | 
			
		||||
{
 | 
			
		||||
    auto connection = dbFactory->forCurrentThread();
 | 
			
		||||
    SqliteSearch searcher(connection);
 | 
			
		||||
@@ -33,7 +33,7 @@ bool SqliteDbService::fileExistsInDatabase(QString path)
 | 
			
		||||
    query.prepare("SELECT 1 FROM file WHERE path = ?");
 | 
			
		||||
    query.addBindValue(path);
 | 
			
		||||
    if(!query.exec())
 | 
			
		||||
    {        throw QSSGeneralException("Error while trying to query for file existance: " + query.lastError().text());
 | 
			
		||||
    {        throw LooqsGeneralException("Error while trying to query for file existance: " + query.lastError().text());
 | 
			
		||||
    }
 | 
			
		||||
    if(!query.next())
 | 
			
		||||
    {
 | 
			
		||||
@@ -82,7 +82,7 @@ int SqliteDbService::getFiles(QVector<FileData> &results, QString wildCardPatter
 | 
			
		||||
    query.setForwardOnly(true);
 | 
			
		||||
    if(!query.exec())
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Error while trying to retrieve files from database: " + query.lastError().text());
 | 
			
		||||
        throw LooqsGeneralException("Error while trying to retrieve files from database: " + query.lastError().text());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //TODO: port this to QRegularExpression once >5.12 gets more widespread because of this bug
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ public:
 | 
			
		||||
    bool deleteFile(QString path);
 | 
			
		||||
    bool fileExistsInDatabase(QString path);
 | 
			
		||||
    bool fileExistsInDatabase(QString path, qint64 mtime);
 | 
			
		||||
    QVector<SearchResult> search(const QSSQuery &query);
 | 
			
		||||
    QVector<SearchResult> search(const LooqsQuery &query);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,12 @@ QByteArray Utils::readFile(QString path)
 | 
			
		||||
    QFile file(path);
 | 
			
		||||
    if(!file.open(QIODevice::ReadOnly))
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Failed to open file: " + path);
 | 
			
		||||
        throw LooqsGeneralException("Failed to open file: " + path);
 | 
			
		||||
    }
 | 
			
		||||
    QByteArray data = file.readAll();
 | 
			
		||||
    if(data.isEmpty() && file.error() != QFileDevice::FileError::NoError)
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Error reading file: " + path + ", Error: " + file.error());
 | 
			
		||||
        throw LooqsGeneralException("Error reading file: " + path + ", Error: " + file.error());
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
 | 
			
		||||
class Utils
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ QT       += core concurrent gui
 | 
			
		||||
 | 
			
		||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 | 
			
		||||
CONFIG += c++17
 | 
			
		||||
TARGET = qss-gui
 | 
			
		||||
TARGET = looqs-gui
 | 
			
		||||
TEMPLATE = app
 | 
			
		||||
 | 
			
		||||
# The following define makes your compiler emit warnings if you use
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	{
 | 
			
		||||
		Common::ensureConfigured();
 | 
			
		||||
	}
 | 
			
		||||
	catch(QSSGeneralException &e)
 | 
			
		||||
	catch(LooqsGeneralException &e)
 | 
			
		||||
	{
 | 
			
		||||
		qDebug() << e.message;
 | 
			
		||||
		QMessageBox::critical(nullptr, "Error", e.message);
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
#include "ui_mainwindow.h"
 | 
			
		||||
#include "clicklabel.h"
 | 
			
		||||
#include "../shared/sqlitesearch.h"
 | 
			
		||||
#include "../shared/qssgeneralexception.h"
 | 
			
		||||
#include "../shared/looqsgeneralexception.h"
 | 
			
		||||
#include "../shared/common.h"
 | 
			
		||||
 | 
			
		||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
 | 
			
		||||
@@ -52,7 +52,7 @@ void MainWindow::connectSignals()
 | 
			
		||||
			auto results = searchWatcher.future().result();
 | 
			
		||||
			handleSearchResults(results);
 | 
			
		||||
		}
 | 
			
		||||
		catch(QSSGeneralException &e)
 | 
			
		||||
		catch(LooqsGeneralException &e)
 | 
			
		||||
		{
 | 
			
		||||
			handleSearchError(e.message);
 | 
			
		||||
		}
 | 
			
		||||
@@ -170,7 +170,7 @@ void MainWindow::pdfPreviewReceived(PdfPreview preview)
 | 
			
		||||
void MainWindow::lineEditReturnPressed()
 | 
			
		||||
{
 | 
			
		||||
	QString q = ui->txtSearch->text();
 | 
			
		||||
	if(!QSSQuery::checkParanthesis(q))
 | 
			
		||||
	if(!LooqsQuery::checkParanthesis(q))
 | 
			
		||||
	{
 | 
			
		||||
		ui->lblSearchResults->setText("Invalid paranthesis");
 | 
			
		||||
		return;
 | 
			
		||||
@@ -180,7 +180,7 @@ void MainWindow::lineEditReturnPressed()
 | 
			
		||||
	this->ui->txtSearch->setEnabled(false);
 | 
			
		||||
	QFuture<QVector<SearchResult>> searchFuture = QtConcurrent::run([&, q]() {
 | 
			
		||||
		SqliteSearch searcher(db);
 | 
			
		||||
		this->currentQuery = QSSQuery::build(q);
 | 
			
		||||
		this->currentQuery = LooqsQuery::build(q);
 | 
			
		||||
		return searcher.search(this->currentQuery);
 | 
			
		||||
	});
 | 
			
		||||
	searchWatcher.setFuture(searchFuture);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
#include <QFutureWatcher>
 | 
			
		||||
#include <QSqlDatabase>
 | 
			
		||||
#include "pdfworker.h"
 | 
			
		||||
#include "../shared/qssquery.h"
 | 
			
		||||
#include "../shared/looqsquery.h"
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class MainWindow;
 | 
			
		||||
}
 | 
			
		||||
@@ -40,7 +40,7 @@ private:
 | 
			
		||||
    unsigned int processedPdfPreviews;
 | 
			
		||||
    void handleSearchResults(const QVector<SearchResult> &results);
 | 
			
		||||
    void handleSearchError(QString error);
 | 
			
		||||
    QSSQuery currentQuery;
 | 
			
		||||
    LooqsQuery currentQuery;
 | 
			
		||||
	int pdfPreviewsPerPage;
 | 
			
		||||
	void createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo);
 | 
			
		||||
private slots:
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
#include <QSqlError>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#define SETTINGS_KEY_DBPATH "dbpath"
 | 
			
		||||
@@ -64,13 +64,13 @@ void Common::ensureConfigured()
 | 
			
		||||
		{
 | 
			
		||||
			if(!dir.mkpath(dbpath))
 | 
			
		||||
			{
 | 
			
		||||
				throw QSSGeneralException("Failed to create dbpath directory");
 | 
			
		||||
				throw LooqsGeneralException("Failed to create dbpath directory");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		dbpath += "/qss.sqlite";
 | 
			
		||||
		dbpath += "/looqs.sqlite";
 | 
			
		||||
		if(!initSqliteDatabase(dbpath))
 | 
			
		||||
		{
 | 
			
		||||
			throw QSSGeneralException("Failed to initialize sqlite database");
 | 
			
		||||
			throw LooqsGeneralException("Failed to initialize sqlite database");
 | 
			
		||||
		}
 | 
			
		||||
		settings.setValue(SETTINGS_KEY_FIRSTRUN, false);
 | 
			
		||||
		settings.setValue(SETTINGS_KEY_DBPATH, dbpath);
 | 
			
		||||
@@ -81,7 +81,7 @@ void Common::ensureConfigured()
 | 
			
		||||
		QString dbpath = databasePath();
 | 
			
		||||
		if(!QFile::exists(dbpath))
 | 
			
		||||
		{
 | 
			
		||||
			throw QSSGeneralException("Database " + dbpath + " was not found");
 | 
			
		||||
			throw LooqsGeneralException("Database " + dbpath + " was not found");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -90,7 +90,7 @@ void Common::setupAppInfo()
 | 
			
		||||
{
 | 
			
		||||
	QCoreApplication::setOrganizationName("quitesimple.org");
 | 
			
		||||
	QCoreApplication::setOrganizationDomain("quitesimple.org");
 | 
			
		||||
	QCoreApplication::setApplicationName("qss");
 | 
			
		||||
	QCoreApplication::setApplicationName("looqs");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Common::databasePath()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								shared/looqsgeneralexception.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								shared/looqsgeneralexception.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								shared/looqsgeneralexception.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								shared/looqsgeneralexception.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
#ifndef LOOQSGENERALEXCEPTION_H
 | 
			
		||||
#define LOOQSGENERALEXCEPTION_H
 | 
			
		||||
 | 
			
		||||
#include <QException>
 | 
			
		||||
 | 
			
		||||
class LooqsGeneralException : public QException
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    QString message;
 | 
			
		||||
    LooqsGeneralException(QString message) { this->message = message; }
 | 
			
		||||
    void raise() const override { throw *this; }
 | 
			
		||||
    LooqsGeneralException *clone() const override { return new LooqsGeneralException(*this); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // LOOQSGENERALEXCEPTION_H
 | 
			
		||||
@@ -6,30 +6,30 @@
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include "qssquery.h"
 | 
			
		||||
#include "looqsquery.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const QVector<Token> &QSSQuery::getTokens() const
 | 
			
		||||
const QVector<Token> &LooqsQuery::getTokens() const
 | 
			
		||||
{
 | 
			
		||||
    return tokens;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QVector<SortCondition> &QSSQuery::getSortConditions() const
 | 
			
		||||
const QVector<SortCondition> &LooqsQuery::getSortConditions() const
 | 
			
		||||
{
 | 
			
		||||
    return sortConditions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QueryType QSSQuery::getQueryType()
 | 
			
		||||
QueryType LooqsQuery::getQueryType()
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<QueryType>(tokensMask & COMBINED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QSSQuery::addSortCondition(SortCondition sc)
 | 
			
		||||
void LooqsQuery::addSortCondition(SortCondition sc)
 | 
			
		||||
{
 | 
			
		||||
    this->sortConditions.append(sc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QSSQuery::checkParanthesis(QString expression)
 | 
			
		||||
bool LooqsQuery::checkParanthesis(QString expression)
 | 
			
		||||
{
 | 
			
		||||
    QStack<QChar> open;
 | 
			
		||||
    QStack<QChar> close;
 | 
			
		||||
@@ -105,7 +105,7 @@ QVector<SortCondition> createSortConditions(QString sortExpression)
 | 
			
		||||
            QStringList splitted = splitted_inner[i].split(" ");
 | 
			
		||||
            if(splitted.length() < 1 || splitted.length() > 2)
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("sort specifier must have format [field] (asc|desc)");
 | 
			
		||||
                throw LooqsGeneralException("sort specifier must have format [field] (asc|desc)");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +113,7 @@ QVector<SortCondition> createSortConditions(QString sortExpression)
 | 
			
		||||
            auto queryField = fromString(field);
 | 
			
		||||
            if(!queryField)
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("Unknown sort field supplied");
 | 
			
		||||
                throw LooqsGeneralException("Unknown sort field supplied");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SortOrder order;
 | 
			
		||||
@@ -130,7 +130,7 @@ QVector<SortCondition> createSortConditions(QString sortExpression)
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    throw QSSGeneralException("Unknown order specifier: " + order);
 | 
			
		||||
                    throw LooqsGeneralException("Unknown order specifier: " + order);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
@@ -152,7 +152,7 @@ QVector<SortCondition> createSortConditions(QString sortExpression)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void QSSQuery::addToken(Token t)
 | 
			
		||||
void LooqsQuery::addToken(Token t)
 | 
			
		||||
{
 | 
			
		||||
    tokens.append(t);
 | 
			
		||||
    tokensMask |= t.type;
 | 
			
		||||
@@ -164,14 +164,14 @@ void QSSQuery::addToken(Token t)
 | 
			
		||||
 * thus, "Downloads zip" becomes essentailly "path.contains:(Downloads) AND path.contains:(zip)"
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: It's a bit ugly still*/
 | 
			
		||||
QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
LooqsQuery LooqsQuery::build(QString expression)
 | 
			
		||||
{
 | 
			
		||||
    if(!checkParanthesis(expression))
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("Invalid paranthesis");
 | 
			
		||||
        throw LooqsGeneralException("Invalid paranthesis");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QSSQuery result;
 | 
			
		||||
	LooqsQuery result;
 | 
			
		||||
    //TODO: merge lonewords
 | 
			
		||||
    QRegularExpression rx("((?<filtername>(\\.|\\w)+):(?<args>\\((?<innerargs>[^\\)]+)\\)|([\\w,])+)|(?<boolean>AND|OR)|(?<negation>!)|(?<bracket>\\(|\\))|(?<loneword>\\w+))");
 | 
			
		||||
    QRegularExpressionMatchIterator i = rx.globalMatch(expression);
 | 
			
		||||
@@ -191,11 +191,11 @@ QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
        {
 | 
			
		||||
            if(previousWasBool())
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("Can't have two booleans following each other");
 | 
			
		||||
                throw LooqsGeneralException("Can't have two booleans following each other");
 | 
			
		||||
            }
 | 
			
		||||
            if(previousWas(NEGATION))
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("Can't have a negation preceeding a boolean");
 | 
			
		||||
                throw LooqsGeneralException("Can't have a negation preceeding a boolean");
 | 
			
		||||
            }
 | 
			
		||||
            if(boolean == "AND")
 | 
			
		||||
            {
 | 
			
		||||
@@ -210,7 +210,7 @@ QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
        {
 | 
			
		||||
            if(previousWas(NEGATION))
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("Can't have two negations following each other");
 | 
			
		||||
                throw LooqsGeneralException("Can't have two negations following each other");
 | 
			
		||||
            }
 | 
			
		||||
            if(!previousWasBool())
 | 
			
		||||
            {
 | 
			
		||||
@@ -279,7 +279,7 @@ QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
            {
 | 
			
		||||
                if(!result.sortConditions.empty())
 | 
			
		||||
                {
 | 
			
		||||
                    throw QSSGeneralException("Two sort statements are illegal");
 | 
			
		||||
                    throw LooqsGeneralException("Two sort statements are illegal");
 | 
			
		||||
                }
 | 
			
		||||
				//TODO: hack, since we are not a "filter", we must remove a preceeding (implicit) boolean
 | 
			
		||||
				if(result.tokens.last().type & BOOL == BOOL)
 | 
			
		||||
@@ -291,7 +291,7 @@ QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                throw QSSGeneralException("Unknown filter provided!");
 | 
			
		||||
                throw LooqsGeneralException("Unknown filter provided!");
 | 
			
		||||
            }
 | 
			
		||||
            result.addToken(Token(tokenType, value));
 | 
			
		||||
        }
 | 
			
		||||
@@ -303,7 +303,7 @@ QSSQuery QSSQuery::build(QString expression)
 | 
			
		||||
 | 
			
		||||
    if(!contentsearch && sortsForContent)
 | 
			
		||||
    {
 | 
			
		||||
        throw QSSGeneralException("We cannot sort by text if we don't search for it");
 | 
			
		||||
        throw LooqsGeneralException("We cannot sort by text if we don't search for it");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
#ifndef QSSQUERY_H
 | 
			
		||||
#define QSSQUERY_H
 | 
			
		||||
#ifndef LOOQSQUERY_H
 | 
			
		||||
#define LOOQSQUERY_H
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QVector>
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
/* Fields that can be queried or sorted */
 | 
			
		||||
enum QueryField
 | 
			
		||||
@@ -34,7 +34,7 @@ enum QueryType
 | 
			
		||||
    COMBINED = PATH_ONLY | CONTENT_ONLY
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QSSQuery
 | 
			
		||||
class LooqsQuery
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    /* Helper field to determine quertype as well as to quickly check what kind of filters etc.
 | 
			
		||||
@@ -50,7 +50,7 @@ public:
 | 
			
		||||
    int getTokensMask() const { return tokensMask; }
 | 
			
		||||
    void addSortCondition(SortCondition sc);
 | 
			
		||||
    static bool checkParanthesis(QString query);
 | 
			
		||||
    static QSSQuery build(QString query);
 | 
			
		||||
    static LooqsQuery build(QString query);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
@@ -58,4 +58,4 @@ public:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // QSSQUERY_H
 | 
			
		||||
#endif // LOOQSQUERY_H
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
#ifndef QSSGENERALEXCEPTION_H
 | 
			
		||||
#define QSSGENERALEXCEPTION_H
 | 
			
		||||
 | 
			
		||||
#include <QException>
 | 
			
		||||
 | 
			
		||||
class QSSGeneralException : public QException
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    QString message;
 | 
			
		||||
    QSSGeneralException(QString message) { this->message = message; }
 | 
			
		||||
    void raise() const override { throw *this; }
 | 
			
		||||
    QSSGeneralException *clone() const override { return new QSSGeneralException(*this); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QSSGENERALEXCEPTION_H
 | 
			
		||||
@@ -25,16 +25,16 @@ DEFINES += QT_DEPRECATED_WARNINGS
 | 
			
		||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 | 
			
		||||
 | 
			
		||||
SOURCES += sqlitesearch.cpp \
 | 
			
		||||
    qssgeneralexception.cpp \
 | 
			
		||||
    qssquery.cpp \
 | 
			
		||||
    common.cpp
 | 
			
		||||
    looqsgeneralexception.cpp \
 | 
			
		||||
    common.cpp \
 | 
			
		||||
    looqsquery.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += sqlitesearch.h \
 | 
			
		||||
    filedata.h \
 | 
			
		||||
    looqsgeneralexception.h \
 | 
			
		||||
    looqsquery.h \
 | 
			
		||||
    searchresult.h \
 | 
			
		||||
    qssgeneralexception.h \
 | 
			
		||||
    token.h \
 | 
			
		||||
    qssquery.h \
 | 
			
		||||
    common.h
 | 
			
		||||
unix {
 | 
			
		||||
    target.path = /usr/lib
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include "sqlitesearch.h"
 | 
			
		||||
#include "qssgeneralexception.h"
 | 
			
		||||
#include "looqsgeneralexception.h"
 | 
			
		||||
 | 
			
		||||
SqliteSearch::SqliteSearch(QSqlDatabase &db)
 | 
			
		||||
{
 | 
			
		||||
@@ -46,7 +46,7 @@ QString SqliteSearch::createSortSql(const QVector<SortCondition> sortConditions)
 | 
			
		||||
		QString field = fieldToColumn(sc.field);
 | 
			
		||||
		if(field == "")
 | 
			
		||||
		{
 | 
			
		||||
			throw QSSGeneralException("Unknown sort field supplied");
 | 
			
		||||
			throw LooqsGeneralException("Unknown sort field supplied");
 | 
			
		||||
		}
 | 
			
		||||
		if(sc.order == DESC)
 | 
			
		||||
		{
 | 
			
		||||
@@ -119,10 +119,10 @@ QPair<QString, QVector<QString>> SqliteSearch::createSql(const Token &token)
 | 
			
		||||
				"rank) ",
 | 
			
		||||
				{value}};
 | 
			
		||||
	}
 | 
			
		||||
	throw QSSGeneralException("Unknown token passed (should not happen)");
 | 
			
		||||
	throw LooqsGeneralException("Unknown token passed (should not happen)");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QSqlQuery SqliteSearch::makeSqlQuery(const QSSQuery &query)
 | 
			
		||||
QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
 | 
			
		||||
{
 | 
			
		||||
	QString whereSql;
 | 
			
		||||
	QString joinSql;
 | 
			
		||||
@@ -130,7 +130,7 @@ QSqlQuery SqliteSearch::makeSqlQuery(const QSSQuery &query)
 | 
			
		||||
	bool isContentSearch = query.getTokensMask() & FILTER_CONTENT == FILTER_CONTENT;
 | 
			
		||||
	if(query.getTokens().isEmpty())
 | 
			
		||||
	{
 | 
			
		||||
		throw QSSGeneralException("Nothing to search for supplied");
 | 
			
		||||
		throw LooqsGeneralException("Nothing to search for supplied");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for(const Token &token : query.getTokens())
 | 
			
		||||
@@ -185,7 +185,7 @@ QSqlQuery SqliteSearch::makeSqlQuery(const QSSQuery &query)
 | 
			
		||||
	return dbquery;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVector<SearchResult> SqliteSearch::search(const QSSQuery &query)
 | 
			
		||||
QVector<SearchResult> SqliteSearch::search(const LooqsQuery &query)
 | 
			
		||||
{
 | 
			
		||||
	QVector<SearchResult> results;
 | 
			
		||||
	QSqlQuery dbQuery = makeSqlQuery(query);
 | 
			
		||||
@@ -195,7 +195,7 @@ QVector<SearchResult> SqliteSearch::search(const QSSQuery &query)
 | 
			
		||||
 | 
			
		||||
		qDebug() << dbQuery.lastError();
 | 
			
		||||
		qDebug() << dbQuery.executedQuery();
 | 
			
		||||
		throw QSSGeneralException("SQL Error: " + dbQuery.lastError().text());
 | 
			
		||||
		throw LooqsGeneralException("SQL Error: " + dbQuery.lastError().text());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while(dbQuery.next())
 | 
			
		||||
 
 | 
			
		||||
@@ -4,17 +4,17 @@
 | 
			
		||||
#include <QPair>
 | 
			
		||||
#include "searchresult.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "../shared/qssquery.h"
 | 
			
		||||
#include "../shared/looqsquery.h"
 | 
			
		||||
class SqliteSearch
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    SqliteSearch(QSqlDatabase &db);
 | 
			
		||||
    QVector<SearchResult> search(const QSSQuery &query);
 | 
			
		||||
    QVector<SearchResult> search(const LooqsQuery &query);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QSqlDatabase *db;
 | 
			
		||||
    QSqlQuery makeSqlQuery(const QSSQuery &query);
 | 
			
		||||
    QSqlQuery makeSqlQuery(const LooqsQuery &query);
 | 
			
		||||
    QString fieldToColumn(QueryField field);
 | 
			
		||||
    QPair<QString, QVector<QString> > createSql(const Token &token);
 | 
			
		||||
    QString createSortSql(const QVector<SortCondition> sortConditions);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user