1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Qt client first commit

This commit is contained in:
Laurent Cozic 2016-12-10 22:39:53 +00:00
parent 6a73f86943
commit 6b5f7ebfce
25 changed files with 928 additions and 0 deletions

View File

@ -0,0 +1,44 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
Item {
id: root
property alias model: listView.model
property alias currentIndex: listView.currentIndex
signal currentItemChanged()
Rectangle {
color: "#eeeeff"
border.color: "#ff0000"
anchors.fill: parent
}
Component {
id: folderDelegate
Item {
width: parent.width
height: 25
Text {
text: display
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
}
}
}
}
ListView {
id: listView
anchors.fill: parent
delegate: folderDelegate
ScrollBar.vertical: ScrollBar { }
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
onCurrentItemChanged: {
root.currentItemChanged()
}
}
}

View File

@ -0,0 +1,39 @@
QT += qml quick sql
CONFIG += c++11
SOURCES += \
main.cpp \
models/item.cpp \
models/folder.cpp \
database.cpp \
uuid.cpp \
services/folderservice.cpp \
models/foldermodel.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
stable.h \
models/folder.h \
models/item.h \
database.h \
uuid.h \
services/folderservice.h \
models/foldermodel.h
DISTFILES +=
PRECOMPILED_HEADER = stable.h
# INCLUDEPATH += "C:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/ucrt"
# LIBS += -L"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/ucrt/x86"

View File

@ -0,0 +1,7 @@
import QtQuick 2.7
Page1Form {
button1.onClicked: {
console.log("Button Pressed. Entered text: " + textField1.text);
}
}

View File

@ -0,0 +1,73 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
Item {
property alias textField1: textField1
property alias button1: button1
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
anchors.top: parent.top
TextField {
id: textField1
placeholderText: qsTr("Text Field")
}
Button {
id: button1
text: qsTr("Press Me")
}
}
ListView {
id: listView1
x: 62
y: 143
width: 410
height: 199
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
delegate: Item {
x: 5
width: 80
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
}
Text {
text: name
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
spacing: 10
}
}
}
}

View File

@ -0,0 +1,15 @@
import QtQuick.Controls 1.4
TreeView {
TableViewColumn {
title: "Name"
role: "fileName"
width: 300
}
TableViewColumn {
title: "Permissions"
role: "filePermissions"
width: 100
}
model: fileSystemModel
}

View File

@ -0,0 +1,101 @@
#include "database.h"
using namespace jop;
Database::Database(const QString &path) {
version_ = -1;
QFile::remove(path);
db_ = QSqlDatabase::addDatabase("QSQLITE");
db_.setDatabaseName(path);
if (!db_.open()) {
qDebug() << "Error: connection with database fail";
} else {
qDebug() << "Database: connection ok";
}
upgrade();
}
Database::Database() {}
QSqlQuery Database::query(const QString &sql) const {
QSqlQuery output(db_);
output.prepare(sql);
return output;
}
//QSqlQuery Database::exec(const QString &sql, const QMap<QString, QVariant> &parameters) {
// QSqlQuery query;
// query.prepare(sql);
// QMapIterator<QString, QVariant> it(parameters);
// while (it.hasNext()) {
// it.next();
// qDebug() << i.key() << ": " << i.value();
// }
//}
int Database::version() const {
if (version_ >= 0) return version_;
QSqlQuery query = db_.exec("SELECT * FROM version");
bool result = query.next();
if (!result) return 0;
QSqlRecord r = query.record();
int i_version = r.indexOf("version");
version_ = query.value(i_version).toInt();
return version_;
}
void Database::upgrade() {
// INSTRUCTIONS TO UPGRADE THE DATABASE:
//
// 1. Add the new version number to the existingDatabaseVersions array
// 2. Add the upgrade logic to the "switch (targetVersion)" statement below
QList<int> existingVersions;
existingVersions << 1;
int versionIndex = existingVersions.indexOf(version());
if (versionIndex == existingVersions.length() - 1) return;
while (versionIndex < existingVersions.length() - 1) {
int targetVersion = existingVersions[versionIndex + 1];
qDebug() << "Upgrading database to version " << targetVersion;
db_.transaction();
switch (targetVersion) {
case 1:
db_.exec("CREATE TABLE version (version INT)");
db_.exec("INSERT INTO version (version) VALUES (1)");
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)");
break;
}
db_.exec(QString("UPDATE version SET version = %1").arg(targetVersion));
db_.commit();
versionIndex++;
}
}

