mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
More familiar behavior for the App Drawer
This makes the behavior of the app drawer a bit more familiar and slightly more similar to Android for now: * The drawer always contains every application * Applications are always alphabetically ordered * The drawer opens completely, not staying stuck in "in between" states * is possible to drag more copies of a single app on the homescreen/favorites * possible to remove an icon from the homescreen or favorites Two things have been prepared in there (but are material for 5.22 only, so not finished) * Things have been reordered such in a way that makes easy for most of the qml files to become components to make easy for people to build their own customized homescreen * basic infrastructure is there to allow for multiple horizontal pages scroll, though not implemented yet as needs changes to plasma-workspace layouting code beforehand
This commit is contained in:
parent
cd4675b33e
commit
00d63af2da
19 changed files with 1441 additions and 370 deletions
|
|
@ -1,6 +1,7 @@
|
|||
set(homescreen_SRCS
|
||||
homescreen.cpp
|
||||
applicationlistmodel.cpp
|
||||
favoritesmodel.cpp
|
||||
)
|
||||
|
||||
add_library(plasma_containment_phone_homescreen MODULE ${homescreen_SRCS})
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ constexpr int MAX_FAVOURITES = 5;
|
|||
|
||||
ApplicationListModel::ApplicationListModel(HomeScreen *parent)
|
||||
: QAbstractListModel(parent),
|
||||
m_homeScreen(parent)
|
||||
m_applet(parent)
|
||||
{
|
||||
connect(KSycoca::self(), qOverload<const QStringList &>(&KSycoca::databaseChanged),
|
||||
this, &ApplicationListModel::sycocaDbChanged);
|
||||
|
|
@ -59,15 +59,18 @@ ApplicationListModel::~ApplicationListModel() = default;
|
|||
|
||||
void ApplicationListModel::loadSettings()
|
||||
{
|
||||
m_favorites = m_homeScreen->config().readEntry("Favorites", QStringList());
|
||||
if (!m_applet) {
|
||||
return;
|
||||
}
|
||||
m_favorites = m_applet->config().readEntry("Favorites", QStringList());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
const auto di = m_homeScreen->config().readEntry("DesktopItems", QStringList());
|
||||
const auto di = m_applet->config().readEntry("DesktopItems", QStringList());
|
||||
m_desktopItems = QSet<QString>(di.begin(), di.end());
|
||||
#else
|
||||
m_desktopItems = m_homeScreen->config().readEntry("DesktopItems", QStringList()).toSet();
|
||||
m_desktopItems = m_applet->config().readEntry("DesktopItems", QStringList()).toSet();
|
||||
#endif
|
||||
m_appOrder = m_homeScreen->config().readEntry("AppOrder", QStringList());
|
||||
m_maxFavoriteCount = m_homeScreen->config().readEntry("MaxFavoriteCount", MAX_FAVOURITES);
|
||||
m_appOrder = m_applet->config().readEntry("AppOrder", QStringList());
|
||||
m_maxFavoriteCount = m_applet->config().readEntry("MaxFavoriteCount", MAX_FAVOURITES);
|
||||
|
||||
int i = 0;
|
||||
for (const QString &app : qAsConst(m_appOrder)) {
|
||||
|
|
@ -75,7 +78,7 @@ void ApplicationListModel::loadSettings()
|
|||
++i;
|
||||
}
|
||||
|
||||
loadApplications();
|
||||
//loadApplications();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApplicationListModel::roleNames() const
|
||||
|
|
@ -88,7 +91,8 @@ QHash<int, QByteArray> ApplicationListModel::roleNames() const
|
|||
{ApplicationOriginalRowRole, QByteArrayLiteral("applicationOriginalRow")},
|
||||
{ApplicationStartupNotifyRole, QByteArrayLiteral("applicationStartupNotify")},
|
||||
{ApplicationLocationRole, QByteArrayLiteral("applicationLocation")},
|
||||
{ApplicationRunningRole, QByteArrayLiteral("applicationRunning")}
|
||||
{ApplicationRunningRole, QByteArrayLiteral("applicationRunning")},
|
||||
{ApplicationUniqueIdRole, QByteArrayLiteral("applicationUniqueId")}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -208,17 +212,18 @@ void ApplicationListModel::loadApplications()
|
|||
data.name = service->name();
|
||||
data.icon = service->icon();
|
||||
data.storageId = service->storageId();
|
||||
data.uniqueId = service->storageId();
|
||||
data.entryPath = service->exec();
|
||||
data.startupNotify = service->property(QStringLiteral("StartupNotify")).toBool();
|
||||
|
||||
if (m_favorites.contains(data.storageId)) {
|
||||
if (m_favorites.contains(data.uniqueId)) {
|
||||
data.location = Favorites;
|
||||
foundFavorites.insert(data.storageId);
|
||||
} else if (m_desktopItems.contains(data.storageId)) {
|
||||
foundFavorites.insert(data.uniqueId);
|
||||
} else if (m_desktopItems.contains(data.uniqueId)) {
|
||||
data.location = Desktop;
|
||||
}
|
||||
|
||||
auto it = m_appPositions.constFind(service->storageId());
|
||||
auto it = m_appPositions.constFind(data.uniqueId);
|
||||
if (it != m_appPositions.constEnd()) {
|
||||
orderedList[*it] = data;
|
||||
} else {
|
||||
|
|
@ -249,7 +254,9 @@ void ApplicationListModel::loadApplications()
|
|||
}
|
||||
}
|
||||
if (favChanged) {
|
||||
m_homeScreen->config().writeEntry("Favorites", m_favorites);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
}
|
||||
emit favoriteCountChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -278,6 +285,8 @@ QVariant ApplicationListModel::data(const QModelIndex &index, int role) const
|
|||
return m_applicationList.at(index.row()).location;
|
||||
case ApplicationRunningRole:
|
||||
return m_applicationList.at(index.row()).window != nullptr;
|
||||
case ApplicationUniqueIdRole:
|
||||
return m_applicationList.at(index.row()).uniqueId;
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
|
|
@ -319,35 +328,46 @@ void ApplicationListModel::setLocation(int row, LauncherLocation location)
|
|||
if (location == Favorites) {
|
||||
qWarning() << "favoriting" << row << data.name;
|
||||
// Deny favorites when full
|
||||
if (row >= m_maxFavoriteCount || m_favorites.count() >= m_maxFavoriteCount) {
|
||||
if (row >= m_maxFavoriteCount || m_favorites.count() >= m_maxFavoriteCount ||
|
||||
m_favorites.contains(data.uniqueId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_favorites.insert(row, data.storageId);
|
||||
m_favorites.insert(row, data.uniqueId);
|
||||
|
||||
m_homeScreen->config().writeEntry("Favorites", m_favorites);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
}
|
||||
emit favoriteCountChanged();
|
||||
|
||||
// Out of favorites
|
||||
} else if (data.location == Favorites) {
|
||||
m_favorites.removeAll(data.storageId);
|
||||
m_homeScreen->config().writeEntry("Favorites", m_favorites);
|
||||
m_favorites.removeAll(data.uniqueId);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
}
|
||||
emit favoriteCountChanged();
|
||||
}
|
||||
|
||||
// In Desktop
|
||||
if (location == Desktop) {
|
||||
m_desktopItems.insert(data.storageId);
|
||||
m_homeScreen->config().writeEntry("DesktopItems", m_desktopItems.values());
|
||||
m_desktopItems.insert(data.uniqueId);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
|
||||
}
|
||||
|
||||
// Out of Desktop
|
||||
} else if (data.location == Desktop) {
|
||||
m_desktopItems.remove(data.storageId);
|
||||
m_homeScreen->config().writeEntry(QStringLiteral("DesktopItems"), m_desktopItems.values());
|
||||
m_desktopItems.remove(data.uniqueId);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry(QStringLiteral("DesktopItems"), m_desktopItems.values());
|
||||
}
|
||||
}
|
||||
|
||||
data.location = location;
|
||||
emit m_homeScreen->configNeedsSaving();
|
||||
if (m_applet) {
|
||||
emit m_applet->configNeedsSaving();
|
||||
}
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
|
||||
|
|
@ -377,12 +397,14 @@ void ApplicationListModel::moveItem(int row, int destination)
|
|||
m_appPositions.clear();
|
||||
int i = 0;
|
||||
for (const ApplicationData &app : qAsConst(m_applicationList)) {
|
||||
m_appOrder << app.storageId;
|
||||
m_appPositions[app.storageId] = i;
|
||||
m_appOrder << app.uniqueId;
|
||||
m_appPositions[app.uniqueId] = i;
|
||||
++i;
|
||||
}
|
||||
|
||||
m_homeScreen->config().writeEntry("AppOrder", m_appOrder);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("AppOrder", m_appOrder);
|
||||
}
|
||||
|
||||
endMoveRows();
|
||||
}
|
||||
|
|
@ -434,11 +456,23 @@ void ApplicationListModel::setMaxFavoriteCount(int count)
|
|||
}
|
||||
|
||||
m_maxFavoriteCount = count;
|
||||
m_homeScreen->config().writeEntry("MaxFavoriteCount", m_maxFavoriteCount);
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("MaxFavoriteCount", m_maxFavoriteCount);
|
||||
}
|
||||
|
||||
emit maxFavoriteCountChanged();
|
||||
}
|
||||
|
||||
Plasma::Applet *ApplicationListModel::applet() const
|
||||
{
|
||||
return m_applet;
|
||||
}
|
||||
|
||||
void ApplicationListModel::setApplet(Plasma::Applet *applet)
|
||||
{
|
||||
m_applet = applet;
|
||||
}
|
||||
|
||||
void ApplicationListModel::setMinimizedDelegate(int row, QQuickItem *delegate)
|
||||
{
|
||||
if (row < 0 || row >= m_applicationList.count()) {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
Q_ENUM(LauncherLocation)
|
||||
|
||||
struct ApplicationData {
|
||||
QString uniqueId;
|
||||
QString name;
|
||||
QString icon;
|
||||
QString storageId;
|
||||
|
|
@ -74,7 +75,8 @@ public:
|
|||
ApplicationOriginalRowRole,
|
||||
ApplicationStartupNotifyRole,
|
||||
ApplicationLocationRole,
|
||||
ApplicationRunningRole
|
||||
ApplicationRunningRole,
|
||||
ApplicationUniqueIdRole
|
||||
};
|
||||
|
||||
ApplicationListModel(HomeScreen *parent = nullptr);
|
||||
|
|
@ -92,6 +94,9 @@ public:
|
|||
int maxFavoriteCount() const;
|
||||
void setMaxFavoriteCount(int count);
|
||||
|
||||
void setApplet(Plasma::Applet *applet);
|
||||
Plasma::Applet *applet() const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
|
@ -104,7 +109,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void runApplication(const QString &storageId);
|
||||
|
||||
Q_INVOKABLE void loadApplications();
|
||||
Q_INVOKABLE virtual void loadApplications();
|
||||
|
||||
Q_INVOKABLE void setMinimizedDelegate(int row, QQuickItem *delegate);
|
||||
Q_INVOKABLE void unsetMinimizedDelegate(int row, QQuickItem *delegate);
|
||||
|
|
@ -117,13 +122,13 @@ Q_SIGNALS:
|
|||
void favoriteCountChanged();
|
||||
void maxFavoriteCountChanged();
|
||||
|
||||
private:
|
||||
protected:
|
||||
void initWayland();
|
||||
|
||||
QList<ApplicationData> m_applicationList;
|
||||
|
||||
KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr;
|
||||
HomeScreen *m_homeScreen = nullptr;
|
||||
Plasma::Applet *m_applet = nullptr;
|
||||
int m_maxFavoriteCount = 0;
|
||||
QStringList m_appOrder;
|
||||
QStringList m_favorites;
|
||||
|
|
|
|||
199
containments/homescreen/favoritesmodel.cpp
Normal file
199
containments/homescreen/favoritesmodel.cpp
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* or (at your option) any later version, as published by the Free
|
||||
* Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Self
|
||||
#include "favoritesmodel.h"
|
||||
|
||||
// Qt
|
||||
#include <QByteArray>
|
||||
#include <QModelIndex>
|
||||
#include <QDebug>
|
||||
|
||||
// KDE
|
||||
#include <KService>
|
||||
#include <KSharedConfig>
|
||||
|
||||
|
||||
constexpr int MAX_FAVOURITES = 5;
|
||||
|
||||
FavoritesModel::FavoritesModel(HomeScreen *parent)
|
||||
: ApplicationListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
FavoritesModel::~FavoritesModel() = default;
|
||||
|
||||
|
||||
QString FavoritesModel::storageToUniqueId(const QString &storageId) const
|
||||
{
|
||||
if (storageId.isEmpty()) {
|
||||
return storageId;
|
||||
}
|
||||
|
||||
int id = 0;
|
||||
QString uniqueId = storageId + QStringLiteral("-") + QString::number(id);
|
||||
|
||||
while (m_appOrder.contains(uniqueId)) {
|
||||
uniqueId = storageId + QStringLiteral("-") + QString::number(++id);
|
||||
}
|
||||
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
QString FavoritesModel::uniqueToStorageId(const QString &uniqueId) const
|
||||
{
|
||||
if (uniqueId.isEmpty()) {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
return uniqueId.split(QLatin1Char('-')).first();
|
||||
}
|
||||
|
||||
|
||||
void FavoritesModel::loadApplications()
|
||||
{
|
||||
|
||||
beginResetModel();
|
||||
|
||||
m_applicationList.clear();
|
||||
|
||||
QSet<QString> appsToRemove;
|
||||
|
||||
for (const auto &uniqueId : m_appOrder) {
|
||||
const QString storageId = uniqueToStorageId(uniqueId);
|
||||
if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
|
||||
ApplicationData data;
|
||||
data.name = service->name();
|
||||
data.icon = service->icon();
|
||||
data.storageId = service->storageId();
|
||||
data.uniqueId = uniqueId;
|
||||
data.entryPath = service->exec();
|
||||
data.startupNotify = service->property(QStringLiteral("StartupNotify")).toBool();
|
||||
|
||||
if (m_favorites.contains(uniqueId)) {
|
||||
data.location = Favorites;
|
||||
} else if (m_desktopItems.contains(uniqueId)) {
|
||||
data.location = Desktop;
|
||||
}
|
||||
|
||||
m_applicationList << data;
|
||||
} else {
|
||||
appsToRemove.insert(uniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
bool favChanged = false;
|
||||
|
||||
for (const auto &uniqueId : appsToRemove) {
|
||||
m_appOrder.removeAll(uniqueId);
|
||||
if (m_favorites.contains(uniqueId)) {
|
||||
favChanged = true;
|
||||
m_favorites.removeAll(uniqueId);
|
||||
}
|
||||
m_desktopItems.remove(uniqueId);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
m_applet->config().writeEntry("AppOrder", m_appOrder);
|
||||
m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
|
||||
emit m_applet->configNeedsSaving();
|
||||
}
|
||||
|
||||
if (favChanged) {
|
||||
emit favoriteCountChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesModel::addFavorite(const QString &storageId, int row, LauncherLocation location)
|
||||
{
|
||||
if (row < 0 || row > m_applicationList.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
|
||||
const QString uniqueId = storageToUniqueId(service->storageId());
|
||||
ApplicationData data;
|
||||
data.name = service->name();
|
||||
data.icon = service->icon();
|
||||
data.storageId = service->storageId();
|
||||
data.uniqueId = uniqueId;
|
||||
data.entryPath = service->exec();
|
||||
data.startupNotify = service->property(QStringLiteral("StartupNotify")).toBool();
|
||||
|
||||
bool favChanged = false;
|
||||
if (location == Favorites) {
|
||||
data.location = Favorites;
|
||||
m_favorites.insert(qMin(row, m_favorites.count()), uniqueId);
|
||||
favChanged = true;
|
||||
} else {
|
||||
data.location = location;
|
||||
m_desktopItems.insert(data.uniqueId);
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
m_applicationList.insert(row, data);
|
||||
m_appOrder.insert(row, uniqueId);
|
||||
endInsertRows();
|
||||
if (favChanged) {
|
||||
emit favoriteCountChanged();
|
||||
}
|
||||
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
m_applet->config().writeEntry("AppOrder", m_appOrder);
|
||||
m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
|
||||
emit m_applet->configNeedsSaving();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesModel::removeFavorite(int row)
|
||||
{
|
||||
if (row < 0 || row >= m_applicationList.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
const QString uniqueId = m_applicationList[row].uniqueId;
|
||||
m_appOrder.removeAll(uniqueId);
|
||||
const bool favChanged = m_favorites.contains(uniqueId);
|
||||
m_favorites.removeAll(uniqueId);
|
||||
m_desktopItems.remove(uniqueId);
|
||||
m_appPositions.remove(uniqueId);
|
||||
m_applicationList.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
if (favChanged) {
|
||||
emit favoriteCountChanged();
|
||||
}
|
||||
|
||||
if (m_applet) {
|
||||
m_applet->config().writeEntry("Favorites", m_favorites);
|
||||
m_applet->config().writeEntry("AppOrder", m_appOrder);
|
||||
m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
|
||||
emit m_applet->configNeedsSaving();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_favoritesmodel.cpp"
|
||||
|
||||
62
containments/homescreen/favoritesmodel.h
Normal file
62
containments/homescreen/favoritesmodel.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* or (at your option) any later version, as published by the Free
|
||||
* Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <QAbstractListModel>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
|
||||
#include "homescreen.h"
|
||||
#include "applicationlistmodel.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class PlasmaWindowManagement;
|
||||
class PlasmaWindow;
|
||||
}
|
||||
}
|
||||
|
||||
class FavoritesModel;
|
||||
|
||||
class FavoritesModel : public ApplicationListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FavoritesModel(HomeScreen *parent = nullptr);
|
||||
~FavoritesModel() override;
|
||||
|
||||
|
||||
QString storageToUniqueId(const QString &storageId) const;
|
||||
QString uniqueToStorageId(const QString &uniqueId) const;
|
||||
|
||||
Q_INVOKABLE void addFavorite(const QString &storageId, int row, LauncherLocation location);
|
||||
Q_INVOKABLE void removeFavorite(int row);
|
||||
|
||||
Q_INVOKABLE void loadApplications() override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "homescreen.h"
|
||||
#include "applicationlistmodel.h"
|
||||
#include "favoritesmodel.h"
|
||||
|
||||
#include <QtQml>
|
||||
#include <QDebug>
|
||||
|
|
@ -27,7 +28,8 @@
|
|||
HomeScreen::HomeScreen(QObject *parent, const QVariantList &args)
|
||||
: Plasma::Containment(parent, args)
|
||||
{
|
||||
qmlRegisterUncreatableType<ApplicationListModel>("org.kde.phone.homescreen", 1, 0, "ApplicationListModel", QStringLiteral("Cannot create item of type ApplicationListModel"));
|
||||
qmlRegisterType<ApplicationListModel>("org.kde.phone.homescreen", 1, 0, "ApplicationListModel");
|
||||
qmlRegisterType<FavoritesModel>("org.kde.phone.homescreen", 1, 0, "FavoritesModel");
|
||||
|
||||
setHasConfigurationInterface(true);
|
||||
}
|
||||
|
|
@ -45,7 +47,13 @@ void HomeScreen::configChanged()
|
|||
ApplicationListModel *HomeScreen::applicationListModel()
|
||||
{
|
||||
if (!m_applicationListModel) {
|
||||
m_applicationListModel = new ApplicationListModel(this);
|
||||
if (m_showAllApps) {
|
||||
m_applicationListModel = new ApplicationListModel(this);
|
||||
} else {
|
||||
m_applicationListModel = new FavoritesModel(this);
|
||||
}
|
||||
m_applicationListModel->setApplet(this);
|
||||
m_applicationListModel->loadApplications();
|
||||
}
|
||||
return m_applicationListModel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
class QQuickItem;
|
||||
class ApplicationListModel;
|
||||
class FavoritesModel;
|
||||
|
||||
class HomeScreen : public Plasma::Containment
|
||||
{
|
||||
|
|
@ -48,7 +49,7 @@ protected:
|
|||
|
||||
private:
|
||||
ApplicationListModel *m_applicationListModel = nullptr;
|
||||
|
||||
bool m_showAllApps = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ import QtGraphicalEffects 1.6
|
|||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
|
||||
PlasmaCore.SvgItem {
|
||||
id: scrollDownIndicator
|
||||
id: scrollIndicator
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
z: 2
|
||||
opacity: 0
|
||||
svg: arrowsSvg
|
||||
elementId: "down-arrow"
|
||||
elementId: "left-arrow"
|
||||
width: units.iconSizes.large
|
||||
height: width
|
||||
layer.enabled: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* Copyright 2021 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
//import org.kde.kquickcontrolsaddons 2.0
|
||||
import org.kde.kirigami 2.10 as Kirigami
|
||||
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
import org.kde.phone.homescreen 1.0
|
||||
|
||||
import "private"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
enum Status {
|
||||
Closed,
|
||||
Peeking,
|
||||
Open
|
||||
}
|
||||
|
||||
enum MovementDirection {
|
||||
None = 0,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
|
||||
readonly property int status: {
|
||||
if (view.contentY >= -view.originY - view.height) {
|
||||
return AppDrawer.Status.Open;
|
||||
} else if (view.contentY > -view.originY - view.height*2) {
|
||||
return AppDrawer.Status.Peeking;
|
||||
} else {
|
||||
return AppDrawer.Status.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
property real offset: 0
|
||||
|
||||
property real leftPadding: 0
|
||||
property real topPadding: 0
|
||||
property real bottomPadding: 100
|
||||
property real rightPadding: 0
|
||||
|
||||
readonly property int columns: Math.floor(view.width / cellWidth)
|
||||
property alias cellWidth: view.cellWidth
|
||||
property alias cellHeight: view.cellHeight
|
||||
signal launched
|
||||
signal dragStarted
|
||||
|
||||
readonly property int reservedSpaceForLabel: metrics.height
|
||||
property int availableCellHeight: units.iconSizes.huge + reservedSpaceForLabel
|
||||
|
||||
property alias flickable: view
|
||||
|
||||
readonly property real openFactor: Math.min(1, Math.max(0, Math.min(1, (view.contentY + view.originY + view.height*2) / (units.gridUnit * 10))))
|
||||
|
||||
function open() {
|
||||
if (root.status === AppDrawer.Status.Open) {
|
||||
view.flick(0,1);
|
||||
} else {
|
||||
scrollAnim.to = 0
|
||||
scrollAnim.restart();
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (root.status !== AppDrawer.Status.Closed) {
|
||||
scrollAnim.to = -view.height;
|
||||
scrollAnim.restart();
|
||||
}
|
||||
}
|
||||
|
||||
function snapDrawerStatus() {
|
||||
if (root.status !== AppDrawer.Status.Peeking) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.movementDirection === AppDrawer.MovementDirection.Up) {
|
||||
open();
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
Drag.dragType: Drag.Automatic
|
||||
|
||||
onOffsetChanged: {
|
||||
if (!view.moving) {
|
||||
view.contentY = Math.max(0, offset) - view.originY - view.height*2
|
||||
}
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: scrollAnim
|
||||
target: view
|
||||
properties: "contentY"
|
||||
duration: units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
PC3.Label {
|
||||
id: metrics
|
||||
text: "M\nM"
|
||||
visible: false
|
||||
font.pointSize: theme.defaultFont.pointSize * 0.9
|
||||
}
|
||||
|
||||
OpenDrawerButton {
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: scrim.top
|
||||
}
|
||||
factor: root.openFactor
|
||||
flickable: view
|
||||
onOpenRequested: root.open();
|
||||
onCloseRequested: root.close();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: scrim
|
||||
anchors {
|
||||
left: view.left
|
||||
right: view.right
|
||||
leftMargin: -1
|
||||
rightMargin: -1
|
||||
}
|
||||
border.color: Qt.rgba(1, 1, 1, 0.5)
|
||||
radius: units.gridUnit
|
||||
color: "black"
|
||||
opacity: 0.4 * root.openFactor
|
||||
height: root.height + radius * 2
|
||||
y: Math.min(view.height, Math.max(-radius, -view.contentY - view.originY - root.height + root.topPadding + root.bottomPadding))
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: closeTimer
|
||||
interval: 1000
|
||||
onTriggered: root.close();
|
||||
}
|
||||
GridView {
|
||||
id: view
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: root.leftPadding
|
||||
topMargin: root.topPadding
|
||||
rightMargin: root.rightPadding
|
||||
bottomMargin: root.bottomPadding
|
||||
}
|
||||
|
||||
visible: root.status !== AppDrawer.Status.Closed
|
||||
cellWidth: view.width / Math.floor(view.width / ((root.availableCellHeight - root.reservedSpaceForLabel) + units.smallSpacing*4))
|
||||
cellHeight: root.availableCellHeight
|
||||
clip: true
|
||||
|
||||
cacheBuffer: contentHeight
|
||||
|
||||
property real oldContentY: contentY
|
||||
property int movementDirection: AppDrawer.MovementDirection.None
|
||||
onContentYChanged: {
|
||||
if (contentY > oldContentY) {
|
||||
movementDirection = AppDrawer.MovementDirection.Up;
|
||||
} else {
|
||||
movementDirection = AppDrawer.MovementDirection.Down;
|
||||
}
|
||||
oldContentY = contentY;
|
||||
root.offset = contentY + view.originY + view.height*2
|
||||
}
|
||||
onMovementEnded: root.snapDrawerStatus()
|
||||
onFlickEnded: movementEnded()
|
||||
|
||||
// boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
model: ApplicationListModel {
|
||||
id: allApplicationsModel
|
||||
Component.onCompleted: loadApplications()
|
||||
}
|
||||
|
||||
header: Item {
|
||||
height: root.height - root.topPadding - root.bottomPadding
|
||||
property real oldHeight: height
|
||||
onHeightChanged: {
|
||||
if (root.status !== AppDrawer.Status.Open) {
|
||||
view.contentY = -view.height;
|
||||
}
|
||||
oldHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
delegate: DrawerDelegate {
|
||||
id: delegate
|
||||
width: view.cellWidth
|
||||
height: view.cellHeight
|
||||
reservedSpaceForLabel: root.reservedSpaceForLabel
|
||||
|
||||
onDragStarted: (imageSource, x, y, mimeData) => {
|
||||
root.Drag.imageSource = imageSource;
|
||||
root.Drag.hotSpot.x = x;
|
||||
root.Drag.hotSpot.y = y;
|
||||
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
||||
|
||||
root.close()
|
||||
|
||||
root.dragStarted()
|
||||
root.Drag.active = true;
|
||||
}
|
||||
onLaunch: (x, y, icon, title, storageId) => {
|
||||
if (icon !== "") {
|
||||
NanoShell.StartupFeedback.open(
|
||||
icon,
|
||||
title,
|
||||
delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2,
|
||||
delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2,
|
||||
Math.min(delegate.iconItem.width, delegate.iconItem.height));
|
||||
}
|
||||
|
||||
allApplicationsModel.setMinimizedDelegate(index, delegate);
|
||||
allApplicationsModel.runApplication(storageId);
|
||||
root.launched();
|
||||
closeTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
PC3.ScrollBar.vertical: PC3.ScrollBar {
|
||||
id: scrollabr
|
||||
opacity: view.moving
|
||||
interactive: false
|
||||
enabled: false
|
||||
Behavior on opacity {
|
||||
OpacityAnimator {
|
||||
duration: units.longDuration * 2
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
implicitWidth: Math.round(units.gridUnit/3)
|
||||
contentItem: Rectangle {
|
||||
radius: width/2
|
||||
color: Qt.rgba(1, 1, 1, 0.3)
|
||||
border.color: Qt.rgba(0, 0, 0, 0.4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
leftMargin: units.gridUnit + root.leftPadding
|
||||
rightMargin: units.gridUnit + root.rightPadding
|
||||
bottomMargin: root.bottomPadding - height
|
||||
}
|
||||
height: 1
|
||||
visible: root.bottomPadding > 0
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: Qt.rgba(1, 1, 1, 0) }
|
||||
GradientStop { position: 0.15; color: Qt.rgba(1, 1, 1, 0.5) }
|
||||
GradientStop { position: 0.5; color: Qt.rgba(1, 1, 1, 1) }
|
||||
GradientStop { position: 0.85; color: Qt.rgba(1, 1, 1, 0.5) }
|
||||
GradientStop { position: 1.0; color: Qt.rgba(1, 1, 1, 0) }
|
||||
}
|
||||
opacity: root.status !== AppDrawer.Status.Closed ? 0.6 : 0
|
||||
Behavior on opacity {
|
||||
OpacityAnimator {
|
||||
duration: units.longDuration * 2
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2019 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3 as Controls
|
||||
import QtGraphicalEffects 1.6
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.kquickcontrolsaddons 2.0
|
||||
|
||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
import org.kde.phone.homescreen 1.0
|
||||
|
||||
MouseArea {
|
||||
id: delegate
|
||||
width: GridView.view.cellWidth
|
||||
height: GridView.view.cellHeight
|
||||
|
||||
property int reservedSpaceForLabel
|
||||
property alias iconItem: icon
|
||||
|
||||
signal launch(int x, int y, var source, string title, string storageId)
|
||||
signal dragStarted(string imageSource, int x, int y, string mimeData)
|
||||
|
||||
onPressAndHold: {
|
||||
delegate.grabToImage(function(result) {
|
||||
delegate.Drag.imageSource = result.url
|
||||
dragStarted(result.url, width/2, height/2, model.applicationStorageId)
|
||||
})
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (model.applicationRunning) {
|
||||
delegate.launch(0, 0, "", model.applicationName, model.applicationStorageId);
|
||||
} else {
|
||||
delegate.launch(delegate.x + (units.smallSpacing * 2), delegate.y + (units.smallSpacing * 2), icon.source, model.applicationName, model.applicationStorageId);
|
||||
}
|
||||
}
|
||||
|
||||
//preventStealing: true
|
||||
ColumnLayout {
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: units.smallSpacing * 2
|
||||
topMargin: units.smallSpacing * 2
|
||||
rightMargin: units.smallSpacing * 2
|
||||
bottomMargin: units.smallSpacing * 2
|
||||
}
|
||||
spacing: 0
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: icon
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: parent.height - delegate.reservedSpaceForLabel
|
||||
Layout.preferredHeight: Layout.minimumHeight
|
||||
|
||||
usesPlasmaTheme: false
|
||||
source: model.applicationIcon
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
}
|
||||
visible: model.applicationRunning
|
||||
radius: width
|
||||
width: units.smallSpacing
|
||||
height: width
|
||||
color: theme.highlightColor
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: label
|
||||
visible: text.length > 0
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: delegate.reservedSpaceForLabel
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.leftMargin: -parent.anchors.leftMargin + units.smallSpacing
|
||||
Layout.rightMargin: -parent.anchors.rightMargin + units.smallSpacing
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
maximumLineCount: 2
|
||||
elide: Text.ElideRight
|
||||
|
||||
text: model.applicationName
|
||||
|
||||
//FIXME: export smallestReadableFont
|
||||
font.pointSize: theme.defaultFont.pointSize * 0.9
|
||||
color: "white"//model.applicationLocation == ApplicationListModel.Desktop ? "white" : theme.textColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,18 +29,17 @@ import org.kde.kquickcontrolsaddons 2.0
|
|||
LauncherContainer {
|
||||
id: root
|
||||
|
||||
readonly property int count: flow.width / launcherGrid.cellWidth
|
||||
readonly property int count: flow.width / cellWidth
|
||||
|
||||
flow.flow: Flow.TopToBottom
|
||||
favoriteStrip: root
|
||||
|
||||
visible: flow.children.length > 0 || launcherDragManager.active
|
||||
visible: flow.children.length > 0 || launcherDragManager.active || dropArea.containsDrag
|
||||
|
||||
opacity: launcherDragManager.active && plasmoid.nativeInterface.applicationListModel.favoriteCount >= plasmoid.nativeInterface.applicationListModel.maxFavoriteCount ? 0.3 : 1
|
||||
|
||||
height: visible ? launcherGrid.cellHeight : 0
|
||||
height: visible ? cellHeight : 0
|
||||
|
||||
frame.implicitWidth: launcherGrid.cellWidth * Math.max(1, flow.children.length) + frame.leftPadding + frame.rightPadding
|
||||
frame.implicitWidth: cellWidth * Math.max(1, flow.children.length) + frame.leftPadding + frame.rightPadding
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
|
|
|
|||
|
|
@ -23,13 +23,15 @@ import QtGraphicalEffects 1.6
|
|||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.kquickcontrolsaddons 2.0
|
||||
|
||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
import org.kde.phone.homescreen 1.0
|
||||
|
||||
import "private" as Private
|
||||
|
||||
ContainmentLayoutManager.ItemContainer {
|
||||
id: delegate
|
||||
|
||||
|
|
@ -37,12 +39,12 @@ ContainmentLayoutManager.ItemContainer {
|
|||
|
||||
property var modelData: typeof model !== "undefined" ? model : null
|
||||
|
||||
Layout.minimumWidth: launcherGrid.cellWidth
|
||||
Layout.minimumHeight: launcherGrid.cellHeight
|
||||
Layout.minimumWidth: appletsLayout.cellWidth
|
||||
Layout.minimumHeight: appletsLayout.cellHeight
|
||||
|
||||
opacity: dragActive ? 0.4 : 1
|
||||
|
||||
key: model.applicationStorageId
|
||||
key: model.applicationUniqueId
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||
property int reservedSpaceForLabel
|
||||
property real dragCenterX
|
||||
property real dragCenterY
|
||||
property alias iconItem: icon
|
||||
|
|
@ -82,18 +84,28 @@ ContainmentLayoutManager.ItemContainer {
|
|||
syncDelegateGeometry();
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: appletsLayout
|
||||
function onAppletsLayoutInteracted() {
|
||||
removeButton.hide();
|
||||
}
|
||||
}
|
||||
|
||||
onDragActiveChanged: {
|
||||
launcherDragManager.active = dragActive
|
||||
if (dragActive) {
|
||||
// Must be 0, 0 as at this point dragCenterX and dragCenterY are on the drag before"
|
||||
launcherDragManager.startDrag(delegate);
|
||||
launcherDragManager.currentlyDraggedDelegate = delegate;
|
||||
removeButton.show();
|
||||
mouseArea.enabled = true;
|
||||
} else {
|
||||
launcherDragManager.dropItem(delegate, dragCenterX, dragCenterY);
|
||||
plasmoid.editMode = false;
|
||||
editMode = false;
|
||||
plasmoid.fullRepresentationItem.stopScroll();
|
||||
launcherDragManager.currentlyDraggedDelegate = null;
|
||||
forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,16 +114,16 @@ ContainmentLayoutManager.ItemContainer {
|
|||
dragCenterY = dragCenter.y;
|
||||
launcherDragManager.dragItem(delegate, dragCenter.x, dragCenter.y);
|
||||
|
||||
delegate.width = launcherGrid.cellWidth;
|
||||
delegate.height = launcherGrid.cellHeight;
|
||||
delegate.width = appletsLayout.cellWidth;
|
||||
delegate.height = appletsLayout.cellHeight;
|
||||
|
||||
var pos = plasmoid.fullRepresentationItem.mapFromItem(delegate, dragCenter.x, dragCenter.y);
|
||||
//SCROLL UP
|
||||
if (pos.y < plasmoid.availableScreenRect.y + units.gridUnit) {
|
||||
plasmoid.fullRepresentationItem.scrollUp();
|
||||
//SCROLL DOWN
|
||||
} else if (pos.y > plasmoid.availableScreenRect.y + plasmoid.availableScreenRect.height - units.gridUnit) {
|
||||
plasmoid.fullRepresentationItem.scrollDown();
|
||||
//SCROLL LEFT
|
||||
if (pos.x < plasmoid.availableScreenRect.x + units.gridUnit) {
|
||||
plasmoid.fullRepresentationItem.scrollLeft();
|
||||
//SCROLL RIGHT
|
||||
} else if (pos.x > plasmoid.availableScreenRect.x + plasmoid.availableScreenRect.width - units.gridUnit) {
|
||||
plasmoid.fullRepresentationItem.scrollRight();
|
||||
//DON't SCROLL
|
||||
} else {
|
||||
plasmoid.fullRepresentationItem.stopScroll();
|
||||
|
|
@ -119,6 +131,7 @@ ContainmentLayoutManager.ItemContainer {
|
|||
}
|
||||
|
||||
contentItem: MouseArea {
|
||||
id: mouseArea
|
||||
onClicked: {
|
||||
if (modelData.applicationRunning) {
|
||||
delegate.launch(0, 0, "", modelData.applicationName);
|
||||
|
|
@ -126,6 +139,7 @@ ContainmentLayoutManager.ItemContainer {
|
|||
delegate.launch(delegate.x + (units.smallSpacing * 2), delegate.y + (units.smallSpacing * 2), icon.source, modelData.applicationName);
|
||||
}
|
||||
|
||||
plasmoid.nativeInterface.applicationListModel.setMinimizedDelegate(index, delegate);
|
||||
plasmoid.nativeInterface.applicationListModel.runApplication(modelData.applicationStorageId);
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +159,7 @@ ContainmentLayoutManager.ItemContainer {
|
|||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: parent.height - root.reservedSpaceForLabel
|
||||
Layout.minimumHeight: Math.min(units.iconSizes.large, parent.height - delegate.reservedSpaceForLabel)
|
||||
Layout.preferredHeight: Layout.minimumHeight
|
||||
|
||||
usesPlasmaTheme: false
|
||||
|
|
@ -162,15 +176,20 @@ ContainmentLayoutManager.ItemContainer {
|
|||
height: width
|
||||
color: theme.highlightColor
|
||||
}
|
||||
//TODO: in loader?
|
||||
Private.DelegateRemoveButton {
|
||||
id: removeButton
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
PC3.Label {
|
||||
id: label
|
||||
visible: text.length > 0
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.reservedSpaceForLabel
|
||||
Layout.preferredHeight: delegate.reservedSpaceForLabel
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.leftMargin: -parent.anchors.leftMargin + units.smallSpacing
|
||||
Layout.rightMargin: -parent.anchors.rightMargin + units.smallSpacing
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
|
@ -194,6 +213,7 @@ ContainmentLayoutManager.ItemContainer {
|
|||
color: Qt.rgba(0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
Item {Layout.fillHeight:true}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,11 +31,11 @@ Item {
|
|||
id: root
|
||||
|
||||
readonly property int reservedSpaceForLabel: metrics.height
|
||||
readonly property int cellWidth: root.width / Math.floor(root.width / ((availableCellHeight - reservedSpaceForLabel) + units.smallSpacing*4))
|
||||
readonly property int cellHeight: availableCellHeight
|
||||
property int availableCellHeight: units.iconSizes.huge + reservedSpaceForLabel
|
||||
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||
property Item launcherGrid
|
||||
property Item favoriteStrip
|
||||
|
||||
property alias frame: frame
|
||||
property alias flow: applicationsFlow
|
||||
|
|
@ -61,6 +61,7 @@ Item {
|
|||
anchors.centerIn: parent
|
||||
implicitWidth: contentItem.implicitWidth
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
height: parent.height
|
||||
|
||||
leftPadding: 0
|
||||
topPadding: 0
|
||||
|
|
|
|||
|
|
@ -27,18 +27,18 @@ Item {
|
|||
id: root
|
||||
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||
property LauncherGrid launcherGrid
|
||||
property FavoriteStrip favoriteStrip
|
||||
property Delegate currentlyDraggedDelegate
|
||||
property HomeDelegate currentlyDraggedDelegate
|
||||
property bool active
|
||||
property QtObject model: plasmoid.nativeInterface.applicationListModel
|
||||
|
||||
readonly property Item spacer: Item {
|
||||
width: launcherGrid.cellWidth
|
||||
height: launcherGrid.cellHeight
|
||||
width: favoriteStrip.cellWidth
|
||||
height: favoriteStrip.cellHeight
|
||||
}
|
||||
|
||||
function startDrag(item) {
|
||||
internal.showSpacer(item, 0, 0);
|
||||
showSpacer(item, 0, 0);
|
||||
}
|
||||
|
||||
function dragItem(delegate, dragCenterX, dragCenterY) {
|
||||
|
|
@ -46,34 +46,28 @@ Item {
|
|||
var newRow = 0;
|
||||
|
||||
var newContainer = internal.containerForItem(delegate, dragCenterX, dragCenterY);
|
||||
if (!newContainer) {
|
||||
newContainer = appletsLayout;
|
||||
}
|
||||
|
||||
// Put it in the favorites strip
|
||||
if (newContainer == favoriteStrip) {
|
||||
var pos = favoriteStrip.flow.mapFromItem(delegate, 0, 0);
|
||||
newRow = Math.floor((pos.x + dragCenterX) / delegate.width);
|
||||
|
||||
//plasmoid.nativeInterface.applicationListModel.setLocation(delegate.modelData.index, ApplicationListModel.Favorites);
|
||||
//root.model.setLocation(delegate.modelData.index, ApplicationListModel.Favorites);
|
||||
|
||||
internal.showSpacer(delegate, dragCenterX, dragCenterY);
|
||||
plasmoid.nativeInterface.applicationListModel.moveItem(delegate.modelData.index, newRow);
|
||||
showSpacer(delegate, dragCenterX, dragCenterY);
|
||||
root.model.moveItem(delegate.modelData.index, newRow);
|
||||
|
||||
// Put it on desktop
|
||||
} else if (newContainer == appletsLayout) {
|
||||
} else {
|
||||
var pos = appletsLayout.mapFromItem(delegate, 0, 0);
|
||||
//plasmoid.nativeInterface.applicationListModel.setLocation(delegate.modelData.index, ApplicationListModel.Desktop);
|
||||
//root.model.setLocation(delegate.modelData.index, ApplicationListModel.Desktop);
|
||||
|
||||
internal.showSpacer(delegate, dragCenterX, dragCenterY);
|
||||
showSpacer(delegate, dragCenterX, dragCenterY);
|
||||
return;
|
||||
|
||||
// Put it in the general view
|
||||
} else {
|
||||
var pos = launcherGrid.flow.mapFromItem(delegate, 0, 0);
|
||||
newRow = Math.floor(newContainer.flow.width / delegate.width) * Math.floor((pos.y + dragCenterY) / delegate.height) + Math.round((pos.x + dragCenterX) / delegate.width) + favoriteStrip.count;
|
||||
|
||||
//plasmoid.nativeInterface.applicationListModel.setLocation(delegate.modelData.index, ApplicationListModel.Grid);
|
||||
|
||||
internal.showSpacer(delegate, dragCenterX, dragCenterY);
|
||||
plasmoid.nativeInterface.applicationListModel.moveItem(delegate.modelData.index, newRow);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +75,87 @@ Item {
|
|||
internal.positionItem(item, dragCenterX, dragCenterY);
|
||||
}
|
||||
|
||||
function showSpacer(item, dragCenterX, dragCenterY) {
|
||||
var container = internal.containerForItem(item, dragCenterX, dragCenterY);
|
||||
|
||||
internal.raiseContainer(container);
|
||||
|
||||
appletsLayout.hidePlaceHolder();
|
||||
|
||||
if (container == appletsLayout) {
|
||||
spacer.visible = false;
|
||||
spacer.parent = root;
|
||||
appletsLayout.releaseSpace(item);
|
||||
internal.putItemInDragSpace(item);
|
||||
var pos = appletsLayout.mapFromItem(item, 0, 0);
|
||||
appletsLayout.showPlaceHolderAt(Qt.rect(pos.x, pos.y, item.width, item.height));
|
||||
return;
|
||||
}
|
||||
|
||||
var child = internal.nearestChild(item, dragCenterX, dragCenterY, container);
|
||||
|
||||
if (!child) {
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
spacer.visible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
|
||||
var pos = container.flow.mapFromItem(item, dragCenterX, dragCenterY);
|
||||
|
||||
if (pos.x < child.x + child.width / 2) {
|
||||
plasmoid.nativeInterface.stackBefore(spacer, child);
|
||||
} else {
|
||||
plasmoid.nativeInterface.stackAfter(spacer, child);
|
||||
}
|
||||
|
||||
internal.putItemInDragSpace(item);
|
||||
|
||||
spacer.visible = true;
|
||||
}
|
||||
|
||||
function showSpacerAtPos(x, y, container) {
|
||||
var pos = container.flow.mapFromGlobal(x, y);
|
||||
internal.raiseContainer(container);
|
||||
|
||||
appletsLayout.hidePlaceHolder();
|
||||
|
||||
if (container == appletsLayout) {
|
||||
spacer.visible = false;
|
||||
spacer.parent = root;
|
||||
appletsLayout.showPlaceHolderAt(Qt.rect(pos.x, pos.y, appletsLayout.cellWidth, appletsLayout.cellHeight));
|
||||
return;
|
||||
}
|
||||
|
||||
var child = internal.nearestChildFromPos(x, y, container);
|
||||
|
||||
if (!child) {
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
spacer.visible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
|
||||
if (pos.x < child.x + child.width / 2) {
|
||||
plasmoid.nativeInterface.stackBefore(spacer, child);
|
||||
} else {
|
||||
plasmoid.nativeInterface.stackAfter(spacer, child);
|
||||
}
|
||||
|
||||
spacer.visible = true;
|
||||
}
|
||||
|
||||
function hideSpacer () {
|
||||
spacer.visible = false;
|
||||
spacer.parent = root;
|
||||
}
|
||||
|
||||
// Those should never be accessed from outside
|
||||
QtObject {
|
||||
id: internal
|
||||
|
|
@ -88,11 +163,9 @@ Item {
|
|||
container.z = 1;
|
||||
|
||||
if (container == appletsLayout) {
|
||||
launcherGrid.z = 0;
|
||||
favoriteStrip.z = 0;
|
||||
} else if (container == favoriteStrip) {
|
||||
appletsLayout.z = 0;
|
||||
launcherGrid.z = 0;
|
||||
} else {
|
||||
appletsLayout.z = 0;
|
||||
favoriteStrip.z = 0;
|
||||
|
|
@ -101,12 +174,11 @@ Item {
|
|||
|
||||
function containerForItem(item, dragCenterX, dragCenterY) {
|
||||
if (favoriteStrip.contains(Qt.point(0,favoriteStrip.frame.mapFromItem(item, dragCenterX, dragCenterY).y))
|
||||
&& plasmoid.nativeInterface.applicationListModel.favoriteCount < plasmoid.nativeInterface.applicationListModel.maxFavoriteCount) {
|
||||
&& (item.modelData.applicationLocation == ApplicationListModel.Favorites
|
||||
|| root.model.favoriteCount < root.model.maxFavoriteCount)) {
|
||||
return favoriteStrip;
|
||||
} else if (appletsLayout.contains(appletsLayout.mapFromItem(item, dragCenterX, dragCenterY))) {
|
||||
return appletsLayout;
|
||||
} else {
|
||||
return launcherGrid;
|
||||
return appletsLayout;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +213,7 @@ Item {
|
|||
var candidate = container.flow.childAt(
|
||||
Math.min(container.flow.width, Math.max(0, pos.x + i)),
|
||||
Math.min(container.flow.height-1, Math.max(0, pos.y)));
|
||||
|
||||
if (candidate && i < distance) {
|
||||
child = candidate;
|
||||
break;
|
||||
|
|
@ -150,6 +223,7 @@ Item {
|
|||
// Search Left
|
||||
for (var i = 0; i < item.width * 2; i += item.width/2) {
|
||||
var candidate = container.flow.childAt(Math.min(container.flow.width, Math.max(0, pos.x - i)), Math.min(container.flow.height-1, Math.max(0, pos.y)));
|
||||
|
||||
if (candidate && i < distance) {
|
||||
child = candidate;
|
||||
break;
|
||||
|
|
@ -167,53 +241,53 @@ Item {
|
|||
return child;
|
||||
}
|
||||
|
||||
function showSpacer(item, dragCenterX, dragCenterY) {
|
||||
var container = containerForItem(item, dragCenterX, dragCenterY);
|
||||
|
||||
raiseContainer(container);
|
||||
function nearestChildFromPos(x, y, container) {
|
||||
var distance = Number.POSITIVE_INFINITY;
|
||||
var child;
|
||||
var pos = container.flow.mapFromGlobal(x, y);
|
||||
|
||||
// Search Right
|
||||
for (var i = 0; i < appletsLayout.cellWidth * 2; i += appletsLayout.cellWidth/2) {
|
||||
var candidate = container.flow.childAt(
|
||||
Math.min(container.flow.width, Math.max(0, pos.x + i)),
|
||||
Math.min(container.flow.height-1, Math.max(0, pos.y)));
|
||||
|
||||
appletsLayout.hidePlaceHolder();
|
||||
|
||||
if (container == appletsLayout) {
|
||||
spacer.visible = false;
|
||||
appletsLayout.releaseSpace(item);
|
||||
putItemInDragSpace(item);
|
||||
var pos = appletsLayout.mapFromItem(item, 0, 0);
|
||||
appletsLayout.showPlaceHolderAt(Qt.rect(pos.x, pos.y, item.width, item.height));
|
||||
return;
|
||||
if (candidate && i < distance) {
|
||||
child = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var child = nearestChild(item, dragCenterX, dragCenterY, container);
|
||||
// Search Left
|
||||
for (var i = 0; i < appletsLayout.cellWidth * 2; i += appletsLayout.cellWidth/2) {
|
||||
var candidate = container.flow.childAt(Math.min(container.flow.width, Math.max(0, pos.x - i)), Math.min(container.flow.height-1, Math.max(0, pos.y)));
|
||||
|
||||
if (candidate && i < distance) {
|
||||
child = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!child) {
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
return;
|
||||
/* if (item.y < container.flow.height/2) {
|
||||
child = container.flow.children[0];
|
||||
} else {
|
||||
child = container.flow.children[container.flow.children.length - 1];
|
||||
}*/
|
||||
}
|
||||
|
||||
spacer.visible = false;
|
||||
spacer.parent = container.flow
|
||||
|
||||
var pos = container.flow.mapFromItem(item, dragCenterX, dragCenterY);
|
||||
|
||||
if (pos.x < child.x + child.width / 2) {
|
||||
plasmoid.nativeInterface.stackBefore(spacer, child);
|
||||
} else {
|
||||
plasmoid.nativeInterface.stackAfter(spacer, child);
|
||||
}
|
||||
|
||||
putItemInDragSpace(item);
|
||||
|
||||
spacer.visible = true;
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
function positionItem(item, dragCenterX, dragCenterY) {
|
||||
var container = containerForItem(item, dragCenterX, dragCenterY);
|
||||
|
||||
raiseContainer(container);
|
||||
|
||||
if (container == appletsLayout) {
|
||||
plasmoid.nativeInterface.applicationListModel.setLocation(item.modelData.index, ApplicationListModel.Desktop);
|
||||
root.model.setLocation(item.modelData.index, ApplicationListModel.Desktop);
|
||||
var pos = appletsLayout.mapFromItem(item, 0, 0);
|
||||
item.parent = appletsLayout;
|
||||
item.x = pos.x;
|
||||
|
|
@ -223,9 +297,9 @@ Item {
|
|||
|
||||
return;
|
||||
} else if (container == favoriteStrip) {
|
||||
plasmoid.nativeInterface.applicationListModel.setLocation(item.modelData.index, ApplicationListModel.Favorites);
|
||||
root.model.setLocation(item.modelData.index, ApplicationListModel.Favorites);
|
||||
} else {
|
||||
plasmoid.nativeInterface.applicationListModel.setLocation(item.modelData.index, ApplicationListModel.Grid);
|
||||
root.model.setLocation(item.modelData.index, ApplicationListModel.Grid);
|
||||
}
|
||||
|
||||
var child = nearestChild(item, dragCenterX, dragCenterY, container);
|
||||
|
|
@ -233,7 +307,7 @@ Item {
|
|||
putInContainerLayout(item, container);
|
||||
plasmoid.nativeInterface.stackBefore(item, spacer);
|
||||
spacer.visible = false;
|
||||
spacer.parent = container;
|
||||
spacer.parent = root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ LauncherContainer {
|
|||
readonly property int columns: Math.floor(root.flow.width / cellWidth)
|
||||
readonly property int cellWidth: root.flow.width / Math.floor(root.flow.width / ((availableCellHeight - reservedSpaceForLabel) + units.smallSpacing*4))
|
||||
readonly property int cellHeight: availableCellHeight
|
||||
launcherGrid: root
|
||||
|
||||
signal launched
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ LauncherContainer {
|
|||
Repeater {
|
||||
parent: root.flow
|
||||
model: plasmoid.nativeInterface.applicationListModel
|
||||
delegate: Delegate {
|
||||
delegate: HomeDelegate {
|
||||
id: delegate
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2021 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3 as Controls
|
||||
import QtGraphicalEffects 1.6
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.kquickcontrolsaddons 2.0
|
||||
|
||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
import org.kde.phone.homescreen 1.0
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
|
||||
Repeater {
|
||||
id: launcherRepeater
|
||||
model: plasmoid.nativeInterface.applicationListModel
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||
property FavoriteStrip favoriteStrip
|
||||
property int cellWidth
|
||||
property int cellHeight
|
||||
|
||||
delegate: HomeDelegate {
|
||||
id: delegate
|
||||
width: launcherRepeater.cellWidth
|
||||
height: Math.min(parent.height, launcherRepeater.cellHeight)
|
||||
appletsLayout: launcherRepeater.appletsLayout
|
||||
|
||||
//just the normal inline binding in height: fails as it gets broken, make it explicit
|
||||
Binding {
|
||||
target: delegate
|
||||
property: "height"
|
||||
value: Math.min(parent.height, launcherRepeater.cellHeight)
|
||||
}
|
||||
parent: parentFromLocation
|
||||
reservedSpaceForLabel: metrics.height
|
||||
property Item parentFromLocation: {
|
||||
switch (model.applicationLocation) {
|
||||
case ApplicationListModel.Favorites:
|
||||
return favoriteStrip.flow;
|
||||
case ApplicationListModel.Desktop:
|
||||
default:
|
||||
return appletsLayout;
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (model.applicationLocation === ApplicationListModel.Desktop) {
|
||||
appletsLayout.restoreItem(delegate);
|
||||
}
|
||||
}
|
||||
|
||||
onLaunch: (x, y, icon, title) => {
|
||||
if (icon !== "") {
|
||||
print(delegate.iconItem)
|
||||
NanoShell.StartupFeedback.open(
|
||||
icon,
|
||||
title,
|
||||
delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2,
|
||||
delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2,
|
||||
Math.min(delegate.iconItem.width, delegate.iconItem.height));
|
||||
}
|
||||
root.launched();
|
||||
}
|
||||
onParentFromLocationChanged: {
|
||||
if (!launcherDragManager.active && parent != parentFromLocation) {
|
||||
parent = parentFromLocation;
|
||||
if (model.applicationLocation === ApplicationListModel.Favorites) {
|
||||
plasmoid.nativeInterface.stackBefore(delegate, parentFromLocation.children[index]);
|
||||
|
||||
} else if (model.applicationLocation === ApplicationListModel.Grid) {
|
||||
plasmoid.nativeInterface.stackBefore(delegate, parentFromLocation.children[Math.max(0, index - plasmoid.nativeInterface.applicationListModel.favoriteCount)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2019 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3 as Controls
|
||||
import QtGraphicalEffects 1.6
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.kquickcontrolsaddons 2.0
|
||||
|
||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
import org.kde.phone.homescreen 1.0
|
||||
|
||||
|
||||
PC3.RoundButton {
|
||||
id: removeButton
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
visible: false
|
||||
icon.name: "delete"
|
||||
onClicked: delegateDestructionAnim.restart()
|
||||
|
||||
function show() {
|
||||
scale = 0;
|
||||
visible = true;
|
||||
removeButtonScaleAnim.from = 0;
|
||||
removeButtonScaleAnim.to = 1;
|
||||
removeButtonAnim.running = true;
|
||||
}
|
||||
function hide() {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
removeButtonScaleAnim.from = 1;
|
||||
removeButtonScaleAnim.to = 0;
|
||||
removeButtonAnim.running = true;
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: delegateDestructionAnim
|
||||
NumberAnimation {
|
||||
target: delegate
|
||||
property: "scale"
|
||||
from: 1
|
||||
to: 0
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
appletsLayout.releaseSpace(delegate);
|
||||
plasmoid.nativeInterface.applicationListModel.removeFavorite(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: removeButtonAnim
|
||||
NumberAnimation {
|
||||
id: removeButtonScaleAnim
|
||||
target: removeButton
|
||||
property: "scale"
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
if (removeButton.scale === 0) {
|
||||
removeButton.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2019 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.draganddrop 2.0 as DragDrop
|
||||
|
||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||
|
||||
import org.kde.phone.homescreen 1.0
|
||||
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: arrowUpIcon
|
||||
z: 9
|
||||
property Flickable flickable
|
||||
property real factor: 0
|
||||
|
||||
height: units.iconSizes.medium
|
||||
signal openRequested
|
||||
signal closeRequested
|
||||
|
||||
onClicked: {
|
||||
if ((arrowUpIcon.flickable.contentY + arrowUpIcon.flickable.originY + arrowUpIcon.flickable.height*2) >= arrowUpIcon.flickable.height/2) {
|
||||
closeRequested();
|
||||
} else {
|
||||
openRequested();
|
||||
}
|
||||
scrollAnim.restart();
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: units.iconSizes.medium
|
||||
height: width
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.horizontalCenter
|
||||
left: parent.left
|
||||
verticalCenterOffset: -arrowUpIcon.height/4 + (arrowUpIcon.height/4) * arrowUpIcon.factor
|
||||
}
|
||||
color: theme.backgroundColor
|
||||
transformOrigin: Item.Right
|
||||
rotation: -45 + 90 * arrowUpIcon.factor
|
||||
antialiasing: true
|
||||
height: 1
|
||||
}
|
||||
Rectangle {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.horizontalCenter
|
||||
right: parent.right
|
||||
verticalCenterOffset: -arrowUpIcon.height/4 + (arrowUpIcon.height/4) * arrowUpIcon.factor
|
||||
}
|
||||
color: theme.backgroundColor
|
||||
transformOrigin: Item.Left
|
||||
rotation: 45 - 90 * arrowUpIcon.factor
|
||||
antialiasing: true
|
||||
height: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,24 +44,30 @@ Item {
|
|||
|
||||
//BEGIN functions
|
||||
//Autoscroll related functions
|
||||
function scrollUp() {
|
||||
autoScrollTimer.scrollDown = false;
|
||||
function scrollLeft() {
|
||||
if (mainFlickable.atXBeginning) {
|
||||
return;
|
||||
}
|
||||
autoScrollTimer.scrollRight = false;
|
||||
autoScrollTimer.running = true;
|
||||
scrollUpIndicator.opacity = 1;
|
||||
scrollDownIndicator.opacity = 0;
|
||||
scrollLeftIndicator.opacity = 1;
|
||||
scrollRightIndicator.opacity = 0;
|
||||
}
|
||||
|
||||
function scrollDown() {
|
||||
autoScrollTimer.scrollDown = true;
|
||||
function scrollRight() {
|
||||
if (mainFlickable.atXEnd) {
|
||||
return;
|
||||
}
|
||||
autoScrollTimer.scrollRight = true;
|
||||
autoScrollTimer.running = true;
|
||||
scrollUpIndicator.opacity = 0;
|
||||
scrollDownIndicator.opacity = 1;
|
||||
scrollLeftIndicator.opacity = 0;
|
||||
scrollRightIndicator.opacity = 1;
|
||||
}
|
||||
|
||||
function stopScroll() {
|
||||
autoScrollTimer.running = false;
|
||||
scrollUpIndicator.opacity = 0;
|
||||
scrollDownIndicator.opacity = 0;
|
||||
scrollLeftIndicator.opacity = 0;
|
||||
scrollRightIndicator.opacity = 0;
|
||||
}
|
||||
|
||||
function recalculateMaxFavoriteCount() {
|
||||
|
|
@ -69,8 +75,9 @@ Item {
|
|||
return;
|
||||
}
|
||||
|
||||
plasmoid.nativeInterface.applicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / launcher.cellWidth));
|
||||
plasmoid.nativeInterface.applicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / appletsLayout.cellWidth));
|
||||
}
|
||||
|
||||
//END functions
|
||||
|
||||
property bool componentComplete: false
|
||||
|
|
@ -98,30 +105,37 @@ Item {
|
|||
}
|
||||
|
||||
Connections {
|
||||
property real lastRequestedPosition: 0
|
||||
target: MobileShell.HomeScreenControls
|
||||
function onResetHomeScreenPosition() {
|
||||
scrollAnim.to = 0;
|
||||
scrollAnim.restart();
|
||||
appDrawer.close();
|
||||
}
|
||||
function onSnapHomeScreenPosition() {
|
||||
mainFlickable.flick(0, 1);
|
||||
if (lastRequestedPosition > 0) {
|
||||
appDrawer.open();
|
||||
} else {
|
||||
appDrawer.close();
|
||||
}
|
||||
}
|
||||
function onRequestHomeScreenPosition(y) {
|
||||
mainFlickable.contentY = y;
|
||||
appDrawer.offset += y;
|
||||
lastRequestedPosition = y;
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: autoScrollTimer
|
||||
property bool scrollDown: true
|
||||
property bool scrollRight: true
|
||||
repeat: true
|
||||
interval: 1500
|
||||
onTriggered: {
|
||||
scrollAnim.to = scrollDown ?
|
||||
//Scroll down
|
||||
Math.min(mainFlickable.contentItem.height - root.height, mainFlickable.contentY + root.height/2) :
|
||||
//Scroll up
|
||||
Math.max(0, mainFlickable.contentY - root.height/2);
|
||||
scrollAnim.to = scrollRight ?
|
||||
//Scroll Right
|
||||
Math.min(mainFlickable.contentItem.width - mainFlickable.width, mainFlickable.contentX + mainFlickable.width) :
|
||||
//Scroll Left
|
||||
Math.max(0, mainFlickable.contentX - mainFlickable.width);
|
||||
|
||||
scrollAnim.running = true;
|
||||
}
|
||||
|
|
@ -139,38 +153,28 @@ Item {
|
|||
anchors.fill: parent
|
||||
z: 2
|
||||
appletsLayout: appletsLayout
|
||||
launcherGrid: launcher
|
||||
favoriteStrip: favoriteStrip
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: -1
|
||||
rightMargin: -1
|
||||
}
|
||||
border.color: Qt.rgba(1, 1, 1, 0.5)
|
||||
radius: units.gridUnit
|
||||
color: "black"
|
||||
opacity: 0.4 * Math.min(1, mainFlickable.contentY / (units.gridUnit * 10))
|
||||
height: root.height + radius * 2
|
||||
y: Math.max(-radius, -mainFlickable.contentY + arrowUpIcon.y)
|
||||
}
|
||||
|
||||
//TODO: this flickable does nothing for now, will be used for horizontal paging
|
||||
Flickable {
|
||||
id: mainFlickable
|
||||
width: parent.width
|
||||
clip: true
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
//topMargin: plasmoid.availableScreenRect.y
|
||||
topMargin: plasmoid.availableScreenRect.y
|
||||
bottomMargin: favoriteStrip.height + plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
||||
}
|
||||
|
||||
opacity: 1 - appDrawer.openFactor
|
||||
transform: Translate {
|
||||
y: -mainFlickable.height/10 * appDrawer.openFactor
|
||||
}
|
||||
scale: (3 - appDrawer.openFactor) /3
|
||||
|
||||
//bottomMargin: favoriteStrip.height
|
||||
contentWidth: width
|
||||
contentHeight: flickableContents.height
|
||||
contentWidth: appletsLayout.width
|
||||
contentHeight: height
|
||||
interactive: !plasmoid.editMode && !launcherDragManager.active
|
||||
|
||||
signal cancelEditModeForItemsRequested
|
||||
|
|
@ -181,256 +185,208 @@ Item {
|
|||
|
||||
onContentYChanged: MobileShell.HomeScreenControls.homeScreenPosition = contentY
|
||||
|
||||
PlasmaComponents.ScrollBar.vertical: PlasmaComponents.ScrollBar {
|
||||
id: scrollabr
|
||||
opacity: mainFlickable.moving
|
||||
interactive: false
|
||||
enabled: false
|
||||
Behavior on opacity {
|
||||
OpacityAnimator {
|
||||
duration: units.longDuration * 2
|
||||
easing.type: Easing.InOutQuad
|
||||
DragHandler {
|
||||
target: mainFlickable
|
||||
yAxis.enabled: !appletsLayout.editMode
|
||||
enabled: appDrawer.status !== Launcher.AppDrawer.Status.Open
|
||||
onTranslationChanged: {
|
||||
if (active) {
|
||||
appDrawer.offset = -translation.y
|
||||
}
|
||||
}
|
||||
implicitWidth: Math.round(units.gridUnit/3)
|
||||
contentItem: Rectangle {
|
||||
radius: width/2
|
||||
color: Qt.rgba(1, 1, 1, 0.3)
|
||||
border.color: Qt.rgba(0, 0, 0, 0.4)
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
appDrawer.snapDrawerStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: scrollAnim
|
||||
target: mainFlickable
|
||||
properties: "contentY"
|
||||
properties: "contentX"
|
||||
duration: units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
Column {
|
||||
id: flickableContents
|
||||
|
||||
// TODO: span on multiple pages
|
||||
DragDrop.DropArea {
|
||||
id: dropArea
|
||||
width: mainFlickable.width
|
||||
spacing: 0
|
||||
height: mainFlickable.height + favoriteStrip.height
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: plasmoid.availableScreenRect.y
|
||||
onDragEnter: {
|
||||
event.accept(event.proposedAction);
|
||||
}
|
||||
DragDrop.DropArea {
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: mainFlickable.height - plasmoid.availableScreenRect.y //TODO: multiple widgets pages
|
||||
|
||||
onDragEnter: {
|
||||
event.accept(event.proposedAction);
|
||||
}
|
||||
onDragMove: {
|
||||
onDragMove: {
|
||||
let posInFavorites = favoriteStrip.mapFromItem(this, event.x, event.y);
|
||||
if (posInFavorites.y > 0) {
|
||||
launcherDragManager.showSpacerAtPos(event.x, event.y, favoriteStrip);
|
||||
appletsLayout.hidePlaceHolder();
|
||||
} else {
|
||||
appletsLayout.showPlaceHolderAt(
|
||||
Qt.rect(event.x - appletsLayout.defaultItemWidth / 2,
|
||||
event.y - appletsLayout.defaultItemHeight / 2,
|
||||
appletsLayout.defaultItemWidth,
|
||||
appletsLayout.defaultItemHeight)
|
||||
);
|
||||
launcherDragManager.hideSpacer();
|
||||
}
|
||||
}
|
||||
|
||||
onDragLeave: {
|
||||
onDragLeave: {
|
||||
appletsLayout.hidePlaceHolder();
|
||||
}
|
||||
|
||||
preventStealing: true
|
||||
|
||||
onDrop: {
|
||||
if (event.mimeData.formats[0] === "text/x-plasma-phone-homescreen-launcher") {
|
||||
let storageId = event.mimeData.getDataAsByteArray("text/x-plasma-phone-homescreen-launcher");
|
||||
|
||||
let posInFavorites = favoriteStrip.flow.mapFromItem(this, event.x, event.y);
|
||||
if (posInFavorites.y > 0) {
|
||||
plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, 0, ApplicationListModel.Favorites)
|
||||
let item = launcherRepeater.itemAt(0);
|
||||
|
||||
if (item) {
|
||||
item.x = posInFavorites.x;
|
||||
item.y = 0//posInFavorites.y;
|
||||
|
||||
//launcherDragManager.showSpacer(item, item.width/2, item.height/2);
|
||||
launcherDragManager.dropItem(item, item.width/2, item.height/2);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, 0, ApplicationListModel.Desktop)
|
||||
let item = launcherRepeater.itemAt(0);
|
||||
|
||||
event.accept(event.proposedAction);
|
||||
if (item) {
|
||||
item.x = appletsLayout.placeHolder.x;
|
||||
item.y = appletsLayout.placeHolder.y;
|
||||
appletsLayout.hidePlaceHolder();
|
||||
launcherDragManager.dropItem(item, appletsLayout.placeHolder.x + appletsLayout.placeHolder.width/2, appletsLayout.placeHolder.y + appletsLayout.placeHolder.height/2);
|
||||
}
|
||||
appletsLayout.hidePlaceHolder();
|
||||
}
|
||||
|
||||
preventStealing: true
|
||||
|
||||
onDrop: {
|
||||
} else {
|
||||
plasmoid.processMimeData(event.mimeData,
|
||||
event.x - appletsLayout.placeHolder.width / 2, event.y - appletsLayout.placeHolder.height / 2);
|
||||
event.accept(event.proposedAction);
|
||||
appletsLayout.hidePlaceHolder();
|
||||
}
|
||||
|
||||
PlasmaCore.Svg {
|
||||
id: arrowsSvg
|
||||
imagePath: "widgets/arrows"
|
||||
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||
}
|
||||
MouseArea {
|
||||
id: arrowUpIcon
|
||||
z: 9
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: -units.smallSpacing
|
||||
}
|
||||
property real factor: Math.max(0, Math.min(1, mainFlickable.contentY / (mainFlickable.height/2)))
|
||||
|
||||
height: units.iconSizes.medium
|
||||
onClicked: {
|
||||
if (mainFlickable.contentY >= mainFlickable.height/2) {
|
||||
scrollAnim.to = 0;
|
||||
} else {
|
||||
scrollAnim.to = mainFlickable.height/2
|
||||
}
|
||||
scrollAnim.restart();
|
||||
}
|
||||
Item {
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: units.iconSizes.medium
|
||||
height: width
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.horizontalCenter
|
||||
left: parent.left
|
||||
verticalCenterOffset: -arrowUpIcon.height/4 + (arrowUpIcon.height/4) * arrowUpIcon.factor
|
||||
}
|
||||
color: theme.backgroundColor
|
||||
transformOrigin: Item.Right
|
||||
rotation: -45 + 90 * arrowUpIcon.factor
|
||||
antialiasing: true
|
||||
height: 1
|
||||
}
|
||||
Rectangle {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.horizontalCenter
|
||||
right: parent.right
|
||||
verticalCenterOffset: -arrowUpIcon.height/4 + (arrowUpIcon.height/4) * arrowUpIcon.factor
|
||||
}
|
||||
color: theme.backgroundColor
|
||||
transformOrigin: Item.Left
|
||||
rotation: 45 - 90 * arrowUpIcon.factor
|
||||
antialiasing: true
|
||||
height: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContainmentLayoutManager.AppletsLayout {
|
||||
id: appletsLayout
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
cellWidth: Math.floor(width / launcher.columns)
|
||||
cellHeight: launcher.cellHeight
|
||||
|
||||
configKey: width > height ? "ItemGeometriesHorizontal" : "ItemGeometriesVertical"
|
||||
containment: plasmoid
|
||||
editModeCondition: plasmoid.immutable
|
||||
? ContainmentLayoutManager.AppletsLayout.Manual
|
||||
: ContainmentLayoutManager.AppletsLayout.AfterPressAndHold
|
||||
|
||||
// Sets the containment in edit mode when we go in edit mode as well
|
||||
onEditModeChanged: plasmoid.editMode = editMode
|
||||
|
||||
minimumItemWidth: units.gridUnit * 3
|
||||
minimumItemHeight: minimumItemWidth
|
||||
|
||||
defaultItemWidth: units.gridUnit * 6
|
||||
defaultItemHeight: defaultItemWidth
|
||||
|
||||
//cellWidth: units.iconSizes.small
|
||||
//cellHeight: cellWidth
|
||||
|
||||
acceptsAppletCallback: function(applet, x, y) {
|
||||
print("Applet: "+applet+" "+x+" "+y)
|
||||
return true;
|
||||
}
|
||||
|
||||
appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer {
|
||||
id: appletContainer
|
||||
configOverlayComponent: ConfigOverlay {}
|
||||
|
||||
onEditModeChanged: {
|
||||
launcherDragManager.active = dragActive || editMode;
|
||||
}
|
||||
onDragActiveChanged: {
|
||||
launcherDragManager.active = dragActive || editMode;
|
||||
}
|
||||
}
|
||||
|
||||
placeHolder: ContainmentLayoutManager.PlaceHolder {}
|
||||
}
|
||||
}
|
||||
|
||||
Launcher.LauncherGrid {
|
||||
id: launcher
|
||||
PlasmaCore.Svg {
|
||||
id: arrowsSvg
|
||||
imagePath: "widgets/arrows"
|
||||
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||
}
|
||||
|
||||
ContainmentLayoutManager.AppletsLayout {
|
||||
id: appletsLayout
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
fill: parent
|
||||
bottomMargin: favoriteStrip.height
|
||||
}
|
||||
onLaunched: scrollResetTimer.restart();
|
||||
favoriteStrip: favoriteStrip
|
||||
appletsLayout: appletsLayout
|
||||
}
|
||||
Timer {
|
||||
id: scrollResetTimer
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
scrollAnim.to = 0;
|
||||
scrollAnim.restart();
|
||||
|
||||
signal appletsLayoutInteracted
|
||||
|
||||
TapHandler {
|
||||
target: mainFlickable
|
||||
enabled: appDrawer.status !== Launcher.AppDrawer.Status.Open
|
||||
onTapped: {
|
||||
//Hides icons close button
|
||||
appletsLayout.appletsLayoutInteracted();
|
||||
appletsLayout.editMode = false;
|
||||
}
|
||||
onLongPressed: appletsLayout.editMode = true;
|
||||
}
|
||||
|
||||
cellWidth: favoriteStrip.cellWidth
|
||||
cellHeight: Math.floor(height / Math.floor(height / favoriteStrip.cellHeight))
|
||||
|
||||
configKey: width > height ? "ItemGeometriesHorizontal" : "ItemGeometriesVertical"
|
||||
containment: plasmoid
|
||||
editModeCondition: plasmoid.immutable
|
||||
? ContainmentLayoutManager.AppletsLayout.Manual
|
||||
: ContainmentLayoutManager.AppletsLayout.AfterPressAndHold
|
||||
|
||||
// Sets the containment in edit mode when we go in edit mode as well
|
||||
onEditModeChanged: plasmoid.editMode = editMode
|
||||
|
||||
minimumItemWidth: units.gridUnit * 3
|
||||
minimumItemHeight: minimumItemWidth
|
||||
|
||||
defaultItemWidth: units.gridUnit * 6
|
||||
defaultItemHeight: defaultItemWidth
|
||||
|
||||
acceptsAppletCallback: function(applet, x, y) {
|
||||
print("Applet: "+applet+" "+x+" "+y)
|
||||
return true;
|
||||
}
|
||||
|
||||
appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer {
|
||||
id: appletContainer
|
||||
configOverlayComponent: ConfigOverlay {}
|
||||
|
||||
onEditModeChanged: {
|
||||
launcherDragManager.active = dragActive || editMode;
|
||||
}
|
||||
onDragActiveChanged: {
|
||||
launcherDragManager.active = dragActive || editMode;
|
||||
}
|
||||
}
|
||||
|
||||
placeHolder: ContainmentLayoutManager.PlaceHolder {}
|
||||
//FIXME: move
|
||||
PlasmaComponents.Label {
|
||||
id: metrics
|
||||
text: "M\nM"
|
||||
visible: false
|
||||
font.pointSize: theme.defaultFont.pointSize * 0.9
|
||||
}
|
||||
Launcher.LauncherRepeater {
|
||||
id: launcherRepeater
|
||||
cellWidth: appletsLayout.cellWidth
|
||||
cellHeight: appletsLayout.cellHeight
|
||||
appletsLayout: appletsLayout
|
||||
favoriteStrip: favoriteStrip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollIndicator {
|
||||
id: scrollUpIndicator
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: units.gridUnit * 2
|
||||
}
|
||||
elementId: "up-arrow"
|
||||
}
|
||||
ScrollIndicator {
|
||||
id: scrollDownIndicator
|
||||
anchors {
|
||||
bottom: favoriteStrip.top
|
||||
bottomMargin: units.gridUnit
|
||||
}
|
||||
elementId: "down-arrow"
|
||||
Launcher.AppDrawer {
|
||||
id: appDrawer
|
||||
anchors.fill: parent
|
||||
|
||||
topPadding: plasmoid.availableScreenRect.y
|
||||
bottomPadding: favoriteStrip.height + plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
ScrollIndicator {
|
||||
id: scrollLeftIndicator
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: units.smallSpacing
|
||||
}
|
||||
elementId: "left-arrow"
|
||||
}
|
||||
ScrollIndicator {
|
||||
id: scrollRightIndicator
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: favoriteStrip.top
|
||||
leftMargin: units.gridUnit
|
||||
rightMargin: units.gridUnit
|
||||
}
|
||||
height: 1
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: Qt.rgba(1, 1, 1, 0) }
|
||||
GradientStop { position: 0.15; color: Qt.rgba(1, 1, 1, 0.5) }
|
||||
GradientStop { position: 0.5; color: Qt.rgba(1, 1, 1, 1) }
|
||||
GradientStop { position: 0.85; color: Qt.rgba(1, 1, 1, 0.5) }
|
||||
GradientStop { position: 1.0; color: Qt.rgba(1, 1, 1, 0) }
|
||||
}
|
||||
opacity: mainFlickable.contentY > 0 ? 0.6 : 0
|
||||
Behavior on opacity {
|
||||
OpacityAnimator {
|
||||
duration: units.longDuration * 2
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
rightMargin: units.smallSpacing
|
||||
}
|
||||
elementId: "right-arrow"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill:favoriteStrip
|
||||
property real oldMouseY
|
||||
onPressed: oldMouseY = mouse.y
|
||||
onPositionChanged: {
|
||||
mainFlickable.contentY -= mouse.y - oldMouseY;
|
||||
oldMouseY = mouse.y;
|
||||
}
|
||||
onReleased: {
|
||||
mainFlickable.flick(0, 1);
|
||||
}
|
||||
}
|
||||
Launcher.FavoriteStrip {
|
||||
id: favoriteStrip
|
||||
anchors {
|
||||
|
|
@ -440,8 +396,31 @@ Item {
|
|||
bottomMargin: plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
||||
}
|
||||
appletsLayout: appletsLayout
|
||||
launcherGrid: launcher
|
||||
//y: Math.max(krunner.inputHeight, root.height - height - mainFlickable.contentY)
|
||||
|
||||
DragHandler {
|
||||
target: favoriteStrip
|
||||
yAxis.enabled: !appletsLayout.editMode
|
||||
enabled: appDrawer.status !== Launcher.AppDrawer.Status.Open
|
||||
onTranslationChanged: {
|
||||
if (active) {
|
||||
appDrawer.offset = -translation.y
|
||||
}
|
||||
}
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
appDrawer.snapDrawerStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
TapHandler {
|
||||
target: favoriteStrip
|
||||
onTapped: {
|
||||
//Hides icons close button
|
||||
appletsLayout.appletsLayoutInteracted();
|
||||
appletsLayout.editMode = false;
|
||||
}
|
||||
onLongPressed: appletsLayout.editMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue