diff --git a/.gitignore b/.gitignore index 30f5bca5a..81c9c7307 100755 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ database.sqlite QtClient/build-*-Debug/ *.pro.user -notes.sqlite \ No newline at end of file +notes*.sqlite \ No newline at end of file diff --git a/QtClient/JoplinQtClient/JoplinQtClient.pro b/QtClient/JoplinQtClient/JoplinQtClient.pro index 1a39236c5..c3832d686 100755 --- a/QtClient/JoplinQtClient/JoplinQtClient.pro +++ b/QtClient/JoplinQtClient/JoplinQtClient.pro @@ -18,7 +18,8 @@ SOURCES += \ services/notecache.cpp \ models/qmlnote.cpp -RESOURCES += qml.qrc +RESOURCES += qml.qrc \ + database.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = diff --git a/QtClient/JoplinQtClient/build.bat b/QtClient/JoplinQtClient/build.bat new file mode 100755 index 000000000..aaaf3a436 --- /dev/null +++ b/QtClient/JoplinQtClient/build.bat @@ -0,0 +1,3 @@ +"C:\Qt\5.7\msvc2015\bin\qmake.exe" D:\Web\www\joplin\QtClient\JoplinQtClient\JoplinQtClient.pro -spec win32-msvc2015 "CONFIG+=debug" "CONFIG+=qml_debug" +"C:\Qt\Tools\QtCreator\bin\jom.exe" qmake_all +"C:\Qt\Tools\QtCreator\bin\jom.exe" \ No newline at end of file diff --git a/QtClient/JoplinQtClient/database.cpp b/QtClient/JoplinQtClient/database.cpp index 9316c4df1..8016e913e 100755 --- a/QtClient/JoplinQtClient/database.cpp +++ b/QtClient/JoplinQtClient/database.cpp @@ -5,7 +5,7 @@ using namespace jop; Database::Database(const QString &path) { version_ = -1; - //QFile::remove(path); + QFile::remove(path); db_ = QSqlDatabase::addDatabase("QSQLITE"); db_.setDatabaseName(path); @@ -16,7 +16,7 @@ Database::Database(const QString &path) { qDebug() << "Database: connection ok"; } - //upgrade(); + upgrade(); } Database::Database() {} @@ -52,6 +52,23 @@ int Database::version() const { return version_; } +QStringList Database::sqlStringToLines(const QString& sql) { + QStringList statements; + QStringList lines = sql.split("\n"); + QString statement; + foreach (QString line, lines) { + line = line.trimmed(); + if (line == "") continue; + if (line.left(2) == "--") continue; + statement += line; + if (line[line.length() - 1] == ';') { + statements.append(statement); + statement = ""; + } + } + return statements; +} + void Database::upgrade() { // INSTRUCTIONS TO UPGRADE THE DATABASE: // @@ -75,19 +92,18 @@ void Database::upgrade() { case 1: - db_.exec("CREATE TABLE version (version INT)"); - db_.exec("INSERT INTO version (version) VALUES (1)"); + QFile f(":/schema.sql"); + if (!f.open(QFile::ReadOnly | QFile::Text)) { + qFatal("Cannot open database schema file"); + return; + } + QTextStream in(&f); + QString schemaSql = in.readAll(); - db_.exec("CREATE TABLE folders (id TEXT PRIMARY KEY, title TEXT, created_time INT)"); - -// for (int i = 1; i < 100; i++) { -// QUuid uuid = QUuid::createUuid(); -// QString title = QString::number(i); -// db_.exec(QString("INSERT INTO folders (id, title, created_time) VALUES (\"%1\", \"%2\", 1481235571)").arg(uuid.toString(), title.repeated(10))); -// } - - //db_.exec("INSERT INTO folders (id, title, created_time) VALUES (\"ed735d55415bee976b771989be8f7005\", \"bbbb\", 1481235571)"); - //db_.exec("INSERT INTO folders (id, title, created_time) VALUES (\"5d41402abc4b2a76b9719d911017c592\", \"cccc\", 1481235571)"); + QStringList lines = sqlStringToLines(schemaSql); + foreach (const QString& line, lines) { + db_.exec(line); + } break; diff --git a/QtClient/JoplinQtClient/database.h b/QtClient/JoplinQtClient/database.h index face1dd91..1461ef11a 100755 --- a/QtClient/JoplinQtClient/database.h +++ b/QtClient/JoplinQtClient/database.h @@ -20,6 +20,7 @@ private: void upgrade(); int version() const; mutable int version_; + QStringList sqlStringToLines(const QString& sql); }; diff --git a/QtClient/JoplinQtClient/database.qrc b/QtClient/JoplinQtClient/database.qrc new file mode 100755 index 000000000..b601fdcb0 --- /dev/null +++ b/QtClient/JoplinQtClient/database.qrc @@ -0,0 +1,5 @@ + + + schema.sql + + diff --git a/QtClient/JoplinQtClient/schema.sql b/QtClient/JoplinQtClient/schema.sql new file mode 100755 index 000000000..7154f4c4c --- /dev/null +++ b/QtClient/JoplinQtClient/schema.sql @@ -0,0 +1,23 @@ +CREATE TABLE folders ( + id INTEGER PRIMARY KEY, + title TEXT, + created_time INT, + updated_time INT, + remote_id TEXT +); + +CREATE TABLE notes ( + id INTEGER PRIMARY KEY, + title TEXT, + body TEXT, + parent_id INT, + created_time INT, + updated_time INT, + remote_id TEXT +); + +CREATE TABLE version ( + version INT +); + +INSERT INTO version (version) VALUES (1); \ No newline at end of file diff --git a/QtClient/JoplinQtClient/stable.h b/QtClient/JoplinQtClient/stable.h index e4491a2c7..afd68b3de 100755 --- a/QtClient/JoplinQtClient/stable.h +++ b/QtClient/JoplinQtClient/stable.h @@ -19,6 +19,7 @@ #include #include #include +#include #endif // __cplusplus diff --git a/QtClient/database.sql b/QtClient/database.sql new file mode 100755 index 000000000..7154f4c4c --- /dev/null +++ b/QtClient/database.sql @@ -0,0 +1,23 @@ +CREATE TABLE folders ( + id INTEGER PRIMARY KEY, + title TEXT, + created_time INT, + updated_time INT, + remote_id TEXT +); + +CREATE TABLE notes ( + id INTEGER PRIMARY KEY, + title TEXT, + body TEXT, + parent_id INT, + created_time INT, + updated_time INT, + remote_id TEXT +); + +CREATE TABLE version ( + version INT +); + +INSERT INTO version (version) VALUES (1); \ No newline at end of file diff --git a/QtClient/dependencies/dll-debug/Qt5Cored.dll b/QtClient/dependencies/dll-debug/Qt5Cored.dll new file mode 100755 index 000000000..0722daf93 Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Cored.dll differ diff --git a/QtClient/dependencies/dll-debug/Qt5Guid.dll b/QtClient/dependencies/dll-debug/Qt5Guid.dll new file mode 100755 index 000000000..02c451d30 Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Guid.dll differ diff --git a/QtClient/dependencies/dll-debug/Qt5Networkd.dll b/QtClient/dependencies/dll-debug/Qt5Networkd.dll new file mode 100755 index 000000000..ec5163d59 Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Networkd.dll differ diff --git a/QtClient/dependencies/dll-debug/Qt5Qmld.dll b/QtClient/dependencies/dll-debug/Qt5Qmld.dll new file mode 100755 index 000000000..a10187e7f Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Qmld.dll differ diff --git a/QtClient/dependencies/dll-debug/Qt5Quickd.dll b/QtClient/dependencies/dll-debug/Qt5Quickd.dll new file mode 100755 index 000000000..ad0022c57 Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Quickd.dll differ diff --git a/QtClient/dependencies/dll-debug/Qt5Sqld.dll b/QtClient/dependencies/dll-debug/Qt5Sqld.dll new file mode 100755 index 000000000..a4862b2c1 Binary files /dev/null and b/QtClient/dependencies/dll-debug/Qt5Sqld.dll differ diff --git a/QtClient/dependencies/dll-debug/ucrtbased.dll b/QtClient/dependencies/dll-debug/ucrtbased.dll new file mode 100755 index 000000000..e8e28e0ee Binary files /dev/null and b/QtClient/dependencies/dll-debug/ucrtbased.dll differ diff --git a/QtClient/evernote-import/build.sh b/QtClient/evernote-import/build.sh new file mode 100755 index 000000000..155e6f36d --- /dev/null +++ b/QtClient/evernote-import/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +"/opt/Qt/5.7/gcc_64/bin/qmake" /home/laurent/src/notes/evernote-import-qt/evernote-import-qt.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug +"/usr/bin/make" qmake_all +make + +echo "=============================================" +./evernote-import-qt \ No newline at end of file diff --git a/QtClient/evernote-import/evernote-import-qt b/QtClient/evernote-import/evernote-import-qt new file mode 100755 index 000000000..390c8dffb Binary files /dev/null and b/QtClient/evernote-import/evernote-import-qt differ diff --git a/QtClient/evernote-import/evernote-import-qt.pro b/QtClient/evernote-import/evernote-import-qt.pro new file mode 100755 index 000000000..fa41b2d05 --- /dev/null +++ b/QtClient/evernote-import/evernote-import-qt.pro @@ -0,0 +1,23 @@ +QT += core sql +QT -= gui + +CONFIG += c++11 + +TARGET = evernote-import-qt +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +SOURCES += main.cpp + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked 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 diff --git a/QtClient/evernote-import/main.cpp b/QtClient/evernote-import/main.cpp new file mode 100755 index 000000000..2742636be --- /dev/null +++ b/QtClient/evernote-import/main.cpp @@ -0,0 +1,256 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct Resource { + QString id; + QString mime; + QString filename; + QByteArray data; + time_t timestamp; + + Resource() : timestamp(0) {} +}; + +struct Note { + int id; + QString title; + QString content; + time_t created; + time_t updated; + QStringList tags; + QString longitude; + QString latitude; + QString altitude; + QString source; + QString author; + QString sourceUrl; + QString reminderOrder; + QString reminderDoneTime; + QString reminderTime; + QString sourceApplication; + QString applicationData; + std::vector resources; + + Note() : created(0), updated(0) {} +}; + +time_t dateStringToTimestamp(const QString& s) { + QDateTime d = QDateTime::fromString(s, "yyyyMMddThhmmssZ"); + d.setTimeSpec(Qt::UTC); + if (!d.isValid()) return 0; + return d.toTime_t(); +} + +void parseAttributes(QXmlStreamReader& reader, Note& note) { + while (reader.readNextStartElement()) { + if (reader.name() == "longitude") { + note.longitude = reader.readElementText(); + } else if (reader.name() == "latitude") { + note.latitude = reader.readElementText(); + } else if (reader.name() == "altitude") { + note.altitude = reader.readElementText(); + } else if (reader.name() == "source") { + note.source = reader.readElementText(); + } else if (reader.name() == "author") { + note.author = reader.readElementText(); + } else if (reader.name() == "source-url") { + note.sourceUrl = reader.readElementText(); + } else if (reader.name() == "source-application") { + note.sourceApplication = reader.readElementText(); + } else if (reader.name() == "reminder-order") { + note.reminderOrder = reader.readElementText(); + } else if (reader.name() == "reminder-time") { + note.reminderTime = reader.readElementText(); + } else if (reader.name() == "reminder-done-time") { + note.reminderDoneTime = reader.readElementText(); + } else if (reader.name() == "application-data") { + note.applicationData = reader.readElementText(); + } else { + qWarning() << "Unsupported element:" << reader.name(); + reader.skipCurrentElement(); + } + } +} + +// +// +// ........... +// ........... +// +// image/png +// 500 +// 326 +// +// +// +// ]]> +// +// +// NoeudDeChaise.png +// +// + +void parseResourceAttributes(QXmlStreamReader& reader, Resource& resource) { + while (reader.readNextStartElement()) { + if (reader.name() == "file-name") { + resource.filename = reader.readElementText(); + } else if (reader.name() == "timestamp") { + resource.timestamp = dateStringToTimestamp(reader.readElementText()); + } else if (reader.name() == "camera-make" || reader.name() == "source-url" || reader.name() == "attachment" || reader.name() == "longitude" || reader.name() == "latitude") { + // Ignore it + reader.skipCurrentElement(); + } else { + qWarning() << "Unsupported element:" << reader.name(); + reader.skipCurrentElement(); + } + } +} + +void parseResourceRecognition(QXmlStreamReader& reader, Resource& resource) { + QString recognitionXml = reader.readElementText(); + + QXmlStreamReader r(recognitionXml.toUtf8()); + + if (r.readNextStartElement()) { + if (r.name() == "recoIndex") { + QString objID; + foreach (const QXmlStreamAttribute &attr, r.attributes()) { + if (attr.name().toString() == "objID") { + objID = attr.value().toString(); + break; + } + } + + resource.id = objID; + + r.skipCurrentElement(); + } else { + qWarning() << "Unsupported element:" << r.name(); + r.skipCurrentElement(); + } + } +} + +Resource parseResource(QXmlStreamReader& reader) { + Resource output; + while (reader.readNextStartElement()) { + if (reader.name() == "data") { + QString encoding = ""; + foreach (const QXmlStreamAttribute &attr, reader.attributes()) { + if (attr.name().toString() == "encoding") { + encoding = attr.value().toString(); + break; + } + } + if (encoding != "base64") { + qWarning() << "Unsupported encoding:" << encoding; + return Resource(); + } + + output.data = QByteArray::fromBase64(reader.readElementText().toUtf8()); + } else if (reader.name() == "mime") { + output.mime = reader.readElementText(); + } else if (reader.name() == "resource-attributes") { + parseResourceAttributes(reader, output); + } else if (reader.name() == "width" || reader.name() == "height") { + // Ignore it + reader.skipCurrentElement(); + } else if (reader.name() == "recognition") { + parseResourceRecognition(reader, output); + } else { + qWarning() << "Unsupported element:" << reader.name(); + reader.skipCurrentElement(); + } + } + + //qDebug() << output.id << output.mime << output.filename << output.timestamp; + + return output; +} + +Note parseNote(QXmlStreamReader& reader) { + Note note; + + while (reader.readNextStartElement()) { + if (reader.name() == "title") { + note.title = reader.readElementText(); + } else if (reader.name() == "content") { + note.content = reader.readElementText(); + } else if (reader.name() == "created") { + note.created = dateStringToTimestamp(reader.readElementText()); + } else if (reader.name() == "updated") { + note.updated = dateStringToTimestamp(reader.readElementText()); + } else if (reader.name() == "tag") { + note.tags.append(reader.readElementText()); + } else if (reader.name() == "resource") { + note.resources.push_back(parseResource(reader)); + } else if (reader.name() == "note-attributes") { + parseAttributes(reader, note); + } else { + qWarning() << "Unsupported element:" << reader.name(); + reader.skipCurrentElement(); + } + } + + //qDebug() << title << created << updated; + + //qDebug() << note.longitude << note.latitude << note.source << note.author << note.sourceUrl; + + //qDebug() << note.sourceApplication << note.reminderOrder << note.reminderDoneTime; + + return note; +} + +std::vector parseXmlFile(const QString& filePath) { + std::vector output; + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Cannot open file" << filePath; + return output; + } + + QByteArray fileData = file.readAll(); + + QXmlStreamReader reader(fileData); + + if (reader.readNextStartElement()) { + while (reader.readNextStartElement()) { + if (reader.name() == "note") { + Note note = parseNote(reader); + output.push_back(note); + } else { + qWarning() << "Unsupported element:" << reader.name(); + reader.skipCurrentElement(); + } + } + } + + return output; +} + + +int main(int argc, char *argv[]) { + QCoreApplication a(argc, argv); + +// QString dbPath = "D:/Web/www/joplin/QtClient/evernote-import/notes.sqlite"; + +// QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); +// db.setDatabaseName(path); + +// if (!db_.open()) { +// qDebug() << "Error: connection with database fail"; +// } else { +// qDebug() << "Database: connection ok"; +// } + + + //std::vector notes = parseXmlFile("/home/laurent/Downloads/Notes/Laurent.enex"); + std::vector notes = parseXmlFile("/home/laurent/Downloads/Notes/a_faire.enex"); +} diff --git a/src/AppBundle/Eloquent.php b/src/AppBundle/Eloquent.php index 6554340cc..3c6bb2ba4 100755 --- a/src/AppBundle/Eloquent.php +++ b/src/AppBundle/Eloquent.php @@ -11,10 +11,10 @@ class Eloquent { $this->capsule_->addConnection([ 'driver' => 'mysql', - 'host' => 'localhost', + 'host' => '127.0.0.1', 'database' => 'notes', 'username' => 'root', - 'password' => 'pass', + 'password' => '', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '',