homescreens/halcyon: Port to plasma_add_applet

This commit is contained in:
Devin Lin 2025-07-14 22:05:18 -04:00
parent 78366a62ac
commit 8a0b3d4f56
31 changed files with 103 additions and 133 deletions

View file

@ -1,16 +1,35 @@
# SPDX-FileCopyrightText: 2022-2023 Devin Lin <devin@kde.org>
# SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
# SPDX-License-Identifier: GPL-2.0-or-later
add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.mobile.homescreen.halcyon\")
set(homescreen_SRCS
homescreen.cpp
plasma_add_applet(org.kde.plasma.mobile.homescreen.halcyon
QML_SOURCES
qml/Clock.qml
qml/FavoritesAppDelegate.qml
qml/FavoritesGrid.qml
qml/FavoritesView.qml
qml/FolderGrid.qml
qml/GridAppDelegate.qml
qml/GridAppList.qml
qml/HomeScreen.qml
qml/main.qml
qml/SearchWidget.qml
CPP_SOURCES
application.cpp
applicationfolder.cpp
applicationlistmodel.cpp
halcyonsettings.cpp
homescreen.cpp
pinnedmodel.cpp
windowlistener.cpp
)
add_library(org.kde.plasma.mobile.homescreen.halcyon MODULE ${homescreen_SRCS})
ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.halcyon SOURCES
qml/settings/SettingsScreen.qml
qml/settings/SettingsWindow.qml
PATH settings
)
target_link_libraries(org.kde.plasma.mobile.homescreen.halcyon
target_link_libraries(org.kde.plasma.mobile.homescreen.halcyon PRIVATE
Qt::Gui
Qt::Qml
Qt::Quick
@ -19,12 +38,5 @@ target_link_libraries(org.kde.plasma.mobile.homescreen.halcyon
KF6::I18n
KF6::Service
KF6::KIOGui
KF6::Notifications
KF6::WindowSystem
)
install(TARGETS org.kde.plasma.mobile.homescreen.halcyon DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/applets)
plasma_install_package(package org.kde.plasma.mobile.homescreen.halcyon)
add_subdirectory(plugin)
KF6::JobWidgets
KF6::WindowSystem)

View file

@ -16,12 +16,16 @@
#include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h>
#include <qqmlregistration.h>
/**
* @short Object that represents an application.
*/
class Application : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("Managed by ApplicationListModel")
Q_PROPERTY(bool running READ running NOTIFY windowChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)

View file

@ -16,6 +16,8 @@
#include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h>
#include <qqmlregistration.h>
/**
* @short Object that represents an application folder on the main page.
*/
@ -24,6 +26,8 @@ class ApplicationFolderModel;
class ApplicationFolder : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("Managed by ApplicationListModel")
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QList<Application *> appPreviews READ appPreviews NOTIFY applicationsChanged)
Q_PROPERTY(ApplicationFolderModel *applications READ applications NOTIFY applicationsReset)
@ -67,7 +71,9 @@ class ApplicationFolderModel : public QAbstractListModel
Q_OBJECT
public:
enum Roles { ApplicationRole = Qt::UserRole + 1 };
enum Roles {
ApplicationRole = Qt::UserRole + 1
};
ApplicationFolderModel(ApplicationFolder *folder);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;

View file

@ -8,6 +8,7 @@
#include <QDebug>
#include <QModelIndex>
#include <QProcess>
#include <QQmlEngine>
#include <QQuickWindow>
#include <KApplicationTrader>
@ -41,6 +42,15 @@ ApplicationListModel *ApplicationListModel::self()
return inst;
}
ApplicationListModel *ApplicationListModel::create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
{
Q_UNUSED(qmlEngine);
Q_UNUSED(jsEngine);
auto *model = self();
QQmlEngine::setObjectOwnership(model, QQmlEngine::CppOwnership);
return model;
}
QHash<int, QByteArray> ApplicationListModel::roleNames() const
{
return {{ApplicationRole, QByteArrayLiteral("application")}};

View file

@ -13,19 +13,29 @@
#include <QSet>
#include <QTimer>
#include <qqmlregistration.h>
class QJSEngine;
class QQmlEngine;
/**
* @short The base application list, used directly by the full app list page.
*/
class ApplicationListModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
enum Roles { ApplicationRole = Qt::UserRole + 1 };
enum Roles {
ApplicationRole = Qt::UserRole + 1
};
ApplicationListModel(QObject *parent = nullptr);
~ApplicationListModel() override;
static ApplicationListModel *self();
static ApplicationListModel *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

View file

@ -7,9 +7,13 @@
#include <KConfigGroup>
#include <qqmlregistration.h>
class HalcyonSettings : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
Q_PROPERTY(HalcyonSettings::WallpaperBlurEffect wallpaperBlurEffect READ wallpaperBlurEffect WRITE setWallpaperBlurEffect NOTIFY wallpaperBlurEffectChanged)
Q_PROPERTY(bool doubleTapToLock READ doubleTapToLock WRITE setDoubleTapToLock NOTIFY doubleTapToLockChanged)

View file

@ -9,9 +9,12 @@
#include <QDebug>
#include <QQuickItem>
K_PLUGIN_CLASS_WITH_JSON(HomeScreen, "metadata.json")
HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
: Plasma::Containment{parent, data, args}
, m_settings{new HalcyonSettings{this, config()}}
, m_pinnedModel{new PinnedModel{this}}
{
setHasConfigurationInterface(true);
}
@ -23,6 +26,9 @@ HalcyonSettings *HomeScreen::settings() const
return m_settings;
}
K_PLUGIN_CLASS(HomeScreen)
PinnedModel *HomeScreen::pinnedModel() const
{
return m_pinnedModel;
}
#include "homescreen.moc"

