mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-29 15:03:09 +00:00
homescreens/folio: Add import/export homescreen layout setting
This commit is contained in:
parent
df80fb65fc
commit
f1aff0b13e
10 changed files with 163 additions and 18 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue