some experiments around therems, a request to update asset
This commit is contained in:
parent
374551d2bb
commit
aa815a5bd7
@ -129,6 +129,15 @@ API::RequestId API::addAsset (
|
||||
return registerAndSend(std::move(add));
|
||||
}
|
||||
|
||||
API::RequestId API::updateAsset (
|
||||
Models::Asset::ID id,
|
||||
const QString& title,
|
||||
const QString& icon,
|
||||
const QColor& color,
|
||||
Models::Currency::ID currency,
|
||||
const QJSValue& finished
|
||||
) {}
|
||||
|
||||
API::RequestId API::deleteAsset (unsigned int id, const QJSValue& finished) {
|
||||
qDebug() << "Deleting asset...";
|
||||
if (magpie.getState() != Models::Magpie::Authenticated)
|
||||
|
@ -12,6 +12,7 @@ set(HEADERS
|
||||
currencies.h
|
||||
addasset.h
|
||||
deleteasset.h
|
||||
updateasset.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
@ -25,6 +26,7 @@ set(SOURCES
|
||||
currencies.cpp
|
||||
addasset.cpp
|
||||
deleteasset.cpp
|
||||
updateasset.cpp
|
||||
)
|
||||
|
||||
target_sources(magpie PRIVATE ${SOURCES})
|
||||
|
19
API/requests/updateasset.cpp
Normal file
19
API/requests/updateasset.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||
//SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "updateasset.h"
|
||||
|
||||
Request::UpdateAsset::UpdateAsset (
|
||||
Models::Asset::ID id,
|
||||
const QString& title,
|
||||
const QString& icon,
|
||||
const QColor& color,
|
||||
Models::Currency::ID currency,
|
||||
const QUrl& baseUrl
|
||||
):
|
||||
Post(createUrl(baseUrl, "/updateAsset"), {
|
||||
{"id", std::to_string(id).c_str()}, {"title", title}, {"icon", icon}, {"currency", std::to_string(currency).c_str()}, {"color", std::to_string(color.rgba()).c_str()}
|
||||
})
|
||||
{
|
||||
emptyResult = true;
|
||||
}
|
27
API/requests/updateasset.h
Normal file
27
API/requests/updateasset.h
Normal file
@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#include "post.h"
|
||||
#include "models/assets.h"
|
||||
#include "models/currencies.h"
|
||||
|
||||
namespace Request {
|
||||
|
||||
class UpdateAsset : public Post {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UpdateAsset(
|
||||
Models::Asset::ID id,
|
||||
const QString& title,
|
||||
const QString& icon,
|
||||
const QColor& color,
|
||||
Models::Currency::ID currency,
|
||||
const QUrl& baseUrl
|
||||
);
|
||||
};
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
#include "utils/helpers.h"
|
||||
|
||||
const QHash<int, QByteArray> Models::Assets::roles({
|
||||
{Title, "title"}, {Icon, "icon"}, {Balance, "balance"}, {Archived, "archived"}, {Color, "color"}, {Currency, "currency"}, {Id, "assetId"}
|
||||
{Title, "title"}, {Icon, "icon"}, {Balance, "balance"}, {Archived, "archived"}, {Color, "color"}, {Currency, "currency"}, {CurrencyID, "currencyID"}, {ID, "assetID"}
|
||||
});
|
||||
|
||||
Models::Assets::Assets (Currencies& currencies, QObject* parent):
|
||||
@ -23,8 +23,8 @@ void Models::Assets::clear () {
|
||||
}
|
||||
|
||||
void Models::Assets::add (const Asset& asset) {
|
||||
QModelIndex index = getIndex(asset.id);
|
||||
if (index.isValid())
|
||||
int index = getIndexByID(asset.id);
|
||||
if (index != -1)
|
||||
throw std::runtime_error("An attempt to insert a duplicating Asset to an asset model");
|
||||
|
||||
beginInsertRows(QModelIndex(), records.size(), records.size());
|
||||
@ -37,7 +37,7 @@ void Models::Assets::add (const std::deque<Asset>& assets) {
|
||||
return;
|
||||
|
||||
for (const Asset& asset : assets)
|
||||
if (getIndex(asset.id).isValid())
|
||||
if (getIndexByID(asset.id) != -1)
|
||||
throw std::runtime_error("An attempt to insert a duplicating Asset to an asset model (bulk)");
|
||||
|
||||
beginInsertRows(QModelIndex(), records.size(), records.size() + assets.size() - 1);
|
||||
@ -47,17 +47,24 @@ void Models::Assets::add (const std::deque<Asset>& assets) {
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void Models::Assets::remove (unsigned int id) {
|
||||
QModelIndex index = getIndex(id);
|
||||
if (!index.isValid())
|
||||
void Models::Assets::remove (Asset::ID id) {
|
||||
int index = getIndexByID(id);
|
||||
if (index == -1)
|
||||
throw std::runtime_error("An attempt to delete non existing Asset from asset model");
|
||||
|
||||
int row = index.row();
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
records.erase(records.begin() + row);
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
records.erase(records.begin() + index);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
Models::Asset Models::Assets::get (Asset::ID id) const {
|
||||
int index = getIndexByID(id);
|
||||
if (index == -1)
|
||||
throw std::runtime_error("An attempt to access non existing Asset from asset model");
|
||||
|
||||
return records[index];
|
||||
}
|
||||
|
||||
int Models::Assets::rowCount (const QModelIndex& parent) const {
|
||||
//For list models only the root node (an invalid parent) should return the
|
||||
//list's size. For all other (valid) parents, rowCount() should return 0 so
|
||||
@ -104,7 +111,9 @@ QVariant Models::Assets::data (const QModelIndex& index, int role) const {
|
||||
return records[row].color;
|
||||
case Currency:
|
||||
return currencies.getCode(records[row].currency);
|
||||
case Id:
|
||||
case CurrencyID:
|
||||
return records[row].currency;
|
||||
case ID:
|
||||
return records[row].id;
|
||||
}
|
||||
}
|
||||
@ -139,11 +148,27 @@ void Models::Assets::receivedAssets (const std::deque<Asset>& assets) {
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex Models::Assets::getIndex (unsigned int id) const {
|
||||
int Models::Assets::getIndexByID (Asset::ID id) const {
|
||||
for (std::size_t i = 0; i < records.size(); ++i) {
|
||||
if (records[i].id == id)
|
||||
return createIndex(i, 0, &records[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
return -1;
|
||||
}
|
||||
|
||||
QVariantMap Models::Assets::getAssetByIndex (int index) const {
|
||||
QVariantMap result;
|
||||
if (index < 0 || index >= records.size())
|
||||
return result;
|
||||
|
||||
QModelIndex idx = createIndex(index, 0, &records[index]);
|
||||
for (int role = Roles::Title; role != Roles::ID; ++role)
|
||||
result[roles[role]] = data(idx, role);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariantMap Models::Assets::getAssetByID (Asset::ID id) const {
|
||||
return getAssetByIndex(getIndexByID(id));
|
||||
}
|
||||
|
@ -14,7 +14,9 @@
|
||||
|
||||
namespace Models {
|
||||
struct Asset {
|
||||
unsigned int id;
|
||||
using ID = uint32_t;
|
||||
|
||||
ID id;
|
||||
QString title;
|
||||
QString icon;
|
||||
QColor color;
|
||||
@ -37,13 +39,16 @@ public:
|
||||
Archived,
|
||||
Color,
|
||||
Currency,
|
||||
Id
|
||||
CurrencyID,
|
||||
ID
|
||||
};
|
||||
|
||||
void clear ();
|
||||
void add (const Asset& asset);
|
||||
void add (const std::deque<Asset>& assets);
|
||||
void remove (unsigned int id);
|
||||
void remove (Asset::ID id);
|
||||
|
||||
Asset get(Asset::ID id) const;
|
||||
|
||||
//Basic functionality:
|
||||
int rowCount (const QModelIndex& parent = QModelIndex()) const override;
|
||||
@ -57,15 +62,16 @@ public:
|
||||
static bool deserialize (const QVariantList& from, std::deque<Asset>& out);
|
||||
static const QHash<int, QByteArray> roles;
|
||||
|
||||
Q_INVOKABLE int getIndexByID (Asset::ID id) const;
|
||||
Q_INVOKABLE QVariantMap getAssetByIndex(int index) const;
|
||||
Q_INVOKABLE QVariantMap getAssetByID(Asset::ID id) const;
|
||||
|
||||
signals:
|
||||
void requestAssets ();
|
||||
|
||||
public slots:
|
||||
void receivedAssets (const std::deque<Asset>& assets);
|
||||
|
||||
private:
|
||||
QModelIndex getIndex (unsigned int id) const;
|
||||
|
||||
private:
|
||||
enum class State {
|
||||
initial,
|
||||
|
@ -9,7 +9,11 @@ import magpie
|
||||
import magpie.Components as Components
|
||||
|
||||
Item {
|
||||
signal add
|
||||
signal add()
|
||||
signal edit(id: int)
|
||||
signal remove(id: int)
|
||||
|
||||
id: item
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
@ -33,6 +37,9 @@ Item {
|
||||
delegate: Components.AssetLine {
|
||||
height: 30
|
||||
width: listView.width
|
||||
|
||||
onRemove: id => item.remove(id)
|
||||
onEdit: id => item.edit(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
signal addAsset
|
||||
signal addAsset()
|
||||
signal removeAsset(id: int)
|
||||
signal editAsset(id: int)
|
||||
|
||||
property string currentPage: "home"
|
||||
RowLayout {
|
||||
@ -71,6 +73,8 @@ Item {
|
||||
Assets {
|
||||
StackView.onActivating: currentPage = "assets"
|
||||
onAdd: addAsset()
|
||||
onRemove: id => removeAsset(id)
|
||||
onEdit: id => editAsset(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,23 @@ Item {
|
||||
id: main
|
||||
Main {
|
||||
onAddAsset: stack.push(addAssetForm);
|
||||
onEditAsset: function(id) {
|
||||
const asset = Magpie.assets.getAssetByID(id);
|
||||
stack.push(editAssetForm, {
|
||||
name: asset.title,
|
||||
icon: asset.icon,
|
||||
color: asset.color,
|
||||
currency: asset.currencyID,
|
||||
assetID: asset.assetID,
|
||||
title: qsTr("Editing asset") + " " + asset.title
|
||||
});
|
||||
}
|
||||
onRemoveAsset: function(id) {
|
||||
API.deleteAsset(id, function(err) {
|
||||
if (err)
|
||||
Magpie.displayError("Error deleting asset " + Magpie.assets.getAssetByID(id).title + ": " + err);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +70,40 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: editAssetForm
|
||||
|
||||
Forms.Asset {
|
||||
required property int assetID
|
||||
|
||||
onCancel: stack.pop()
|
||||
onConfirm: function (title, icon, color, currency) {
|
||||
if (modal.inProgress)
|
||||
return;
|
||||
|
||||
modal.inProgress = true;
|
||||
modal.status = qsTr("Updating asset ") + " " + Magpie.assets.getAssetByID(assetID).title + "...";
|
||||
modal.open();
|
||||
|
||||
API.updateAsset(assetID, title, icon, color, currency, function (err, result) {
|
||||
if (!modal.inProgress)
|
||||
return;
|
||||
|
||||
modal.inProgress = false;
|
||||
if (err)
|
||||
modal.status = err;
|
||||
else
|
||||
modal.status = qsTr("Success");
|
||||
|
||||
if (!!result) {
|
||||
modal.close();
|
||||
stack.pop()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Magpie
|
||||
function onDisplayError (err) {
|
||||
|
@ -13,13 +13,14 @@ Item {
|
||||
required property color color
|
||||
required property string balance
|
||||
required property string currency
|
||||
required property int assetId
|
||||
required property int assetID
|
||||
|
||||
signal error (err:string)
|
||||
signal remove(id: int)
|
||||
signal edit(id: int)
|
||||
|
||||
Row {
|
||||
readonly property int iconSize: height
|
||||
readonly property int freespace: width - deleteButton.width - iconSize - spacing * children.length - 1
|
||||
readonly property int freespace: width - deleteButton.width - editButton.width - iconSize - spacing * children.length - 1
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
@ -37,29 +38,34 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Label {
|
||||
width: parent.freespace / 3
|
||||
height: parent.height
|
||||
text: title
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: palette.text
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
Label {
|
||||
width: parent.freespace / 3
|
||||
height: parent.height
|
||||
text: balance
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Text {
|
||||
Label {
|
||||
width: parent.freespace / 3
|
||||
height: parent.height
|
||||
text: currency
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Button {
|
||||
id: editButton
|
||||
text: qsTr("Edit")
|
||||
flat: true
|
||||
height: parent.height
|
||||
onClicked: edit(assetID)
|
||||
}
|
||||
|
||||
Button {
|
||||
@ -67,10 +73,7 @@ Item {
|
||||
text: qsTr("Delete")
|
||||
flat: true
|
||||
height: parent.height
|
||||
onClicked: API.deleteAsset(line.assetId, function(err) {
|
||||
if (err)
|
||||
Magpie.displayError("Error deleting asset " + line.title + ": " + err);
|
||||
})
|
||||
onClicked: remove(assetID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,17 @@ ComboBox {
|
||||
|
||||
onActivated: index => box.color = model[index]
|
||||
Component.onCompleted: {
|
||||
popup.background.color = box.background.color
|
||||
popup.background.border.color = box.background.border.color
|
||||
popup.background.border.width = box.background.border.width
|
||||
if (box.background.color)
|
||||
popup.background.color = box.background.color;
|
||||
|
||||
if (!box.background.border)
|
||||
return;
|
||||
|
||||
if (box.background.border.color)
|
||||
popup.background.border.color = box.background.border.color;
|
||||
|
||||
if (box.background.border.width)
|
||||
popup.background.border.width = box.background.border.width;
|
||||
}
|
||||
|
||||
popup: Popup {
|
||||
@ -69,8 +77,9 @@ ComboBox {
|
||||
|
||||
highlighted: view.currentIndex === index
|
||||
contentItem: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: modelData
|
||||
radius: box.background.radius
|
||||
radius: box.background.radius || 0
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@ -96,7 +105,7 @@ ComboBox {
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: box.background.radius
|
||||
radius: box.background.radius || 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,11 @@ ComboBox {
|
||||
Icon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconName: icon
|
||||
color: palette.text
|
||||
color: label.color
|
||||
}
|
||||
|
||||
Label {
|
||||
id: label
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: icon
|
||||
}
|
||||
|
33
root.cpp
33
root.cpp
@ -1,11 +1,13 @@
|
||||
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||
//SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QQuickStyle>
|
||||
#include <QPalette>
|
||||
|
||||
Root::Root(const QUrl& root, int& argc, char* argv[]) :
|
||||
Root::Root (const QUrl& root, int& argc, char* argv[]):
|
||||
QGuiApplication(argc, argv),
|
||||
root(root),
|
||||
engine(),
|
||||
@ -13,7 +15,11 @@ Root::Root(const QUrl& root, int& argc, char* argv[]) :
|
||||
magpie(),
|
||||
api(std::make_shared<API>(magpie))
|
||||
{
|
||||
std::cout << "Starting Magpie..." << std::endl;
|
||||
//QQuickStyle::setStyle("Basic");
|
||||
//QQuickStyle::setStyle("Material");
|
||||
//QQuickStyle::setStyle("Universal");
|
||||
//QQuickStyle::setStyle("Imagine");
|
||||
std::cout << "Starting Magpie in style " << QQuickStyle::name().toStdString() << std::endl;
|
||||
|
||||
setOrganizationName("macaw.me");
|
||||
setOrganizationDomain("macaw.me");
|
||||
@ -24,8 +30,11 @@ Root::Root(const QUrl& root, int& argc, char* argv[]) :
|
||||
|
||||
magpie.installAPI(api);
|
||||
|
||||
connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
this, &Root::onObjectCreated,
|
||||
connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreated,
|
||||
this,
|
||||
&Root::onObjectCreated,
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
|
||||
@ -49,11 +58,9 @@ Root::Root(const QUrl& root, int& argc, char* argv[]) :
|
||||
throw std::runtime_error("Couldn't looad root qml object");
|
||||
}
|
||||
|
||||
Root::~Root() {
|
||||
Root::~Root () {}
|
||||
|
||||
}
|
||||
|
||||
bool Root::notify(QObject* receiver, QEvent* e) {
|
||||
bool Root::notify (QObject* receiver, QEvent* e) {
|
||||
try {
|
||||
return QGuiApplication::notify(receiver, e);
|
||||
} catch (const std::exception& e) {
|
||||
@ -69,17 +76,17 @@ bool Root::notify(QObject* receiver, QEvent* e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Root::onObjectCreated(QObject* obj, const QUrl& objUrl) {
|
||||
void Root::onObjectCreated (QObject* obj, const QUrl& objUrl) {
|
||||
if (!obj && objUrl == root)
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
void Root::onAPIAddressChanged(const QUrl& url) {
|
||||
void Root::onAPIAddressChanged (const QUrl& url) {
|
||||
QSettings settings;
|
||||
settings.setValue("address", url);
|
||||
}
|
||||
|
||||
void Root::onStoreTokens(const QString& access, const QString& renew) {
|
||||
void Root::onStoreTokens (const QString& access, const QString& renew) {
|
||||
QSettings settings;
|
||||
settings.setValue("accessToken", access);
|
||||
settings.setValue("renewToken", renew);
|
||||
|
Loading…
Reference in New Issue
Block a user