diff --git a/QtClient/JoplinQtClient/JoplinQtClient.pro b/QtClient/JoplinQtClient/JoplinQtClient.pro index 57ed8034b6..882d9e70f0 100755 --- a/QtClient/JoplinQtClient/JoplinQtClient.pro +++ b/QtClient/JoplinQtClient/JoplinQtClient.pro @@ -45,7 +45,8 @@ SOURCES += \ window.cpp \ filters.cpp \ models/abstractlistmodel.cpp \ - cliapplication.cpp + cliapplication.cpp \ + command.cpp RESOURCES += qml.qrc \ database.qrc @@ -83,7 +84,8 @@ HEADERS += \ window.h \ filters.h \ models/abstractlistmodel.h \ - cliapplication.h + cliapplication.h \ + command.h defined(JOP_FRONT_END_GUI, var) { SOURCES += application.cpp diff --git a/QtClient/JoplinQtClient/JoplinQtClient.pro.user.13661a9 b/QtClient/JoplinQtClient/JoplinQtClient.pro.user.13661a9 new file mode 100644 index 0000000000..0cc2f29be3 --- /dev/null +++ b/QtClient/JoplinQtClient/JoplinQtClient.pro.user.13661a9 @@ -0,0 +1,336 @@ + + + + + + EnvironmentId + {13661a96-7123-4040-a8b0-364538c1219d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.7.1 GCC 64bit + Desktop Qt 5.7.1 GCC 64bit + qt.57.gcc_64_kit + 0 + 0 + 0 + + /home/laurent/src/notes/QtClient/build-JoplinQtClient-Desktop_Qt_5_7_1_GCC_64bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + "JOP_FRONT_END_CLI=1" + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/laurent/src/notes/QtClient/build-JoplinQtClient-Desktop_Qt_5_7_1_GCC_64bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/laurent/src/notes/QtClient/build-JoplinQtClient-Desktop_Qt_5_7_1_GCC_64bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + JoplinQtClient + + Qt4ProjectManager.Qt4RunConfiguration:/home/laurent/src/notes/QtClient/JoplinQtClient/JoplinQtClient.pro + true + + JoplinQtClient.pro + false + + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/QtClient/JoplinQtClient/build.sh b/QtClient/JoplinQtClient/build.sh new file mode 100755 index 0000000000..71a286bee7 --- /dev/null +++ b/QtClient/JoplinQtClient/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +BUILD_DIR=/home/laurent/src/notes/QtClient/build-JoplinQtClient-Desktop_Qt_5_7_1_GCC_64bit-Debug +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" +/opt/Qt/5.7/gcc_64/bin/qmake /home/laurent/src/notes/QtClient/JoplinQtClient/JoplinQtClient.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug JOP_FRONT_END_CLI=1 +/usr/bin/make qmake_all +/usr/bin/make \ No newline at end of file diff --git a/QtClient/JoplinQtClient/cliapplication.cpp b/QtClient/JoplinQtClient/cliapplication.cpp index f2cde06840..3a906076f6 100644 --- a/QtClient/JoplinQtClient/cliapplication.cpp +++ b/QtClient/JoplinQtClient/cliapplication.cpp @@ -6,9 +6,24 @@ #include "paths.h" #include "uuid.h" #include "settings.h" +#include "models/folder.h" + + + + + + + + + +#include + + namespace jop { +StdoutHandler::StdoutHandler() : QTextStream(stdout) {} + CliApplication::CliApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { // This is linked to where the QSettings will be saved. In other words, // if these values are changed, the settings will be reset and saved @@ -33,8 +48,103 @@ CliApplication::CliApplication(int &argc, char **argv) : QCoreApplication(argc, } } +// void CliApplication::processCommand(const Command& command) { +// qDebug() << "Command" << command.name(); +// qDebug() << "Flags" << command.flags(); +// qDebug() << "Args" << command.args(); + +// // if (command == "mkdir") { + +// // //Folder folder; +// // //folder.setValue("title", args[ + +// // } +// } + int CliApplication::exec() { - qDebug() << "exec"; + qDebug() << "==========================================="; + + + + + // QProcess* process = new QProcess(); + // qint64* processId = new qint64(); + // process->startDetached("/usr/bin/vim", QStringList(), QString(), processId); + // while (kill(*processId, 0) == 0) {} + // delete processId; + + + QString command = "help"; + QStringList args = arguments(); + + if (args.size() >= 2) { + command = args[1]; + args.erase(args.begin() + 1); + } + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + + // mkdir "new_folder" + // ls + // ls new_folder + // touch new_folder/new_note + + if (command == "mkdir") { + parser.addPositionalArgument("path", "Folder path."); + } else if (command == "ls") { + parser.addPositionalArgument("path", "Folder path."); + } else if (command == "touch") { + parser.addPositionalArgument("path", "Note path."); + } else { + qDebug().noquote() << parser.helpText(); + return 1; + } + + parser.process(args); + + args = parser.positionalArguments(); + + if (command == "mkdir") { + QString title = args.size() ? args[0] : QString(); + Folder folder; + folder.setValue("title", title); + folder.save(); + } + + if (command == "ls") { + QString path = args.size() ? args[0] : QString(); + if (path == "") { + std::vector> folders = Folder::all(); + for (size_t i = 0; i < folders.size(); i++) { + qDebug().noquote() << folders[i].get()->value("title").toString(); + } + } else { + Folder folder; + bool found = folder.loadByField("", "title", path); + if (found) { + qStdout() << "Found" << path << endl; + } else { + qWarning() << "Not found:" << path; + } + } + } + + if (command == "touch") { + // QString path = args.size() ? args[0] : QString(); + // if (path == "") { + // std::vector> folders = Folder::all(); + // for (size_t i = 0; i < folders.size(); i++) { + // qDebug().noquote() << folders[i].get()->value("title").toString(); + // } + // } else { + // // TODO: Get folder by name + // } + } + + qDebug() << "==========================================="; + return 0; } diff --git a/QtClient/JoplinQtClient/cliapplication.h b/QtClient/JoplinQtClient/cliapplication.h index b275af1f2f..27ca615828 100644 --- a/QtClient/JoplinQtClient/cliapplication.h +++ b/QtClient/JoplinQtClient/cliapplication.h @@ -3,13 +3,29 @@ #include +#include "command.h" + namespace jop { +class StdoutHandler : public QTextStream { + +public: + + StdoutHandler(); + +}; + +inline StdoutHandler& qStdout() { + static StdoutHandler r; + return r; +} + class CliApplication : public QCoreApplication { public: CliApplication(int &argc, char **argv); + void processCommand(const Command &command); int exec(); }; diff --git a/QtClient/JoplinQtClient/command.cpp b/QtClient/JoplinQtClient/command.cpp new file mode 100644 index 0000000000..372dd1d6d8 --- /dev/null +++ b/QtClient/JoplinQtClient/command.cpp @@ -0,0 +1,24 @@ +#include "command.h" + +namespace jop { + +Command::Command(const QStringList &arguments) : name_("help"), args_(arguments) { + args_.removeFirst(); + if (args_.size() >= 1) { + name_ = args_.takeFirst(); + } +} + +QString Command::name() const { + return name_; +} + +std::map Command::flags() const { + return flags_; +} + +QStringList Command::args() const { + return args_; +} + +} diff --git a/QtClient/JoplinQtClient/command.h b/QtClient/JoplinQtClient/command.h new file mode 100644 index 0000000000..378a7340eb --- /dev/null +++ b/QtClient/JoplinQtClient/command.h @@ -0,0 +1,27 @@ +#ifndef COMMAND_H +#define COMMAND_H + +#include + +namespace jop { + +class Command { + +public: + + Command(const QStringList& arguments); + QString name() const; + std::map flags() const; + QStringList args() const; + +private: + + QString name_; + std::map flags_; + QStringList args_; + +}; + +} + +#endif // COMMAND_H diff --git a/QtClient/JoplinQtClient/database.cpp b/QtClient/JoplinQtClient/database.cpp index 54b581fa74..3fccb30b27 100755 --- a/QtClient/JoplinQtClient/database.cpp +++ b/QtClient/JoplinQtClient/database.cpp @@ -4,6 +4,12 @@ using namespace jop; Database::Database() {} +Database::~Database() { + if (db_.open()) { + db_.close(); + } +} + void Database::initialize(const QString &path) { version_ = -1; transactionCount_ = 0; diff --git a/QtClient/JoplinQtClient/database.h b/QtClient/JoplinQtClient/database.h index 6cd6b2ab14..148a14aed4 100755 --- a/QtClient/JoplinQtClient/database.h +++ b/QtClient/JoplinQtClient/database.h @@ -14,6 +14,7 @@ public: enum QueryType { Select, Insert, Update, Delete }; Database(); + ~Database(); void initialize(const QString& path); QSqlDatabase& database(); QSqlQuery buildSqlQuery(Database::QueryType type, const QString& tableName, const QStringList& fields, const VariantVector& values, const QString& whereCondition = ""); diff --git a/QtClient/JoplinQtClient/main.cpp b/QtClient/JoplinQtClient/main.cpp index 8b1518e4c4..b47c974cba 100755 --- a/QtClient/JoplinQtClient/main.cpp +++ b/QtClient/JoplinQtClient/main.cpp @@ -11,9 +11,7 @@ #include "models/foldermodel.h" #include "services/folderservice.h" -using namespace jop; - -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) { #if (!defined(JOP_FRONT_END_GUI) && !defined(JOP_FRONT_END_CLI)) qFatal("Either JOP_FRONT_END_GUI or JOP_FRONT_END_CLI must be defined!"); @@ -26,13 +24,15 @@ int main(int argc, char *argv[]) { #endif #ifdef JOP_FRONT_END_GUI + qDebug() << "Front end: GUI"; QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - Application app(argc, argv); + jop::Application app(argc, argv); #endif #ifdef JOP_FRONT_END_CLI - CliApplication app(argc, argv); + qDebug() << "Front end: CLI"; + jop::CliApplication app(argc, argv); #endif return app.exec(); -} +} \ No newline at end of file diff --git a/QtClient/JoplinQtClient/models/basemodel.cpp b/QtClient/JoplinQtClient/models/basemodel.cpp index f3372bca89..6ce97b8358 100755 --- a/QtClient/JoplinQtClient/models/basemodel.cpp +++ b/QtClient/JoplinQtClient/models/basemodel.cpp @@ -47,6 +47,24 @@ bool BaseModel::load(const QString &id) { return true; } +bool BaseModel::loadByField(const QString& parentId, const QString& field, const QString& fieldValue) { + QSqlQuery q(jop::db().database()); + QString sql = QString("SELECT %1 FROM %2 WHERE %3 = :field_value AND parent_id = :parent_id LIMIT 1") + .arg(BaseModel::tableFieldNames(table()).join(",")) + .arg(BaseModel::tableName(table())) + .arg(field); + q.prepare(sql); + q.bindValue(":parent_id", parentId); + q.bindValue(":field_value", fieldValue); + jop::db().execQuery(q); + q.next(); + if (!jop::db().errorCheck(q)) return false; + if (!q.isValid()) return false; + + loadSqlQuery(q); + return true; +} + bool BaseModel::save(bool trackChanges) { bool isNew = this->isNew(); diff --git a/QtClient/JoplinQtClient/models/basemodel.h b/QtClient/JoplinQtClient/models/basemodel.h index d4b4a0dc1d..401f315265 100755 --- a/QtClient/JoplinQtClient/models/basemodel.h +++ b/QtClient/JoplinQtClient/models/basemodel.h @@ -43,6 +43,7 @@ public: QStringList changedFields() const; static int count(jop::Table table); bool load(const QString& id); + bool loadByField(const QString& parentId, const QString& field, const QString& fieldValue); virtual bool save(bool trackChanges = true); virtual bool dispose(); diff --git a/QtClient/JoplinQtClient/models/folder.h b/QtClient/JoplinQtClient/models/folder.h index 611ccf6dcf..be6883cb67 100755 --- a/QtClient/JoplinQtClient/models/folder.h +++ b/QtClient/JoplinQtClient/models/folder.h @@ -14,7 +14,7 @@ public: Folder(); static int count(); - static std::vector> all(const QString& orderBy); + static std::vector> all(const QString& orderBy = "title"); //Table table() const; bool primaryKeyIsUuid() const; diff --git a/QtClient/JoplinQtClient/schema.sql b/QtClient/JoplinQtClient/schema.sql index 995d462773..95a548930f 100755 --- a/QtClient/JoplinQtClient/schema.sql +++ b/QtClient/JoplinQtClient/schema.sql @@ -1,29 +1,30 @@ CREATE TABLE folders ( id TEXT PRIMARY KEY, - title TEXT, - created_time INT, - updated_time INT + parent_id TEXT NOT NULL DEFAULT "", + title TEXT NOT NULL DEFAULT "", + created_time INT NOT NULL DEFAULT 0, + updated_time INT NOT NULL DEFAULT 0 ); CREATE TABLE notes ( id TEXT PRIMARY KEY, - title TEXT, - body TEXT, - parent_id TEXT, - created_time INT, - updated_time INT, - latitude NUMERIC, - longitude NUMERIC, - altitude NUMERIC, - source TEXT, - author TEXT, - source_url TEXT, - is_todo BOOLEAN, - todo_due INT, - todo_completed INT, - source_application TEXT, - application_data TEXT, - `order` INT + parent_id TEXT NOT NULL DEFAULT "", + title TEXT NOT NULL DEFAULT "", + body TEXT NOT NULL DEFAULT "", + created_time INT NOT NULL DEFAULT 0, + updated_time INT NOT NULL DEFAULT 0, + latitude NUMERIC NOT NULL DEFAULT 0, + longitude NUMERIC NOT NULL DEFAULT 0, + altitude NUMERIC NOT NULL DEFAULT 0, + source TEXT NOT NULL DEFAULT "", + author TEXT NOT NULL DEFAULT "", + source_url TEXT NOT NULL DEFAULT "", + is_todo BOOLEAN NOT NULL DEFAULT 0, + todo_due INT NOT NULL DEFAULT 0, + todo_completed INT NOT NULL DEFAULT 0, + source_application TEXT NOT NULL DEFAULT "", + application_data TEXT NOT NULL DEFAULT "", + `order` INT NOT NULL DEFAULT 0 ); CREATE TABLE tags ( diff --git a/QtClient/JoplinQtClient/stable.h b/QtClient/JoplinQtClient/stable.h index c0886ad2e0..c9cf9e04a2 100755 --- a/QtClient/JoplinQtClient/stable.h +++ b/QtClient/JoplinQtClient/stable.h @@ -33,6 +33,8 @@ #include #include #include +#include +#include #endif // __cplusplus diff --git a/joplin.sublime-project b/joplin.sublime-project index 2bc6fcdb5b..eb3efb2419 100755 --- a/joplin.sublime-project +++ b/joplin.sublime-project @@ -13,6 +13,10 @@ { "name": "Build evernote-import", "shell_cmd": "D:\\Programmes\\cygwin\\bin\\bash.exe --login D:\\Web\\www\\joplin\\QtClient\\evernote-import\\build.sh" + }, + { + "name": "Build QtClient CLI - Linux", + "shell_cmd": "/home/laurent/src/notes/QtClient/JoplinQtClient/build.sh" } ] }