View file

@ -6,21 +6,25 @@
#include <Plasma/Containment>
#include "halcyonsettings.h"
#include "pinnedmodel.h"
class HomeScreen : public Plasma::Containment
{
Q_OBJECT
Q_PROPERTY(HalcyonSettings *settings READ settings CONSTANT)
Q_PROPERTY(PinnedModel *pinnedModel READ pinnedModel CONSTANT)
public:
HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
~HomeScreen() override;
HalcyonSettings *settings() const;
PinnedModel *pinnedModel() const;
Q_SIGNALS:
void showingDesktopChanged(bool showingDesktop);
private:
HalcyonSettings *m_settings{nullptr};
PinnedModel *m_pinnedModel{nullptr};
};

View file

@ -1,5 +1,4 @@
{
"KPackageStructure": "Plasma/Applet",
"KPlugin": {
"Authors": [
{
@ -83,7 +82,6 @@
"Description[x-test]": "xxA mobile homescreen focused on simplicity and ease-of-use.xx",
"Description[zh_CN]": "简约易用的手机主屏幕方案。",
"Description[zh_TW]": "著重於簡潔與易用性的手機主畫面。",
"Id": "org.kde.plasma.mobile.homescreen.halcyon",
"License": "GPLv2+",
"Name": "Halcyon",
"Name[ar]": "قيون",

View file

@ -8,19 +8,15 @@
#include <KLocalizedString>
PinnedModel::PinnedModel(QObject *parent)
PinnedModel::PinnedModel(Plasma::Applet *parent)
: QAbstractListModel{parent}
, m_applet{parent}
{
load();
}
PinnedModel::~PinnedModel() = default;
PinnedModel *PinnedModel::self()
{
static PinnedModel *inst = new PinnedModel();
return inst;
}
int PinnedModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
@ -249,10 +245,3 @@ Plasma::Applet *PinnedModel::applet()
{
return m_applet;
}
void PinnedModel::setApplet(Plasma::Applet *applet)
{
m_applet = applet;
Q_EMIT appletChanged();
load();
}

View file

@ -19,20 +19,26 @@
#include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h>
#include <qqmlregistration.h>
/**
* @short The applications and folders model on the main page.
*/
class PinnedModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(Plasma::Applet *applet READ applet WRITE setApplet NOTIFY appletChanged)
QML_ELEMENT
QML_UNCREATABLE("")
public:
enum Roles { IsFolderRole = Qt::UserRole + 1, ApplicationRole, FolderRole };
enum Roles {
IsFolderRole = Qt::UserRole + 1,
ApplicationRole,
FolderRole
};
PinnedModel(QObject *parent = nullptr);
PinnedModel(Plasma::Applet *parent = nullptr);
~PinnedModel() override;
static PinnedModel *self();
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@ -54,9 +60,6 @@ public:
public Q_SLOTS:
void addAppFromFolder(const QString &storageId);
Q_SIGNALS:
void appletChanged();
private:
void load();

View file

@ -1,30 +0,0 @@
# SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
# SPDX-License-Identifier: GPL-2.0-or-later
set(halcyonplugin_SRCS
halcyonplugin.cpp
application.cpp
applicationfolder.cpp
applicationlistmodel.cpp
pinnedmodel.cpp
windowlistener.cpp
)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/private/mobile/homescreen/halcyon)
add_library(halcyonplugin SHARED ${halcyonplugin_SRCS})
target_link_libraries(halcyonplugin
Qt::Gui
Qt::Qml
Qt::Quick
Plasma::Plasma
KF6::I18n
KF6::Service
KF6::KIOGui
KF6::JobWidgets
Plasma::KWaylandClient
KF6::WindowSystem)
set_property(TARGET halcyonplugin PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/org/kde/private/mobile/homescreen/halcyon)
install(TARGETS halcyonplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/private/mobile/homescreen/halcyon)

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "halcyonplugin.h"
#include "application.h"
#include "applicationfolder.h"
#include "applicationlistmodel.h"
#include "pinnedmodel.h"
#include "windowlistener.h"
void HalcyonPlugin::registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.private.mobile.homescreen.halcyon"));
WindowListener::instance(); // ensure it is created
qmlRegisterSingletonType<ApplicationListModel>(uri, 1, 0, "ApplicationListModel", [](QQmlEngine *, QJSEngine *) -> QObject * {
return ApplicationListModel::self();
});
qmlRegisterSingletonType<PinnedModel>(uri, 1, 0, "PinnedModel", [](QQmlEngine *, QJSEngine *) -> QObject * {
return PinnedModel::self();
});
qmlRegisterType<Application>(uri, 1, 0, "Application");
qmlRegisterType<ApplicationFolder>(uri, 1, 0, "ApplicationFolder");
}

View file

@ -1,16 +0,0 @@
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QQmlEngine>
#include <QQmlExtensionPlugin>
class HalcyonPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char *uri) override;
};

