Begin 'shared' project to share code between cli and gui

This commit is contained in:
Albert S. 2019-04-20 23:31:14 +02:00
parent f461d2c844
commit c928c94eb1
9 changed files with 290 additions and 5 deletions

View File

@ -32,7 +32,8 @@ SOURCES += \
filesaver.cpp \
databasefactory.cpp \
sqlitedbservice.cpp \
logger.cpp
logger.cpp \
commandsearch.cpp
HEADERS += \
encodingdetector.h \
@ -54,5 +55,21 @@ HEADERS += \
filedata.h \
databasefactory.h \
sqlitedbservice.h \
logger.h
logger.h \
commandsearch.h
INCLUDEPATH += /usr/include/poppler/qt5/ /usr/include/quazip5
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../shared/release/ -lshared
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../shared/debug/ -lshared
else:unix: LIBS += -L$$OUT_PWD/../shared/ -lshared
INCLUDEPATH += $$PWD/../shared
DEPENDPATH += $$PWD/../shared
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/release/libshared.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/libshared.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/release/shared.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/shared.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../shared/libshared.a

3
cli/commandsearch.cpp Normal file
View File

@ -0,0 +1,3 @@
#include "commandsearch.h"

20
cli/commandsearch.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef COMMANDSEARCH_H
#define COMMANDSEARCH_H
#include "command.h"
#include "../shared/sqlitesearch.h"
class CommandSearch : public Command
{
private:
SqliteSearch searcher;
public:
using Command::Command;
int handle(QStringList arguments) override
{
return 23;
}
};
#endif // COMMANDSEARCH_H

View File

@ -20,6 +20,7 @@
#include "commandadd.h"
#include "commanddelete.h"
#include "commandupdate.h"
#include "commandsearch.h"
#include "databasefactory.h"
#include "logger.h"
void printUsage(QString argv0)
@ -43,8 +44,9 @@ Command *commandFromName(QString name, SqliteDbService &dbService)
}
if(name == "search")
{
return new CommandSearch(dbService);
}
return nullptr;
}

View File

@ -22,7 +22,6 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
@ -47,3 +46,15 @@ INCLUDEPATH += /usr/include/poppler/qt5/
LIBS += -lpoppler-qt5
QT += widgets sql
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../shared/release/ -lshared
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../shared/debug/ -lshared
else:unix: LIBS += -L$$OUT_PWD/../shared/ -lshared
INCLUDEPATH += $$PWD/../shared
DEPENDPATH += $$PWD/../shared
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/release/libshared.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/libshared.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/release/shared.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/shared.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../shared/libshared.a

View File

@ -1,2 +1,4 @@
TEMPLATE = subdirs
SUBDIRS = gui cli
SUBDIRS = gui cli \
shared

32
shared/shared.pro Normal file
View File

@ -0,0 +1,32 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-04-20T23:00:36
#
#-------------------------------------------------
QT += sql
QT -= gui
TARGET = shared
TEMPLATE = lib
CONFIG += staticlib
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += sqlitesearch.cpp
HEADERS += sqlitesearch.h
unix {
target.path = /usr/lib
INSTALLS += target
}

162
shared/sqlitesearch.cpp Normal file
View File

@ -0,0 +1,162 @@
#include <QStack>
#include <QRegularExpression>
#include "sqlitesearch.h"
SqliteSearch::SqliteSearch()
{
}
QVector<SqliteSearch::Token> SqliteSearch::tokenize(QString expression)
{
if(!checkParanthesis(expression))
{
throw std::invalid_argument("Invalid paranthesis");
}
//TODO: merge lonewords
QVector<SqliteSearch::Token> result;
QRegularExpression rx("((?<filtername>(\\.|\\w)+):(?<args>\\((?<innerargs>[^\\)]+)\\)|(\\w)+)|(?<boolean>AND|OR|!)|(?<bracket>\\(|\\))|(?<loneword>\\w+))");
QRegularExpressionMatchIterator i = rx.globalMatch(expression);
bool wasbool = true;
while(i.hasNext())
{
QRegularExpressionMatch m = i.next();
QString boolean = m.captured("boolean");
QString filtername = m.captured("filtername");
QString bracket = m.captured("bracket");
QString loneword = m.captured("loneword");
if(boolean != "")
{
wasbool = true;
result.append(Token(boolean));
}
if(bracket != "")
{
if(!wasbool)
{
if(bracket == "(")
{
result.append(Token("AND"));
}
}
result.append(Token(bracket));
}
if(loneword != "")
{
if(!wasbool)
{
result.append(Token("AND"));
}
wasbool = false;
result.append(Token("path.contains", loneword));
}
if(filtername != "")
{
if(!wasbool)
{
result.append(Token("AND"));
}
wasbool = false;
QString value = m.captured("innerargs");
if(value == "")
{
value = m.captured("args");
}
result.append(Token(filtername, value));
}
}
return result;
}
QString SqliteSearch::createSql(const SqliteSearch::Token &token)
{
QString key = token.key;
QString value = token.value;
value = value.replace("'", "\\'");
if(key == "AND" || key == "OR" || key == "(" || key == ")")
{
return " " + key + " ";
}
if(key == "!")
{
return " NOT ";
}
if(key == "path.starts")
{
return " file.path LIKE '" + value + "%' ";
}
if(key == "path.ends")
{
return " file.path LIKE '%" + value + "' ";
}
if(key == "path.contains" || key == "inpath")
{
return " file.path LIKE '%" + value + "%' ";
}
if(key == "page")
{
return " content.page = " + value;
}
if(key == "contains" || key == "c")
{
return " content.id IN (SELECT content_fts.ROWID FROM content_fts WHERE content_fts.content MATCH '" + value + "' )";
}
throw std::invalid_argument("Unknown filter: " + key.toStdString());
}
QString SqliteSearch::makeSql(const QVector<SqliteSearch::Token> &tokens)
{
QString result;
for(const Token &c : tokens)
{
result += createSql(c);
}
return result;
}
void SqliteSearch::search(const QString &query)
{
}
bool SqliteSearch::checkParanthesis(QString expression)
{
QStack<QChar> open;
QStack<QChar> close;
for(QChar &c : expression)
{
if(c == '(')
{
open.push(c);
}
if(c == ')')
{
close.push(c);
}
}
if(open.size() != close.size())
{
return false;
}
while(!open.empty() && !close.empty())
{
QChar o = open.pop();
QChar c = close.pop();
if(o != '(' && c != ')' )
{
return false;
}
}
return true;
}

36
shared/sqlitesearch.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef SQLITESEARCH_H
#define SQLITESEARCH_H
#include <QSqlDatabase>
class SqliteSearch
{
class Token
{
public:
QString key;
QString value;
Token(QString key="", QString value="")
{
this->key = key;
this->value = value;
}
};
private:
QSqlDatabase *db;
QVector<SqliteSearch::Token> tokenize(QString expression);
QString createSql(const Token &token);
QString makeSql(const QVector<Token> &tokens);
bool checkParanthesis(QString expression);
public:
SqliteSearch();
SqliteSearch(QSqlDatabase &db);
void search(const QString &query);
};
#endif // SQLITESEARCH_H