View File

@ -0,0 +1,28 @@
#ifndef DATABASE_H
#define DATABASE_H
#include <stable.h>
namespace jop {
class Database {
public:
Database(const QString& path);
Database();
QSqlQuery query(const QString& sql) const;
//QSqlQuery exec(const QString& sql, const QMap<QString, QVariant> &parameters);
private:
QSqlDatabase db_;
void upgrade();
int version() const;
mutable int version_;
};
}
#endif // DATABASE_H

View File

@ -0,0 +1,81 @@
#include <stable.h>
#include "models/folder.h"
#include "database.h"
#include "models/foldermodel.h"
#include "services/folderservice.h"
using namespace jop;
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Database db("D:/Web/www/joplin/database.sqlite");
// FolderService s(db);
// qDebug() << s.count();
// Folder f = s.byId("35dbdd6e633566c4160e699a86601ab8");
// qDebug() << f.id() << f.title() << f.createdTime();
// QSqlQuery q = db.query("SELECT * FROM folders WHERE id = :id");
// q.bindValue(":id", "35dbdd6e633566c4160e699a86601ab8");
// q.exec();
// q.next();
//qDebug() << q.isValid();
// Folder f;
// f.fromSqlQuery(q);
// qDebug() << f.title() << f.id() << f.createdTime();
//QSqlQuery q = query("SELECT * FROM folders WHERE id = :id");
//q.bindValue(":id", "a");
//q.exec();
FolderService folderService(db);
FolderModel model(folderService);
//Folder* f = new Folder(); f->setTitle("oneXXX"); model.addFolder(f);
//f = new Folder(); f->setTitle("two"); model.addFolder(f);
//f = new Folder(); f->setTitle("three"); model.addFolder(f);
// QQuickView view;
// view.setResizeMode(QQuickView::SizeRootObjectToView);
// QQmlContext *ctxt = view.rootContext();
// ctxt->setContextProperty("myModel", &model);
// QSqlDatabase m_db = QSqlDatabase::addDatabase("QSQLITE");
// m_db.setDatabaseName("D:/Web/www/joplin/QtClient/JoplinQtClient/test.sqlite3");
// if (!m_db.open())
// {
// qDebug() << "Error: connection with database fail";
// }
// else
// {
// qDebug() << "Database: connection ok";
// }
//QQmlApplicationEngine engine;
//engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
QQmlContext *ctxt = view.rootContext();
ctxt->setContextProperty("folderTreeViewModel", &model);
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}

127
QtClient/JoplinQtClient/main.qml Executable file
View File

@ -0,0 +1,127 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.0
Item {
width: 800
height: 600
RowLayout {
id: layout
anchors.fill: parent
spacing: 0
FolderListView {
id: folderTreeView
model: folderTreeViewModel
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumWidth: 50
Layout.preferredWidth: 100
Layout.maximumWidth: 300
Layout.minimumHeight: 150
onCurrentItemChanged: {
console.info(folderTreeView.currentIndex)
}
}
// Rectangle {
// color: 'teal'
// Layout.fillWidth: true
// Layout.minimumWidth: 50
// Layout.preferredWidth: 100
// Layout.maximumWidth: 300
// Layout.minimumHeight: 150
// Text {
// anchors.centerIn: parent
// text: parent.width + 'x' + parent.height
// }
// }
Rectangle {
color: 'plum'
Layout.fillWidth: true
Layout.minimumWidth: 100
Layout.preferredWidth: 200
Layout.preferredHeight: 100
Text {
anchors.centerIn: parent
text: parent.width + 'x' + parent.height
}
}
}
// visible: true
// width: 640
// height: 480
// //title: qsTr("Hello World")
// RowLayout {
// anchors.fill: parent
// FolderTreeView {
// id: folderTreeView
// model: folderTreeViewModel
// width: 200
// //height: 500
// //currentIndex: folderTreeViewCurrentIndex
// anchors.fill: parent
// onCurrentItemChanged: {
// console.info(folderTreeView.currentIndex)
// //folderTreeViewCurrentIndex = folderTreeView.currentIndex
// }
// }
// Rectangle {
// color: 'plum'
// Text {
// anchors.centerIn: parent
// text: parent.width + 'x' + parent.height
// }
// }
// }
}
//import QtQuick 2.7
//import QtQuick.Controls 2.0
//import QtQuick.Controls 1.4
//import QtQuick.Layouts 1.0
//ApplicationWindow {
// visible: true
// width: 640
// height: 480
// title: qsTr("Hello World")
// SwipeView {
// id: swipeView
// anchors.fill: parent
// currentIndex: tabBar.currentIndex
// Page1 {
// }
// Page {
// Label {
// text: qsTr("Second page")
// anchors.centerIn: parent
// }
// }
// }
// footer: TabBar {
// id: tabBar
// currentIndex: swipeView.currentIndex
// TabButton {
// text: qsTr("First")
// }
// TabButton {
// text: qsTr("Second")
// }
// }
//}

