From 6b94b8f61952f8954a62c00c00a75c27dbbb2139 Mon Sep 17 00:00:00 2001 From: Albert S Date: Sat, 20 Apr 2019 23:31:14 +0200 Subject: [PATCH] Begin 'shared' project to share code between cli and gui --- cli/cli.pro | 21 +++++- cli/commandsearch.cpp | 1 + cli/commandsearch.h | 20 +++++ cli/main.cpp | 3 + gui/gui.pro | 13 +++- qss.pro | 4 +- shared/shared.pro | 32 ++++++++ shared/sqlitesearch.cpp | 158 ++++++++++++++++++++++++++++++++++++++++ shared/sqlitesearch.h | 33 +++++++++ 9 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 cli/commandsearch.cpp create mode 100644 cli/commandsearch.h create mode 100644 shared/shared.pro create mode 100644 shared/sqlitesearch.cpp create mode 100644 shared/sqlitesearch.h diff --git a/cli/cli.pro b/cli/cli.pro index d87e4a8..ffe02d1 100644 --- a/cli/cli.pro +++ b/cli/cli.pro @@ -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 diff --git a/cli/commandsearch.cpp b/cli/commandsearch.cpp new file mode 100644 index 0000000..ec68155 --- /dev/null +++ b/cli/commandsearch.cpp @@ -0,0 +1 @@ +#include "commandsearch.h" diff --git a/cli/commandsearch.h b/cli/commandsearch.h new file mode 100644 index 0000000..f47192b --- /dev/null +++ b/cli/commandsearch.h @@ -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 diff --git a/cli/main.cpp b/cli/main.cpp index 608c304..0a4e723 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -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,7 +44,9 @@ Command *commandFromName(QString name, SqliteDbService &dbService) } if(name == "search") { + return new CommandSearch(dbService); } + return nullptr; } diff --git a/gui/gui.pro b/gui/gui.pro index fad1970..7117d01 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -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 diff --git a/qss.pro b/qss.pro index ab544dd..a1724ff 100644 --- a/qss.pro +++ b/qss.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = gui cli +SUBDIRS = gui cli \ + shared + diff --git a/shared/shared.pro b/shared/shared.pro new file mode 100644 index 0000000..61ac80f --- /dev/null +++ b/shared/shared.pro @@ -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 +} diff --git a/shared/sqlitesearch.cpp b/shared/sqlitesearch.cpp new file mode 100644 index 0000000..1318b97 --- /dev/null +++ b/shared/sqlitesearch.cpp @@ -0,0 +1,158 @@ +#include +#include + +#include "sqlitesearch.h" + +SqliteSearch::SqliteSearch() +{ +} + +QVector SqliteSearch::tokenize(QString expression) +{ + if(!checkParanthesis(expression)) + { + throw std::invalid_argument("Invalid paranthesis"); + } + // TODO: merge lonewords + QVector result; + QRegularExpression rx("((?(\\.|\\w)+):(?\\((?[^\\)]+)\\)|(\\w)+)|(?AND|OR|!)|" + "(?\\(|\\))|(?\\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 &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 open; + QStack 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; +} diff --git a/shared/sqlitesearch.h b/shared/sqlitesearch.h new file mode 100644 index 0000000..f0d294d --- /dev/null +++ b/shared/sqlitesearch.h @@ -0,0 +1,33 @@ +#ifndef SQLITESEARCH_H +#define SQLITESEARCH_H +#include + +class SqliteSearch +{ + class Token + { + public: + QString key; + QString value; + + Token(QString key = "", QString value = "") + { + this->key = key; + this->value = value; + } + }; + + private: + QSqlDatabase *db; + QVector tokenize(QString expression); + QString createSql(const Token &token); + QString makeSql(const QVector &tokens); + bool checkParanthesis(QString expression); + + public: + SqliteSearch(); + SqliteSearch(QSqlDatabase &db); + void search(const QString &query); +}; + +#endif // SQLITESEARCH_H