Commit fb4c9fbe authored by Viktor Porvaznik's avatar Viktor Porvaznik Committed by Viktor Porvaznik

More work on Dbus #3 and client

parent 2fab9954
......@@ -18,17 +18,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qdebug.h>
#include <QQmlApplicationEngine>
#include <QCommandLineParser>
#include <QApplication>
//#include "filesyncapp/interfaces/json_types.h"
#include <KLocalizedContext>
#include <KLocalizedString>
#include <QQmlContext>
#include "filesyncapp/interfaces/json_types.h"
#include "sync_table_model.h"
int main(int argc, char *argv[])
{
// FileSync::JsonTypes::registerQJsonArrayTypeAsDbusType();
// FileSync::JsonTypes::registerQJsonObjectTypeAsDbusType();
FileSync::JsonTypes::registerQJsonArrayTypeAsDbusType();
FileSync::JsonTypes::registerQJsonObjectTypeAsDbusType();
QApplication app(argc, argv);
QApplication::setApplicationName("KDE Connect File Synchronization Client");
QApplication::setApplicationVersion("0.1.0");
......@@ -39,27 +41,11 @@ int main(int argc, char *argv[])
parser.process(app);
FileSync::SyncTableModel *syncTableModel = new FileSync::SyncTableModel();
// syncTableModel->addSyncItem("test1", "test2", "ONLY_DOWNLOAD", "test3");
// syncTableModel->addSyncItem("t22est1", "te222st2", "NEWEST", "te2333st3");
// QStandardItemModel syncTableModel(1,1,&app);
// syncTableModel.setHorizontalHeaderLabels(QStringList({QString("label1"), QString("label1"), QString("label1")}));
// QList<QStandardItem *> row;
// QStandardItem *item = new QStandardItem();
// item->setData(QVariant::fromValue(QString("testse")));
// row.append(item);
// syncTableModel.appendRow(row);
// qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel");
QQmlApplicationEngine engine;
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
FileSync::SyncTableModel *syncTableModel = new FileSync::SyncTableModel();
engine.rootContext()->setContextProperty("syncTableModel", syncTableModel);
engine.load(QUrl("qrc:/qml/MainApplicationWindow.qml"));
qDebug() << "starting app" << endl;
return app.exec();
}
......
/**
* Copyright 2019 Viktor Porvaznik <viktor.porvaznik@piceacode.eu>
* Copyright 2019 Viktor Porvaznik <viktor.porvaznik@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -177,22 +177,23 @@ ApplicationWindow {
statusBar: StatusBar {
ComboBox {
id: devicesCombo
enabled: true
enabled: count > 0
anchors.fill: parent
model: DevicesSortProxyModel {
id: devicesModel
//TODO: make it possible to filter if they can do sms
sourceModel: DevicesModel {
displayFilter: DevicesModel.Paired | DevicesModel.Reachable
}
onRowsInserted: if (devicesCombo.currentIndex < 0) {
devicesCombo.currentIndex = 0
currentDevice = devicesCombo.currentIndex >= 0 ? devicesModel.data(devicesModel.index(devicesCombo.currentIndex, 0), DevicesModel.DeviceRole) : null
}
}
property QtObject currentDevice: devicesCombo.currentIndex >= 0 ? devicesModel.data(devicesModel.index(devicesCombo.currentIndex, 0), DevicesModel.DeviceRole) : null
property QtObject currentDevice: null
textRole: "display"
onCurrentIndexChanged: {
console.log("activated .... ")
onActivated: {
currentDevice = devicesCombo.currentIndex >= 0 ? devicesModel.data(devicesModel.index(devicesCombo.currentIndex, 0), DevicesModel.DeviceRole) : null
syncTableModel.setDeviceId(currentDevice.id())
syncTableModel.loadModel(currentDevice.id())
}
}
......
......@@ -18,51 +18,157 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <QLoggingCategory>
#include <QDBusPendingReply>
#include "interfaces/dbusinterfaces.h"
#include "sync_table_model.h"
#include "../../filesyncapp/interfaces/json_types.h"
const QStringList FileSync::SyncTableModel::s_syncTableColumns = QStringList({"localPath", "remotePath", "direction", "postSyncScript"});
Q_LOGGING_CATEGORY(LOG_SYNC_TABLE_MODEL,
"kdeconnect.filesyncapp.client.syncTableModel");
const QStringList FileSync::SyncTableModel::s_syncTableColumns = QStringList(
{"localPath", "remotePath", "direction", "postSyncScript"});
FileSync::SyncTableModel::SyncTableModel() : m_deviceId("")
{
}
FileSync::SyncTableModel::SyncTableModel(const QJsonArray &data) : m_data(data)
{
}
int FileSync::SyncTableModel::rowCount(const QModelIndex &) const
{
return m_data.size();
}
int FileSync::SyncTableModel::columnCount(const QModelIndex &) const
{
return s_syncTableColumns.size();
}
QVariant
FileSync::SyncTableModel::data(const QModelIndex &index, int role) const
{
return m_data.at(index.row()).toObject().value(
s_syncTableColumns[(role - Qt::UserRole)]);
}
bool FileSync::SyncTableModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
QJsonObject newObject = m_data.at(index.row()).toObject();
newObject.insert(s_syncTableColumns[(role - Qt::UserRole)], value.toString());
m_data.replace(index.row(), newObject);
qCDebug(LOG_SYNC_TABLE_MODEL) << "Row " << index.row() << " modified: "
<< value;
saveModel(m_deviceId, m_data);
Q_EMIT dataChanged(index, index, QVector<int>(role));
return true;
}
QHash<int, QByteArray> FileSync::SyncTableModel::roleNames() const
{
QHash<int, QByteArray> roleNames;
for (int i = 0; i < s_syncTableColumns.size(); i++)
{
roleNames.insert((Qt::UserRole + i), s_syncTableColumns[i].toLatin1());
}
return roleNames;
}
bool FileSync::SyncTableModel::insertADefaultRow()
{
bool retValue = insertRows(rowCount(), 1);
saveModel(m_deviceId, m_data);
return retValue;
}
bool FileSync::SyncTableModel::removeSelectedRow(int row)
{
bool retValue = removeRows(row, 1);
saveModel(m_deviceId, m_data);
return retValue;
}
bool FileSync::SyncTableModel::removeRows(int row, int count,
const QModelIndex &parent)
{
beginRemoveRows(parent, row, row + (count - 1));
m_data.removeAt(row);
endRemoveRows();
qCDebug(LOG_SYNC_TABLE_MODEL) << "Row removed: " << row;
return true;
}
bool FileSync::SyncTableModel::insertRows(int row, int count,
const QModelIndex &parent)
{
beginInsertRows(parent, row, row + (count - 1));
QJsonObject rowData;
rowData.insert("localPath", "");
rowData.insert("remotePath", "");
rowData.insert("direction", "DEFAULT");
rowData.insert("postSyncScript", "");
m_data.append(rowData);
endInsertRows();
qCDebug(LOG_SYNC_TABLE_MODEL) << "Row inserted: " << rowData;
return true;
}
void FileSync::SyncTableModel::loadModel(const QString &deviceId)
{
qDebug() << "Loading model for " << deviceId << endl;
qCDebug(LOG_SYNC_TABLE_MODEL) << "Loading model for: " << deviceId;
FileSyncAppInterface *fileSyncAppInterface = new FileSyncAppInterface(this);
QDBusPendingReply<QVariantList> reply = fileSyncAppInterface->getConfiguration("testDevice");
QDBusPendingReply<QVariantList> reply = fileSyncAppInterface->getConfiguration(
deviceId);
reply.waitForFinished();
if (reply.isValid())
{
m_data = FileSync::JsonTypes::convertQVariantListToQJsonArray(reply.value());
beginResetModel();
m_data = FileSync::JsonTypes::convertQVariantListToQJsonArray(
reply.value());
endResetModel();
qCDebug(LOG_SYNC_TABLE_MODEL) << "Model loaded";
}
else
{
qDebug() << "err " << reply.error() << endl;
qCDebug(LOG_SYNC_TABLE_MODEL) << "Model loading error: " << reply.error();
}
qDebug() << "Loaded model" << endl;
qDebug() << m_data << endl;
}
void FileSync::SyncTableModel::saveModel(const QJsonArray &model)
void FileSync::SyncTableModel::saveModel(const QString &deviceId,
const QJsonArray &model)
{
qDebug() << "saving " << endl;
qCDebug(LOG_SYNC_TABLE_MODEL) << "Saving model for: " << deviceId;
QVariantList variantList;
for (const QJsonValue &value : m_data) {
for (const QJsonValue &value : m_data)
{
variantList.append(value.toObject());
}
FileSyncAppInterface *fileSyncAppInterface = new FileSyncAppInterface(this);
QDBusPendingReply<bool> reply = fileSyncAppInterface->setConfiguration(variantList);
QDBusPendingReply<bool> reply = fileSyncAppInterface->setConfiguration(
deviceId,
variantList);
reply.waitForFinished();
if (reply.isValid())
{
qDebug() << "ok " << reply.value() << endl;
qCDebug(LOG_SYNC_TABLE_MODEL) << "Model saved";
}
else
{
qDebug() << "err " << reply.error() << endl;
qCDebug(LOG_SYNC_TABLE_MODEL) << "Model saving error: " << reply.error();
}
qDebug() << "Loaded model" << endl;
}
void FileSync::SyncTableModel::setDeviceId(const QString &deviceId)
{
m_deviceId = deviceId;
}
......@@ -17,166 +17,61 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KDECONNECT_SYNC_TABLE_MODEL_H
#define KDECONNECT_SYNC_TABLE_MODEL_H
#include <QStandardItemModel>
#include <KAboutData>
#include <KLocalizedString>
#include <QDBusPendingReply>
#include <KLocalizedContext>
#include <KDBusService>
#include <QtQml>
#include "interfaces/dbusinterfaces.h"
#include <QObject>
#include <QModelIndex>
#include <QJsonArray>
namespace FileSync {
namespace FileSync
{
class SyncTableModel : public QAbstractTableModel
{
Q_OBJECT
private:
QJsonArray m_data;
static const QStringList s_syncTableColumns;
Q_OBJECT
public:
SyncTableModel() {
qDebug() << m_data << endl;
}
SyncTableModel(const QJsonArray& data) : m_data(data) {
m_data = data;
qDebug() << m_data << endl;
}
int rowCount(const QModelIndex & = QModelIndex()) const override
{
return m_data.size();
}
//
// QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
// {
// qDebug() << "header called" << endl;
// switch (role) {
// case Qt::DisplayRole:
// {
// return QString("test header");
// }
// default:
// break;
// }
//
// return QVariant();
// }
int columnCount(const QModelIndex & = QModelIndex()) const override
{
return s_syncTableColumns.size();
}
QVariant data(const QModelIndex &index, int role) const override
{
qDebug() << " Item at " << index.row() << ";" << index.column() << ";" << role << endl;
return m_data.at(index.row()).toObject().value(s_syncTableColumns[(role - Qt::UserRole)]);
// switch (role) {
// case (Qt::UserRole + 1):
// {
// return m_data.at(index.row()).toObject().value(s_syncTableColumns[0]);
// }
// case (Qt::UserRole + 2):
// {
// QJsonObject row = m_data.at(index.row()).toObject();
// qDebug() << s_syncTableColumns.value(index.column()) << endl;
// qDebug() << row[s_syncTableColumns.value(index.column())].toString() << endl;
// return m_data.at(index.row()).toObject().value(s_syncTableColumns[1]);
// }
// default:
// break;
// }
// return QVariant();
}
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
{
QJsonObject newObject = m_data.at(index.row()).toObject();
newObject.insert(s_syncTableColumns[(role - Qt::UserRole)], value.toString());
m_data.replace(index.row(), newObject);
saveModel(m_data);
qDebug() << " SetData at " << index.row() << ";" << index.column() << ";" << role << value << endl;
switch (role) {
case Qt::EditRole:
qDebug() << value << endl;
default:
break;
}
Q_EMIT dataChanged(index, index, QVector<int>(role));
return true;
}
QHash<int, QByteArray> roleNames() const override
{
QHash<int, QByteArray> roleNames;
for (int i = 0; i < s_syncTableColumns.size(); i++)
{
roleNames.insert((Qt::UserRole + i), s_syncTableColumns[i].toLatin1());
}
return roleNames;
}
SyncTableModel();
explicit SyncTableModel(const QJsonArray &data);
int rowCount(const QModelIndex & = QModelIndex()) const override;
int columnCount(const QModelIndex & = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QHash<int, QByteArray> roleNames() const override;
public Q_SLOTS:
bool insertADefaultRow()
{
bool retValue = insertRows(rowCount(), 1);
saveModel(m_data);
return retValue;
};
bool removeSelectedRow(int row)
{
bool retValue = removeRows(row, 1);
saveModel(m_data);
return retValue;
};
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())
{
beginRemoveRows(parent, row, row + (count - 1));
m_data.removeAt(row);
endRemoveRows();
return true;
};
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
{
beginInsertRows(parent, row, row + (count - 1));
QJsonObject rowData;
rowData.insert("localPath", "");
rowData.insert("remotePath", "");
rowData.insert("direction", "DEFAULT");
rowData.insert("postSyncScript", "");
m_data.append(rowData);
endInsertRows();
return true;
};
void addSyncItem(const QString &localPath, const QString &remotePath, const QString &direction, const QString &postSyncScript)
{
QJsonObject row;
row.insert("localPath", localPath);
row.insert("remotePath", remotePath);
row.insert("direction", direction);
row.insert("postSyncScript", postSyncScript);
m_data.append(row);
qDebug() << m_data << endl;
}
void saveModel(const QJsonArray& model);
bool
removeRows(int row, int count,
const QModelIndex &parent = QModelIndex()) override;;
bool
insertRows(int row, int count,
const QModelIndex &parent = QModelIndex()) override;;
void saveModel(const QString &deviceId, const QJsonArray &model);
void loadModel(const QString &deviceId);
void setDeviceId(const QString &deviceId);
bool insertADefaultRow();
bool removeSelectedRow(int row);
private:
static const QStringList s_syncTableColumns;
QJsonArray m_data;
QString m_deviceId;
};
}
......
......@@ -10,6 +10,7 @@ add_executable(kdeconnect-filesync-daemon
executor.cpp
sync_operation.cpp
config.cpp
singleton_pool.cpp
../interfaces/filesyncapp_interface.cpp
../interfaces/sync_result.cpp
../interfaces/file_hash_array.cpp
......
......@@ -38,7 +38,6 @@ namespace FileSync
static const QString SSHFS_MOUNT_ROOT = "%1/storage/emulated/0/%2";
static const QString MTIME_MOD_CMD = "touch -d \"%1\" \"%2\"";
static const QString MTIME_DATETIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
static const QString FILESYNC_APP_CONFIG_PATH = "%1/.kdeconnect-sync/%2/sync_config.json";
// Daemon
static const QString DAEMON_SYNC_REQUEST = "Sync requested for deviceId %1 sync list (%2)";
......
......@@ -18,6 +18,81 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QJsonDocument>
#include <QJsonArray>
#include "log.h"
#include "config.h"
QMap<QString, FileSync::Config*>* s_instances = NULL;
Q_LOGGING_CATEGORY(LOG_CONFIG, "kdeconnect.filesyncapp.daemon.config");
FileSync::Config::Config(const QString &deviceId)
{
Log::instance(deviceId);
m_deviceId = deviceId;
m_confiFilePath = CONFIG_FILE_PATH.arg(
QStandardPaths::writableLocation(QStandardPaths::HomeLocation), deviceId);
loadConfig(deviceId);
}
FileSync::Config::~Config()
{
}
const QJsonArray FileSync::Config::data()
{
return m_data;
}
void FileSync::Config::setData(const QJsonArray &data)
{
m_data = data;
}
void FileSync::Config::saveConfig()
{
LOG_D(LOG_CONFIG, "Sav configuration for " + m_confiFilePath);
QFile configFile(m_confiFilePath);
if (QFileInfo(configFile).exists())
{
LOG_W(LOG_CONFIG, "Configuration file does exist, overriding!");
}
if (!configFile.open(QIODevice::WriteOnly))
{
LOG_E(LOG_CONFIG, "Can not open configuration file!");
}
QJsonDocument tmpDoc;
tmpDoc.setArray(m_data);
configFile.write(tmpDoc.toJson());
configFile.close();
LOG_D(LOG_CONFIG, "Configuration saved");
configFile.close();
}
void FileSync::Config::loadConfig(const QString &deviceId)
{
LOG_D(LOG_CONFIG, "Loading configuration for " + deviceId);
QFile configFile(m_confiFilePath);
if (!QFileInfo(configFile).exists())
{
LOG_W(LOG_CONFIG, "Configuration file does not exist, creating one!");
if (!configFile.open(QIODevice::WriteOnly))
{
LOG_E(LOG_CONFIG, "Can not open configuration file!");
}
configFile.write("[]");
configFile.close();
}
if (!configFile.open(QIODevice::ReadOnly))
{
LOG_E(LOG_CONFIG, "Can not open configuration file!");
}
m_data = QJsonDocument::fromJson(configFile.readAll()).array();
LOG_D(LOG_CONFIG, "Configuration opened");
configFile.close();
}
#include "config.moc"
\ No newline at end of file
......@@ -23,7 +23,7 @@
#include <string>
#include "common.h"
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include <QLoggingCategory>
#include <QtCore/QDateTime>
......@@ -33,73 +33,31 @@
#include <QtCore/QFileInfo>
#include <QtCore/QJsonDocument>
#include "singleton_pool.h"
namespace FileSync
{
class Config : QObject
class Config : public QObject, public SingletonPool<FileSync::Config>
{
Q_OBJECT
public:
Config(const QString &deviceId)
{
m_deviceId = deviceId;
m_confiFilePath = CONFIG_FILE_PATH.arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), deviceId);
QByteArray configData;
QFile configFile;
configFile.setFileName(m_confiFilePath);
if (!configFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
// qCDebug(LOG_INDEX)
// << FileSync::INDEX_READ_OPEN_ERROR.arg(indexFile.fileName(),
// indexFile.errorString());
}
else
{
configData = configFile.readAll();
m_data = QJsonDocument::fromJson(configData).object();
}
}
Config(const QString &deviceId);
~Config()
{
}
~Config();
static Config &instance(const QString &deviceId) {
FileSync::Config *config = NULL;
if (s_instances == NULL)
{
s_instances = new QMap<QString, FileSync::Config*>();
config = new Config(deviceId);
s_instances->insert(deviceId, config);
}
else
{
QMap<QString, FileSync::Config*>::iterator it= s_instances->find(deviceId);
if (it != s_instances->end())
{
config = it.value();
}
}
return *config;
}
const QJsonArray data();
static void destroyInstances()
{
delete s_instances;
}
const QJsonObject data()
{
return m_data;
}
void setData(const QJsonArray &data);
void saveConfig();
private:
static QMap<QString, Config*>* s_instances;
QString m_confiFilePath;
QString m_deviceId;
QJsonObject m_data;
QJsonArray m_data;
void loadConfig(const QString &deviceId);
};
}
......
......@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <daemon.h>
#include <QJsonArray>
......@@ -79,6 +80,26 @@ void FileSync::Daemon::processRequestedHashes(const QString &deviceId,
}
}
QJsonArray
FileSync::Daemon::getConfiguration(const QString &deviceId)
{
QJsonArray deviceConfig = FileSync::Config::instance(deviceId).data();
qCDebug(LOG_DAEMON) << "Configuration for device " << deviceId
<< " requested: " << deviceConfig;
return deviceConfig;
}
bool FileSync::Daemon::setConfiguration(const QString &deviceId,
const QJsonArray &newConfig)
{
FileSync::Config::instance(deviceId).setData(newConfig);
FileSync::Config::instance(deviceId).saveConfig();
qCDebug(LOG_DAEMON) << "Configuration for device " << deviceId
<< " saved: " << newConfig;
return true;
}
void FileSync::Daemon::relayNotification(const FileSync::SyncResult &syncResult)
{
qDebug() << "Relaying signal." << endl;
......
......@@ -50,6 +50,13 @@ namespace FileSync
processRequestedHashes(const QString &deviceId,
const QJsonArray &hashArray);
QJsonArray
getConfiguration(const QString &deviceId);
bool
setConfiguration(const QString &deviceId,
const QJsonArray &newConfig);
void relayNotification(const FileSync::SyncResult &syncResult);
Q_SIGNALS:
......
......@@ -171,7 +171,7 @@ FileSync::SyncResult FileSync::Executor::determineAndPerformSyncOperation(const
void FileSync::Executor::loadConfig()
{