View File

@ -0,0 +1,7 @@
#include "models/folder.h"
using namespace jop;
Folder::Folder() {
}

View File

@ -0,0 +1,23 @@
#ifndef FOLDER_H
#define FOLDER_H
#include <stable.h>
#include "models/item.h"
namespace jop {
class Folder : public Item {
public:
Folder();
private:
};
}
#endif // FOLDER_H

View File

@ -0,0 +1,7 @@
#include "foldercollection.h"
using namespace jop;
FolderCollection::FolderCollection() {
}

View File

@ -0,0 +1,24 @@
#ifndef FOLDERCOLLECTION_H
#define FOLDERCOLLECTION_H
#include <stable.h>
#include "model/folder.h"
namespace jop {
class FolderCollection {
public:
FolderCollection();
void add(const Folder* folder);
private:
std::vector<Folder*> collection_;
};
}
#endif // FOLDERCOLLECTION_H

View File

@ -0,0 +1,52 @@
#include "foldermodel.h"
using namespace jop;
//FolderModel::FolderModel() : QAbstractListModel() {}
FolderModel::FolderModel(FolderService &folderService) : QAbstractListModel() {
folderService_ = folderService;
}
void FolderModel::addFolder(Folder* folder) {
//folders_.push_back(folder);
}
int FolderModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return folderService_.count();
//return 10;
//return folders_.size();
}
// NOTE: to lazy load - send back "Loading..." if item not currently loaded
// queue the item for loading.
// Then batch load them a bit later.
QVariant FolderModel::data(const QModelIndex & index, int role) const {
QList<Folder> list = folderService_.overviewList();
if (index.row() < 0 || index.row() >= list.size()) return QVariant();
Folder folder = list[index.row()];
if (role == Qt::DisplayRole) {
return QVariant(folder.title());
}
return QVariant();
}
QHash<int, QByteArray> FolderModel::roleNames() const {
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[TitleRole] = "title";
roles[UuidRole] = "uuid";
return roles;
}
bool FolderModel::canFetchMore(const QModelIndex &parent) const {
return folders_.size() < folderService_.count();
}
void FolderModel::fetchMore(const QModelIndex &parent) {
}

View File

@ -0,0 +1,45 @@
#ifndef FOLDERMODEL_H
#define FOLDERMODEL_H
#include <stable.h>
#include "services/folderservice.h"
namespace jop {
class FolderModel : public QAbstractListModel {
Q_OBJECT
public:
enum FolderRoles {
UuidRole = Qt::UserRole + 1,
TitleRole
};
//FolderModel();
FolderModel(FolderService& folderService);
void addFolder(Folder* folder);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
protected:
QHash<int, QByteArray> roleNames() const;
bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE;
void fetchMore(const QModelIndex &parent) Q_DECL_OVERRIDE;
private:
QList<Folder> folders_;
FolderService folderService_;
};
}
#endif // FOLDERMODEL_H

View File

@ -0,0 +1,55 @@
#include "models/item.h"
#include "uuid.h"
using namespace jop;
Item::Item() {
isPartial_ = true;
}
void Item::fromSqlQuery(const QSqlQuery &q) {
int i_id = q.record().indexOf("id");
int i_title = q.record().indexOf("title");
int i_created_time = q.record().indexOf("created_time");
id_ = jop::uuid::fromString(q.value(i_id).toString());
title_ = q.value(i_title).toString();
createdTime_ = q.value(i_created_time).toInt();
}
QUuid Item::id() const {
return id_;
}
QString Item::title() const {
return title_;
}
int Item::createdTime() const {
return createdTime_;
}
void Item::setId(const QUuid &v) {
id_ = v;
}
void Item::setId(const QString& v) {
QUuid u = uuid::fromString(v);
setId(u);
}
void Item::setTitle(const QString &v) {
title_ = v;
}
void Item::setCreatedTime(int v) {
createdTime_ = v;
}
void Item::setIsPartial(bool v) {
isPartial_ = v;
}
bool Item::isPartial() const {
return isPartial_;
}

