1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-07-16 00:14:34 +02:00

Recreating item list

This commit is contained in:
Laurent Cozic
2017-02-06 20:20:30 +00:00
parent a4116a4bf8
commit ab3bb28036
27 changed files with 445 additions and 179 deletions

View File

@ -5,14 +5,23 @@ Item {
id: root
signal rowsRequested(int fromRowIndex, int toRowIndex)
property int blabla: 123456;
property variant items: [];
property int itemCount: 0;
property int itemHeight: 0;
property int itemCount_: 0;
property int itemHeight_: 0;
property bool needToRequestRows_: false;
function testing() {
console.info("WXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
function itemHeight() {
if (root.itemHeight_) return root.itemHeight_;
var item = itemComponent.createObject(root)
item.content = { title: "dummy", id: "" };
item.updateDisplay();
item.visible = false;
root.itemHeight_ = item.height;
return root.itemHeight_;
}
function itemCount() {
return itemCount_;
}
function setItem(index, itemContent) {
@ -21,18 +30,18 @@ Item {
return;
}
var item = itemComponent.createObject(scrollArea.contentItem)
item.title = itemContent.title;
item.invalidateDisplay();
var contentTitle = itemContent.title;
if (!itemHeight) {
item.updateDisplay();
itemHeight = item.height;
}
var item = itemComponent.createObject(scrollArea.contentItem)
item.content = {
id: itemContent.id,
title: itemContent.title
};
item.invalidateDisplay();
items[index] = item;
this.invalidateDisplay();
root.invalidateDisplay();
}
function setItems(fromIndex, itemContents) {
@ -49,46 +58,61 @@ Item {
items.push(item);
if (!itemHeight) itemHeight = item.height;
this.invalidateDisplay();
root.invalidateDisplay();
}
function setItemCount(count) {
this.itemCount = count;
this.invalidateDisplay();
if (count === root.itemCount_) return;
root.itemCount_ = count;
root.needToRequestRows_ = true;
root.invalidateDisplay();
}
function invalidateDisplay() {
updateDisplay();
root.updateDisplay();
}
function updateDisplay() {
var itemY = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item) {
item.y = itemY;
}
itemY += itemHeight
if (item) item.y = itemY;
itemY += itemHeight()
}
scrollArea.contentHeight = itemCount * itemHeight;
scrollArea.contentHeight = itemCount() * itemHeight();
// console.info("itemCount itemHeight", this.itemCount, this.itemHeight);
// console.info("scrollArea.contentHeight", scrollArea.contentHeight);
if (root.needToRequestRows_) {
root.needToRequestRows_ = false;
var indexes = itemIndexesInView();
root.rowsRequested(indexes[0], indexes[1]);
}
}
function itemIndexesInView() {
var maxVisibleItems = Math.ceil(scrollArea.height / itemHeight());
var fromIndex = Math.max(0, Math.floor(scrollArea.contentY / itemHeight()));
var toIndex = fromIndex + maxVisibleItems;
var maxIndex = itemCount() - 1;
return [Math.min(fromIndex, maxIndex), Math.min(toIndex, maxIndex)];
}
Component {
id: itemComponent
Item {
property alias title: label.text
id: container
//property alias title: label.text
property variant content;
function invalidateDisplay() {
this.updateDisplay();
container.updateDisplay();
}
function updateDisplay() {
this.height = label.height
label.text = content.title;
container.height = label.height
}
Text {

View File

@ -47,8 +47,9 @@ SOURCES += \
models/abstractlistmodel.cpp \
cliapplication.cpp \
command.cpp \
itemlistcontroller.cpp \
qmlutils.cpp
qmlutils.cpp \
baseitemlistcontroller.cpp \
folderlistcontroller.cpp
RESOURCES += qml.qrc \
database.qrc
@ -88,8 +89,9 @@ HEADERS += \
models/abstractlistmodel.h \
cliapplication.h \
command.h \
itemlistcontroller.h \
qmlutils.h
qmlutils.h \
baseitemlistcontroller.h \
folderlistcontroller.h
defined(JOP_FRONT_END_GUI, var) {
SOURCES += application.cpp

View File

@ -22,7 +22,7 @@ Item {
ItemList2 {
id: itemList
width: 800
height: 600
height: 500
}

View File

@ -62,8 +62,13 @@ Application::Application(int &argc, char **argv) :
QObject* itemList = qmlUtils::childFromProperty(rootObject, "itemList");
itemListController_.setItemList(itemList);
itemListController_.setParentId(QString(""));
//qmlUtils::callQml(itemList, "testing");
qmlUtils::callQml(itemList, "testing");
//qDebug() << itemList;

View File

@ -10,6 +10,7 @@
#include "webapi.h"
#include "synchronizer.h"
#include "window.h"
#include "folderlistcontroller.h"
namespace jop {
@ -34,6 +35,7 @@ private:
WebApi api_;
Synchronizer synchronizer_;
QTimer synchronizerTimer_;
FolderListController itemListController_;
void afterSessionInitialization();

View File

@ -0,0 +1,69 @@
#include "baseitemlistcontroller.h"
namespace jop {
BaseItemListController::BaseItemListController() :
parentId_(QString("")),
itemList_(NULL),
orderBy_("title") {
}
void BaseItemListController::setItemList(QObject *itemList) {
if (itemList_) {
qFatal("Cannot reset itemList - create a new ItemListController instead");
return;
}
itemList_ = itemList;
connect(itemList, SIGNAL(rowsRequested(int,int)), this, SLOT(itemList_rowsRequested(int,int)));
}
void BaseItemListController::setParentId(const QString &parentId) {
parentId_= parentId;
updateItemCount();
}
QString BaseItemListController::parentId() const {
return parentId_;
}
QObject *BaseItemListController::itemList() const {
return itemList_;
}
void BaseItemListController::setOrderBy(const QString &v) {
orderBy_ = v;
}
QString BaseItemListController::orderBy() const {
return orderBy_;
}
void BaseItemListController::updateItemCount() {
qFatal("BaseItemListController::updateItemCount() must be implemented by child class");
}
void BaseItemListController::itemList_rowsRequested(int fromIndex, int toIndex) {
qFatal("BaseItemListController::itemList_rowsRequested() must be implemented by child class");
}
const BaseModel *BaseItemListController::cacheGet(int index) const {
qFatal("BaseItemListController::cacheGet() not implemented");
return NULL;
}
void BaseItemListController::cacheSet(int index, BaseModel* baseModel) const {
qFatal("BaseItemListController::cacheSet() not implemented");
}
bool BaseItemListController::cacheIsset(int index) const {
qFatal("BaseItemListController::cacheIsset() not implemented");
return false;
}
void BaseItemListController::cacheClear() const {
qFatal("BaseItemListController::cacheClear() not implemented");
}
}

View File

@ -0,0 +1,49 @@
#ifndef BASEITEMLISTCONTROLLER_H
#define BASEITEMLISTCONTROLLER_H
#include <stable.h>
#include "models/basemodel.h"
namespace jop {
class BaseItemListController : public QObject {
Q_OBJECT
public:
BaseItemListController();
void setItemList(QObject* itemList);
void setParentId(const QString& parentId);
QString parentId() const;
QObject* itemList() const;
void setOrderBy(const QString& v);
QString orderBy() const;
private:
QObject* itemList_;
QString parentId_;
QString orderBy_;
protected:
virtual void updateItemCount();
// All these methods are const because we want to be able to clear the
// cache or set values from any method including const ones.
// http://stackoverflow.com/a/4248661/561309
virtual const BaseModel* cacheGet(int index) const;
virtual void cacheSet(int index, BaseModel* baseModel) const;
virtual bool cacheIsset(int index) const;
virtual void cacheClear() const;
public slots:
virtual void itemList_rowsRequested(int fromIndex, int toIndex);
};
}
#endif // BASEITEMLISTCONTROLLER_H

View File

@ -116,7 +116,7 @@ int CliApplication::exec() {
if (command == "ls") {
QString path = args.size() ? args[0] : QString();
if (path == "") {
std::vector<std::unique_ptr<Folder>> folders = Folder::all();
std::vector<std::unique_ptr<Folder>> folders = Folder::all(QString(""));
for (size_t i = 0; i < folders.size(); i++) {
qDebug().noquote() << folders[i].get()->value("title").toString();
}

View File

@ -15,7 +15,7 @@ void Database::initialize(const QString &path) {
transactionCount_ = 0;
logQueries_ = true;
//QFile::remove(path);
// QFile::remove(path);
db_ = QSqlDatabase::addDatabase("QSQLITE");
db_.setDatabaseName(path);
@ -137,7 +137,6 @@ bool Database::commit() {
bool Database::execQuery(QSqlQuery &query) {
if (logQueries_) {
QString sql = query.lastQuery();
// if (sql.startsWith("insert", Qt::CaseInsensitive)) {
qDebug().noquote() << "SQL:" << sql;
QMapIterator<QString, QVariant> i(query.boundValues());
@ -145,7 +144,6 @@ bool Database::execQuery(QSqlQuery &query) {
i.next();
qDebug().noquote() << "SQL:" << i.key() << "=" << i.value().toString();
}
// }
}
return query.exec();

View File

@ -0,0 +1,61 @@
#include "folderlistcontroller.h"
#include "qmlutils.h"
#include "models/folder.h"
namespace jop {
FolderListController::FolderListController() : BaseItemListController() {}
void FolderListController::updateItemCount() {
int itemCount = Folder::count(parentId());
qmlUtils::callQml(itemList(), "setItemCount", QVariantList() << itemCount);
}
const BaseModel *FolderListController::cacheGet(int index) const {
return cache_[index].get();
}
void FolderListController::cacheSet(int index, BaseModel *baseModel) const {
Folder* folder = static_cast<Folder*>(baseModel);
cache_[index] = std::unique_ptr<Folder>(folder);
}
bool FolderListController::cacheIsset(int index) const {
return index > 0 && cache_.size() > index;
}
void FolderListController::cacheClear() const {
cache_.clear();
}
void FolderListController::itemList_rowsRequested(int fromIndex, int toIndex) {
if (!cache_.size()) {
cache_ = Folder::all(parentId(), orderBy());
}
//qDebug() << cache_.size();
if (fromIndex < 0 || toIndex >= cache_.size() || !cache_.size()) {
qWarning() << "Invalid folder indexes" << fromIndex << toIndex;
return;
}
QVariantList output;
for (int i = fromIndex; i <= toIndex; i++) {
const BaseModel* model = cacheGet(i);
//qDebug() << model;
//QVariant v(cacheGet(i));
QVariant v = QVariant::fromValue((QObject*)model);
//qDebug() << v;
output.push_back(v);
}
QVariantList args;
args.push_back(fromIndex);
args.push_back(output);
qmlUtils::callQml(itemList(), "setItems", args);
}
}

View File

@ -0,0 +1,39 @@
#ifndef ITEMLISTCONTROLLER_H
#define ITEMLISTCONTROLLER_H
#include <stable.h>
#include "models/folder.h"
#include "baseitemlistcontroller.h"
namespace jop {
class FolderListController : public BaseItemListController {
Q_OBJECT
public:
FolderListController();
protected:
void updateItemCount();
const BaseModel* cacheGet(int index) const;
void cacheSet(int index, BaseModel* baseModel) const;
bool cacheIsset(int index) const;
void cacheClear() const;
private:
mutable std::vector<std::unique_ptr<Folder>> cache_;
public slots:
void itemList_rowsRequested(int fromIndex, int toIndex);
};
}
#endif // ITEMLISTCONTROLLER_H

View File

@ -1,10 +0,0 @@
#include "itemlistcontroller.h"
namespace jop {
ItemListController::ItemListController()
{
}
}

View File

@ -1,18 +0,0 @@
#ifndef ITEMLISTCONTROLLER_H
#define ITEMLISTCONTROLLER_H
#include <stable.h>
namespace jop {
class ItemListController {
public:
ItemListController();
};
}
#endif // ITEMLISTCONTROLLER_H

View File

@ -20,15 +20,17 @@ QStringList BaseModel::changedFields() const {
return output;
}
int BaseModel::count(Table table) {
int BaseModel::count(Table table, const QString &parentId) {
QString t = BaseModel::tableName(table);
QString k = QString("%1:count").arg(t);
QVariant r = BaseModel::cacheGet(k);
if (r.isValid()) return r.toInt();
QSqlQuery q("SELECT count(*) AS row_count FROM " + t);
QSqlQuery q = jop::db().prepare("SELECT count(*) AS row_count FROM " + t + " WHERE parent_id = :parent_id");
q.bindValue(":parent_id", parentId);
jop::db().execQuery(q);
q.next();
if (!jop::db().errorCheck(q)) return 0;
int output = q.value(0).toInt();
BaseModel::cacheSet(k, QVariant(output));
return output;
@ -457,6 +459,10 @@ void BaseModel::cacheDelete(const QString &key) {
BaseModel::cache_.remove(key);
}
QString BaseModel::title() const {
return value("title").toString();
}
void BaseModel::setValue(const QString &name, const QString &value) {
setValue(name, Value(value));
}

View File

@ -7,7 +7,12 @@
namespace jop {
class BaseModel {
class BaseModel : public QObject {
Q_OBJECT
Q_PROPERTY(QString title READ title)
Q_PROPERTY(QString id READ idString)
public:
@ -41,7 +46,7 @@ public:
BaseModel();
QStringList changedFields() const;
static int count(jop::Table table);
static int count(jop::Table table, const QString &parentId);
bool load(const QString& id);
bool loadByField(const QString& parentId, const QString& field, const QString& fieldValue);
virtual bool save(bool trackChanges = true);
@ -74,7 +79,6 @@ public:
void setValue(const QString& name, const QJsonValue& value, QMetaType::Type type);
//void setValues(const QHash<QString, Value> values);
Value id() const;
QString idString() const;
QString valuesToString() const;
void clone(const BaseModel& baseModel);
@ -93,6 +97,12 @@ protected:
static QMap<int, QVector<BaseModel::Field>> tableFields_;
static QHash<QString, QVariant> cache_;
public slots:
QString title() const;
QString idString() const;
};
}

View File

@ -22,11 +22,13 @@ QVector<Change> Change::all(int limit) {
QVector<Change> output;
while (q.next()) {
Change change;
change.loadSqlQuery(q);
output.push_back(change);
}
qWarning() << "TODO: fix change iteration";
// while (q.next()) {
// Change change;
// change.loadSqlQuery(q);
// output.push_back(change);
// }
return output;
}
@ -36,46 +38,48 @@ QVector<Change> Change::mergedChanges(const QVector<Change>& changes) {
QStringList deletedItems;
QHash<QString, Change> itemChanges;
foreach (Change change, changes) {
QString itemId = change.value("item_id").toString();
Change::Type type = (Change::Type)change.value("type").toInt();
qWarning() << "TODO: fix change iteration";
if (type == Change::Create) {
createdItems.push_back(itemId);
} else if (type == Change::Delete) {
deletedItems.push_back(itemId);
}
// foreach (Change change, changes) {
// QString itemId = change.value("item_id").toString();
// Change::Type type = (Change::Type)change.value("type").toInt();
if (itemChanges.contains(itemId) && type == Change::Update) {
// Merge all the "Update" event into one.
Change& existingChange = itemChanges[itemId];
existingChange.addMergedField(change.value("item_field").toString());
} else {
itemChanges[itemId] = change;
}
}
// if (type == Change::Create) {
// createdItems.push_back(itemId);
// } else if (type == Change::Delete) {
// deletedItems.push_back(itemId);
// }
// if (itemChanges.contains(itemId) && type == Change::Update) {
// // Merge all the "Update" event into one.
// Change& existingChange = itemChanges[itemId];
// existingChange.addMergedField(change.value("item_field").toString());
// } else {
// itemChanges[itemId] = change;
// }
// }
QVector<Change> output;
for (QHash<QString, Change>::iterator it = itemChanges.begin(); it != itemChanges.end(); ++it) {
QString itemId = it.key();
Change& change = it.value();
// for (QHash<QString, Change>::iterator it = itemChanges.begin(); it != itemChanges.end(); ++it) {
// QString itemId = it.key();
// Change& change = it.value();
if (createdItems.contains(itemId) && deletedItems.contains(itemId)) {
// Item both created then deleted - skip
continue;
}
// if (createdItems.contains(itemId) && deletedItems.contains(itemId)) {
// // Item both created then deleted - skip
// continue;
// }
if (deletedItems.contains(itemId)) {
// Item was deleted at some point - just return one 'delete' event
change.setValue("type", Change::Delete);
} else if (createdItems.contains(itemId)) {
// Item was created then updated - just return one 'create' event with the latest changes
change.setValue("type", Change::Create);
}
// if (deletedItems.contains(itemId)) {
// // Item was deleted at some point - just return one 'delete' event
// change.setValue("type", Change::Delete);
// } else if (createdItems.contains(itemId)) {
// // Item was created then updated - just return one 'create' event with the latest changes
// change.setValue("type", Change::Create);
// }
output.push_back(change);
}
// output.push_back(change);
// }
return output;
}

View File

@ -84,16 +84,22 @@ int Folder::noteIndexById(const QString &orderBy, const QString& id) const {
return -1;
}
int Folder::count() {
return BaseModel::count(jop::FoldersTable);
int Folder::count(const QString &parentId) {
return BaseModel::count(jop::FoldersTable, parentId);
}
std::vector<std::unique_ptr<Folder>> Folder::all(const QString &orderBy) {
QSqlQuery q("SELECT " + BaseModel::tableFieldNames(jop::FoldersTable).join(",") + " FROM " + BaseModel::tableName(jop::FoldersTable) + " ORDER BY " + orderBy);
std::vector<std::unique_ptr<Folder>> Folder::all(const QString& parentId, const QString &orderBy) {
QSqlQuery q = jop::db().prepare(QString("SELECT %1 FROM %2 WHERE parent_id = :parent_id ORDER BY %3")
.arg(BaseModel::tableFieldNames(jop::FoldersTable).join(","))
.arg(BaseModel::tableName(jop::FoldersTable))
.arg(orderBy));
q.bindValue(":parent_id", parentId);
jop::db().execQuery(q);
std::vector<std::unique_ptr<Folder>> output;
//if (!jop::db().errorCheck(q)) return output;
while (q.next()) {
std::unique_ptr<Folder> folder(new Folder());
folder->loadSqlQuery(q);

View File

@ -9,12 +9,14 @@ namespace jop {
class Folder : public Item {
Q_OBJECT
public:
Folder();
static int count();
static std::vector<std::unique_ptr<Folder>> all(const QString& orderBy = "title");
static int count(const QString& parentId);
static std::vector<std::unique_ptr<Folder>> all(const QString& parentId, const QString& orderBy = "title");
static std::vector<std::unique_ptr<Folder>> pathToFolders(const QString& path, bool isNotePath);
//Table table() const;

View File

@ -66,7 +66,7 @@ void FolderModel::deleteData(const int index) {
}
int FolderModel::baseModelCount() const {
return Folder::count();
return Folder::count("");
}
const BaseModel *FolderModel::cacheGet(int index) const {

View File

@ -9,6 +9,8 @@ namespace jop {
class Item : public BaseModel {
Q_OBJECT
public:
Item();

View File

@ -26,15 +26,15 @@ const Note *NoteModel::atIndex(int index) const {
int from = indexes[0];
int to = indexes[indexes.size() - 1];
Folder folder = this->folder();
// Folder folder = this->folder();
qDebug() << "NoteModel: cache recreated";
std::vector<std::unique_ptr<Note>> notes = folder.notes(orderBy_, to - from + 1, from);
int noteIndex = from;
for (int i = 0; i < notes.size(); i++) {
cache_.set(noteIndex, notes[i].release());
noteIndex++;
}
// qDebug() << "NoteModel: cache recreated";
// std::vector<std::unique_ptr<Note>> notes = folder.notes(orderBy_, to - from + 1, from);
// int noteIndex = from;
// for (int i = 0; i < notes.size(); i++) {
// cache_.set(noteIndex, notes[i].release());
// noteIndex++;
// }
return cache_.get(index);
}
@ -47,12 +47,12 @@ void NoteModel::setFolderId(const QString &v) {
endResetModel();
}
Folder NoteModel::folder() const {
Folder folder;
if (folderId_ == "") return folder;
folder.load(folderId_);
return folder;
}
//Folder NoteModel::folder() const {
// Folder folder;
// //if (folderId_ == "") return folder;
// folder.load(folderId_);
// return folder;
//}
int NoteModel::idToIndex(const QString &id) const {
std::vector<int> indexes = cache_.indexes();
@ -61,8 +61,10 @@ int NoteModel::idToIndex(const QString &id) const {
if (note->idString() == id) return indexes[i];
}
Folder f = this->folder();
return f.noteIndexById(orderBy_, id);
return 0;
//Folder f = this->folder();
//return f.noteIndexById(orderBy_, id);
}
void NoteModel::addData(const QString &title) {
@ -81,7 +83,8 @@ void NoteModel::deleteData(int index) {
}
int NoteModel::baseModelCount() const {
return folder().noteCount();
return 0;
//return folder().noteCount();
}
const BaseModel *NoteModel::cacheGet(int index) const {

View File

@ -18,7 +18,7 @@ public:
NoteModel();
const Note* atIndex(int index) const;
void setFolderId(const QString& v);
Folder folder() const;
//Folder folder() const;
public slots:

View File

@ -13,6 +13,6 @@ QString QmlNote::body() const {
}
void QmlNote::setNote(const Note &note) {
note_ = note;
// note_ = note;
emit changed();
}

View File

@ -5,7 +5,7 @@ namespace qmlUtils {
QVariant callQml(QObject* o, const QString &name, const QVariantList &args) {
QVariant returnedValue;
qDebug() << "Going to call QML:" << name << args;
//qDebug() << "Going to call QML:" << name << args;
if (args.size() == 0) {
QMetaObject::invokeMethod(o, name.toStdString().c_str(), Q_RETURN_ARG(QVariant, returnedValue));
} else if (args.size() == 1) {

View File

@ -20,8 +20,8 @@ CREATE TABLE notes (
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,
todo_due INT NOT NULL DEFAULT "",
todo_completed INT NOT NULL DEFAULT "",
source_application TEXT NOT NULL DEFAULT "",
application_data TEXT NOT NULL DEFAULT "",
`order` INT NOT NULL DEFAULT 0

View File

@ -122,38 +122,40 @@ void Synchronizer::switchState(Synchronizer::SynchronizationState state) {
uploadsRemaining_ = changes.size();
foreach (Change change, changes) {
jop::Table itemType = (jop::Table)change.value("item_type").toInt();
QString itemId = change.value("item_id").toString();
Change::Type type = (Change::Type)change.value("type").toInt();
qWarning() << "TODO: fix change iteration";
if (itemType == jop::FoldersTable) {
// foreach (Change change, changes) {
// jop::Table itemType = (jop::Table)change.value("item_type").toInt();
// QString itemId = change.value("item_id").toString();
// Change::Type type = (Change::Type)change.value("type").toInt();
if (type == Change::Create) {
// if (itemType == jop::FoldersTable) {
Folder folder;
folder.load(itemId);
QUrlQuery data = valuesToUrlQuery(folder.values());
api_.put("folders/" + folder.id().toString(), QUrlQuery(), data, "upload:putFolder:" + folder.id().toString());
// if (type == Change::Create) {
} else if (type == Change::Update) {
// Folder folder;
// folder.load(itemId);
// QUrlQuery data = valuesToUrlQuery(folder.values());
// api_.put("folders/" + folder.id().toString(), QUrlQuery(), data, "upload:putFolder:" + folder.id().toString());
Folder folder;
folder.load(itemId);
QStringList mergedFields = change.mergedFields();
QUrlQuery data;
foreach (QString field, mergedFields) {
data.addQueryItem(field, folder.value(field).toString());
}
api_.patch("folders/" + folder.id().toString(), QUrlQuery(), data, "upload:patchFolder:" + folder.id().toString());
// } else if (type == Change::Update) {
} else if (type == Change::Delete) {
// Folder folder;
// folder.load(itemId);
// QStringList mergedFields = change.mergedFields();
// QUrlQuery data;
// foreach (QString field, mergedFields) {
// data.addQueryItem(field, folder.value(field).toString());
// }
// api_.patch("folders/" + folder.id().toString(), QUrlQuery(), data, "upload:patchFolder:" + folder.id().toString());
api_.del("folders/" + itemId, QUrlQuery(), QUrlQuery(), "upload:deleteFolder:" + itemId);
// } else if (type == Change::Delete) {
}
}
}
// api_.del("folders/" + itemId, QUrlQuery(), QUrlQuery(), "upload:deleteFolder:" + itemId);
// }
// }
// }
checkNextState();

View File

@ -348,6 +348,16 @@ QString extensionFromMimeType(const QString& mimeType) {
return "";
}
QString enforceNotNull(const QString& s) {
if (s.isEmpty() || s.isNull()) return QString("");
return s;
}
QString enforceZero(const QString& f) {
if (f.isEmpty() || f.isNull()) return QString("0");
return f;
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
@ -466,22 +476,22 @@ int main(int argc, char *argv[]) {
QSqlQuery query(db);
query.prepare("INSERT INTO notes (id, title, body, parent_id, created_time, updated_time, longitude, latitude, altitude, source, author, source_url, is_todo, todo_due, todo_completed, source_application, application_data, `order`) VALUES (:id, :title,:body, :parent_id, :created_time,:updated_time,:longitude,:latitude,:altitude,:source,:author,:source_url,:is_todo,:todo_due,:todo_completed,:source_application,:application_data,:order)");
query.bindValue(":id", n.id);
query.bindValue(":title", n.title);
query.bindValue(":body", markdown);
query.bindValue(":parent_id", folderId);
query.bindValue(":title", enforceNotNull(n.title));
query.bindValue(":body", enforceNotNull(markdown));
query.bindValue(":parent_id", enforceNotNull(folderId));
query.bindValue(":created_time", n.created);
query.bindValue(":updated_time", n.updated);
query.bindValue(":longitude", n.longitude);
query.bindValue(":latitude", n.latitude);
query.bindValue(":altitude", n.altitude);
query.bindValue(":source", n.source);
query.bindValue(":author", n.author);
query.bindValue(":source_url", n.sourceUrl);
query.bindValue(":longitude", enforceZero(n.longitude));
query.bindValue(":latitude", enforceZero(n.latitude));
query.bindValue(":altitude", enforceZero(n.altitude));
query.bindValue(":source", enforceNotNull(n.source));
query.bindValue(":author", enforceNotNull(n.author));
query.bindValue(":source_url", enforceNotNull(n.sourceUrl));
query.bindValue(":is_todo", reminderOrder ? 1 : 0);
query.bindValue(":todo_due", dateStringToTimestamp(n.reminderTime));
query.bindValue(":todo_completed", dateStringToTimestamp(n.reminderDoneTime));
query.bindValue(":source_application", n.sourceApplication);
query.bindValue(":application_data", n.applicationData);
query.bindValue(":source_application", enforceNotNull(n.sourceApplication));
query.bindValue(":application_data", enforceNotNull(n.applicationData));
query.bindValue(":order", reminderOrder);
query.exec();