View file

@ -1,5 +0,0 @@
# SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
# SPDX-License-Identifier: GPL-2.0-or-later
module org.kde.private.mobile.homescreen.halcyon
plugin halcyonplugin

View file

@ -8,10 +8,11 @@ import QtQml.Models
import org.kde.plasma.components 3.0 as PC3
import org.kde.draganddrop as DragDrop
import org.kde.plasma.plasmoid
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.private.mobile.homescreen.halcyon as Halcyon
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
MobileShell.GridView {
id: root
@ -74,7 +75,7 @@ MobileShell.GridView {
Keys.onReturnPressed: currentItem.appDelegate.launch()
model: DelegateModel {
id: visualModel
model: Halcyon.PinnedModel
model: Plasmoid.pinnedModel
delegate: Item {
id: delegateRoot
@ -87,7 +88,7 @@ MobileShell.GridView {
function moveDragToCurrentPos(from, to) {
if (from !== to) {
visualModel.items.move(from, to);
Halcyon.PinnedModel.moveEntry(from, to);
Plasmoid.pinnedModel.moveEntry(from, to);
}
}
@ -189,9 +190,9 @@ MobileShell.GridView {
onDropped: (drop) => {
if (transitionAnim.running || appDelegate.drag.active || drag.source.isFolder) return; // don't do anything when reordering
if (appDelegate.isFolder) {
Halcyon.PinnedModel.addAppToFolder(drop.source.visualIndex, appDelegate.visualIndex);
Plasmoid.pinnedModel.addAppToFolder(drop.source.visualIndex, appDelegate.visualIndex);
} else {
Halcyon.PinnedModel.createFolderFromApps(drop.source.visualIndex, appDelegate.visualIndex);
Plasmoid.pinnedModel.createFolderFromApps(drop.source.visualIndex, appDelegate.visualIndex);
}
folderAnim.to = 0;
folderAnim.restart();
@ -221,7 +222,7 @@ MobileShell.GridView {
Kirigami.Action {
icon.name: "emblem-favorite"
text: i18n("Remove from favourites")
onTriggered: Halcyon.PinnedModel.removeEntry(model.index)
onTriggered: Plasmoid.pinnedModel.removeEntry(model.index)
}
]

View file

@ -12,7 +12,7 @@ import org.kde.draganddrop as DragDrop
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.private.mobile.homescreen.halcyon as Halcyon
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
MobileShell.GridView {
id: root

View file

@ -12,10 +12,11 @@ import QtQuick.Controls as Controls
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons
import org.kde.plasma.plasmoid
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.private.mobile.homescreen.halcyon as Halcyon
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
import org.kde.kirigami as Kirigami
@ -63,7 +64,7 @@ MouseArea {
icon.name: "emblem-favorite"
text: i18n("Add to favourites")
onClicked: {
Halcyon.PinnedModel.addApp(application.storageId, 0);
Plasmoid.pinnedModel.addApp(application.storageId, 0);
}
}
onClosed: dialogLoader.active = false

View file

@ -12,7 +12,7 @@ import org.kde.kirigami 2.10 as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.private.mobile.homescreen.halcyon 1.0 as Halcyon
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
import org.kde.plasma.plasmoid
MobileShell.GridView {

View file

@ -11,15 +11,15 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.private.mobile.homescreen.halcyon as Halcyon
import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
ContainmentItem {
id: root
Component.onCompleted: {
Halcyon.ApplicationListModel.loadApplications();
Halcyon.PinnedModel.applet = root.plasmoid;
forceActiveFocus();
}