View File

@ -0,0 +1,38 @@
#ifndef ITEM_H
#define ITEM_H
#include <stable.h>
namespace jop {
class Item {
public:
Item();
QUuid id() const;
QString title() const;
int createdTime() const;
bool isPartial() const;
void setId(const QUuid& v);
void setId(const QString& v);
void setTitle(const QString& v);
void setCreatedTime(int v);
void setIsPartial(bool v);
void fromSqlQuery(const QSqlQuery& query);
private:
QUuid id_;
QString title_;
int createdTime_;
bool isPartial_;
};
}
#endif // ITEM_H

View File

@ -0,0 +1,9 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>Page1.qml</file>
<file>Page1Form.ui.qml</file>
<file>FolderListView.qml</file>
<file>TestUnQuatre.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,49 @@
#include "folderservice.h"
#include "uuid.h"
using namespace jop;
FolderService::FolderService() {}
FolderService::FolderService(Database &database) {
database_ = database;
}
int FolderService::count() const {
QSqlQuery q = database_.query("SELECT count(*) as row_count FROM folders");
q.exec();
q.next();
return q.value(0).toInt();
}
Folder FolderService::byId(const QString &id) const {
QSqlQuery q = database_.query("SELECT title, created_time FROM folders WHERE id = :id");
q.bindValue(":id", id);
q.exec();
q.next();
Folder output;
output.setId(id);
output.setTitle(q.value(0).toString());
output.setCreatedTime(q.value(1).toInt());
return output;
}
const QList<Folder> FolderService::overviewList() const {
if (cache_.size()) return cache_;
QList<Folder> output;
QSqlQuery q = database_.query("SELECT id, title FROM folders ORDER BY created_time DESC");
q.exec();
while (q.next()) {
Folder f;
f.setId(q.value(0).toString());
f.setTitle(q.value(1).toString());
f.setIsPartial(true);
output << f;
}
cache_ = output;
return cache_;
}

View File

@ -0,0 +1,30 @@
#ifndef FOLDERSERVICE_H
#define FOLDERSERVICE_H
#include <stable.h>
#include "database.h"
#include "models/folder.h"
namespace jop {
class FolderService {
public:
FolderService();
FolderService(Database& database);
int count() const;
Folder byId(const QString& id) const;
//Folder partialAt(int index) const;
const QList<Folder> overviewList() const;
private:
Database database_;
mutable QList<Folder> cache_;
};
}
#endif // FOLDERSERVICE_H

View File

@ -0,0 +1,23 @@
#ifndef STABLE_H
#define STABLE_H
#if defined __cplusplus
#include <QAbstractListModel>
#include <QDebug>
#include <QFileInfo>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QUuid>
#include <vector>
#include <QList>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSqlDatabase>
#include <QQuickView>
#include <QQmlContext>
#endif // __cplusplus
#endif // STABLE_H

View File

@ -0,0 +1,22 @@
#include <stable.h>
#include "uuid.h"
namespace jop {
namespace uuid {
QUuid fromString(const QString& s) {
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
QString mod = s;
mod.insert(8, '-');
mod.insert(13, '-');
mod.insert(18, '-');
mod.insert(23, '-');
mod = "{" + mod + "}";
qDebug() << mod;
return QUuid(mod);
}
}
}

14
QtClient/JoplinQtClient/uuid.h Executable file
View File

@ -0,0 +1,14 @@
#ifndef UUID_H
#define UUID_H
#include <stable.h>
namespace jop {
namespace uuid {
QUuid fromString(const QString& s);
}
}
#endif // UUID_H

View File

@ -0,0 +1,7 @@
#include "uuid_utils.h"
QString testtest()
{
return "con";
}

View File

@ -0,0 +1,8 @@
#ifndef UUID_UTILS_H
#define UUID_UTILS_H
#include <stable.h>
QString testtest();
#endif // UUID_UTILS_H