homescreens/folio: Add import/export homescreen layout setting

This commit is contained in:
Devin Lin 2023-10-22 10:17:09 -07:00
parent df80fb65fc
commit f1aff0b13e
10 changed files with 163 additions and 18 deletions

View file

@ -212,12 +212,8 @@ void FavouritesModel::deleteGhostEntry()
}
}
void FavouritesModel::save()
QJsonArray FavouritesModel::exportToJson()
{
if (!m_applet) {
return;
}
QJsonArray arr;
for (int i = 0; i < m_delegates.size(); i++) {
FolioDelegate *delegate = m_delegates[i].delegate;
@ -229,6 +225,16 @@ void FavouritesModel::save()
arr.append(delegate->toJson());
}
return arr;
}
void FavouritesModel::save()
{
if (!m_applet) {
return;
}
QJsonArray arr = exportToJson();
QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact);
m_applet->config().writeEntry("Favourites", QString::fromStdString(data.toStdString()));
@ -242,12 +248,16 @@ void FavouritesModel::load()
}
QJsonDocument doc = QJsonDocument::fromJson(m_applet->config().readEntry("Favourites", "{}").toUtf8());
loadFromJson(doc.array());
}
void FavouritesModel::loadFromJson(QJsonArray arr)
{
beginResetModel();
m_delegates.clear();
for (QJsonValueRef r : doc.array()) {
for (QJsonValueRef r : arr) {
QJsonObject obj = r.toObject();
FolioDelegate *delegate = FolioDelegate::fromJson(obj, this);

View file

@ -59,12 +59,14 @@ public:
QPointF getDelegateScreenPosition(int position) const;
QJsonArray exportToJson();
void save();
Q_INVOKABLE void load();
void loadFromJson(QJsonArray arr);
void setApplet(Plasma::Applet *applet);
private:
void save();
void evaluateDelegatePositions(bool emitSignal = true);
// get the x (or y) position where delegates start being placed

View file

@ -265,6 +265,9 @@ void ApplicationFolderModel::removeDelegate(int index)
QPointF ApplicationFolderModel::getDelegatePosition(int index)
{
if (index < 0 || index >= m_folder->m_delegates.size()) {
return {0, 0};
}
auto delegate = m_folder->m_delegates[index];
return {delegate.xPosition, delegate.yPosition};
}

View file

@ -2,6 +2,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "foliosettings.h"
#include "favouritesmodel.h"
#include "pagelistmodel.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QTextStream>
FolioSettings::FolioSettings(QObject *parent)
: QObject{parent}
@ -139,3 +146,56 @@ void FolioSettings::load()
Q_EMIT showFavouritesAppLabelsChanged();
Q_EMIT delegateIconSizeChanged();
}
bool FolioSettings::saveLayoutToFile(QString path)
{
if (path.startsWith(QStringLiteral("file://"))) {
path = path.replace(QStringLiteral("file://"), QString());
}
QJsonArray favourites = FavouritesModel::self()->exportToJson();
QJsonArray pages = PageListModel::self()->exportToJson();
QJsonObject obj;
obj[QStringLiteral("Favourites")] = favourites;
obj[QStringLiteral("Pages")] = pages;
QByteArray data = QJsonDocument(obj).toJson(QJsonDocument::Compact);
QFile file{path};
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write(data);
} else {
qDebug() << "failed to write to file:" << file.errorString();
return false;
}
file.close();
return true;
}
bool FolioSettings::loadLayoutFromFile(QString path)
{
if (path.startsWith(QStringLiteral("file://"))) {
path = path.replace(QStringLiteral("file://"), QString());
}
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "failed to open file:" << file.errorString();
return false;
}
QTextStream in(&file);
QString contents = in.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(contents.toUtf8());
QJsonObject obj = doc.object();
// TODO error checking
FavouritesModel::self()->loadFromJson(obj[QStringLiteral("Favourites")].toArray());
PageListModel::self()->loadFromJson(obj[QStringLiteral("Pages")].toArray());
return true;
}

View file

@ -45,6 +45,9 @@ public:
Q_INVOKABLE void load();
Q_INVOKABLE bool saveLayoutToFile(QString path);
Q_INVOKABLE bool loadLayoutFromFile(QString path);
Q_INVOKABLE void setApplet(Plasma::Applet *applet);
Q_SIGNALS:

View file

@ -644,7 +644,7 @@ QPointF HomeScreenState::getFavouritesDelegateScreenPosition(int position)
QPointF HomeScreenState::getFolderDelegateScreenPosition(int position)
{
if (!m_currentFolder) {
if (!m_currentFolder || position < 0 || position >= m_currentFolder->applications()->rowCount()) {
return {0, 0};
}
auto pos = m_currentFolder->applications()->getDelegatePosition(position);

View file

@ -34,7 +34,7 @@ MobileShell.GridView {
cellWidth: effectiveContentWidth / Math.min(Math.floor(effectiveContentWidth / (Folio.FolioSettings.delegateIconSize + Kirigami.Units.largeSpacing * 3)), 8)
cellHeight: cellWidth + reservedSpaceForLabel
boundsBehavior: Flickable.OvershootBounds
boundsBehavior: Flickable.StopAtBounds
readonly property int columns: Math.floor(effectiveContentWidth / cellWidth)
readonly property int rows: Math.ceil(root.count / columns)

View file

@ -4,6 +4,7 @@
import QtQuick
import QtQuick.Window
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Controls as QQC2
import org.kde.kirigami 2.20 as Kirigami
@ -178,6 +179,7 @@ Kirigami.ApplicationWindow {
}
FormCard.FormCard {
Layout.bottomMargin: Kirigami.Units.gridUnit
FormCard.FormButtonDelegate {
id: containmentSettings
text: i18n('Switch Homescreen')
@ -189,20 +191,73 @@ Kirigami.ApplicationWindow {
FormCard.FormButtonDelegate {
id: exportSettings
enabled: false
text: 'Export layout (in development)'
text: i18n('Export layout')
icon.name: 'document-export'
onClicked: exportFileDialog.open()
}
FormCard.FormDelegateSeparator { above: exportSettings; below: importSettings }
FormCard.FormButtonDelegate {
id: importSettings
enabled: false
text: 'Import layout (in development)'
text: i18n('Import layout')
icon.name: 'document-import'
onClicked: importFileDialog.open()
}
}
}
FileDialog {
id: exportFileDialog
title: i18n("Export layout to")
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadsLocation)
fileMode: FileDialog.SaveFile
defaultSuffix: 'json'
nameFilters: ["JSON files (*.json)"]
onAccepted: {
console.log('saving layout to ' + selectedFile);
if (selectedFile) {
let status = Folio.FolioSettings.saveLayoutToFile(selectedFile);
if (status) {
exportedSuccessfullyPrompt.open();
} else {
exportFailedPrompt.open();
}
}
}
}
FileDialog {
id: importFileDialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadsLocation)
fileMode: FileDialog.OpenFile
nameFilters: ["JSON files (*.json)"]
onAccepted: {
console.log('about to load layout from ' + selectedFile);
confirmImportPrompt.open();
}
}
Kirigami.PromptDialog {
id: exportFailedPrompt
title: i18n("Export Status")
subtitle: i18n("Failed to export to %1", String(exportFileDialog.selectedFile).substring('file://'.length))
standardButtons: Kirigami.Dialog.Close
}
Kirigami.PromptDialog {
id: exportedSuccessfullyPrompt
title: i18n("Export Status")
subtitle: i18n("Homescreen layout exported successfully to %1", String(exportFileDialog.selectedFile).substring('file://'.length))
standardButtons: Kirigami.Dialog.Close
}
Kirigami.PromptDialog {
id: confirmImportPrompt
title: i18n("Confirm Import")
subtitle: i18n("This will overwrite your existing homescreen layout!")
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: Folio.FolioSettings.loadLayoutFromFile(importFileDialog.selectedFile);
}
}
}

View file

@ -94,16 +94,22 @@ bool PageListModel::isLastPageEmpty()
return m_pages.size() == 0 ? true : m_pages[m_pages.size() - 1]->isPageEmpty();
}
QJsonArray PageListModel::exportToJson()
{
QJsonArray arr;
for (auto &page : m_pages) {
arr.push_back(page->toJson());
}
return arr;
}
void PageListModel::save()
{
if (!m_applet) {
return;
}
QJsonArray arr;
for (auto &page : m_pages) {
arr.push_back(page->toJson());
}
QJsonArray arr = exportToJson();
QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact);
m_applet->config().writeEntry("Pages", QString::fromStdString(data.toStdString()));
@ -117,12 +123,16 @@ void PageListModel::load()
}
QJsonDocument doc = QJsonDocument::fromJson(m_applet->config().readEntry("Pages", "{}").toUtf8());
loadFromJson(doc.array());
}
void PageListModel::loadFromJson(QJsonArray arr)
{
beginResetModel();
m_pages.clear();
for (QJsonValueRef r : doc.array()) {
for (QJsonValueRef r : arr) {
QJsonArray obj = r.toArray();
PageModel *page = PageModel::fromJson(obj, this);

View file

@ -33,8 +33,10 @@ public:
Q_INVOKABLE void addPageAtEnd();
bool isLastPageEmpty();
QJsonArray exportToJson();
void save();
Q_INVOKABLE void load();
void loadFromJson(QJsonArray arr);
void setApplet(Plasma::Applet *applet);