homescreens/folio: Port away from singletons to support multi-display

https://invent.kde.org/plasma/plasma-mobile/-/issues/316
This commit is contained in:
Devin Lin 2024-06-21 00:42:14 -04:00
parent 600fd05900
commit 21ed42ee30
50 changed files with 1136 additions and 993 deletions

View file

@ -18,7 +18,7 @@
#include <KSharedConfig> #include <KSharedConfig>
#include <KSycoca> #include <KSycoca>
ApplicationListModel::ApplicationListModel(QObject *parent) ApplicationListModel::ApplicationListModel(HomeScreen *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
{ {
connect(KSycoca::self(), &KSycoca::databaseChanged, this, &ApplicationListModel::sycocaDbChanged); connect(KSycoca::self(), &KSycoca::databaseChanged, this, &ApplicationListModel::sycocaDbChanged);
@ -34,12 +34,6 @@ ApplicationListModel::ApplicationListModel(QObject *parent)
ApplicationListModel::~ApplicationListModel() = default; ApplicationListModel::~ApplicationListModel() = default;
ApplicationListModel *ApplicationListModel::self()
{
static ApplicationListModel *inst = new ApplicationListModel(nullptr);
return inst;
}
QHash<int, QByteArray> ApplicationListModel::roleNames() const QHash<int, QByteArray> ApplicationListModel::roleNames() const
{ {
return {{DelegateRole, QByteArrayLiteral("delegate")}}; return {{DelegateRole, QByteArrayLiteral("delegate")}};
@ -82,8 +76,8 @@ void ApplicationListModel::load()
const KService::List apps = KApplicationTrader::query(filter); const KService::List apps = KApplicationTrader::query(filter);
for (const KService::Ptr &service : apps) { for (const KService::Ptr &service : apps) {
FolioApplication *app = new FolioApplication{this, service}; FolioApplication *app = new FolioApplication{m_homeScreen, service};
FolioDelegate *delegate = new FolioDelegate{app, this}; FolioDelegate *delegate = new FolioDelegate{app, m_homeScreen};
unorderedList << delegate; unorderedList << delegate;
} }

View file

@ -11,6 +11,10 @@
#include <QSet> #include <QSet>
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreen.h"
class HomeScreen;
class FolioDelegate;
/** /**
* @short The base application list, used directly by the app drawer. * @short The base application list, used directly by the app drawer.
@ -24,15 +28,14 @@ public:
DelegateRole = Qt::UserRole + 1, DelegateRole = Qt::UserRole + 1,
}; };
ApplicationListModel(QObject *parent = nullptr); ApplicationListModel(HomeScreen *parent = nullptr);
~ApplicationListModel() override; ~ApplicationListModel() override;
static ApplicationListModel *self();
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;
Q_INVOKABLE void load(); void load();
public Q_SLOTS: public Q_SLOTS:
void sycocaDbChanged(); void sycocaDbChanged();
@ -41,5 +44,6 @@ Q_SIGNALS:
void launchError(const QString &msg); void launchError(const QString &msg);
protected: protected:
HomeScreen *m_homeScreen{nullptr};
QList<FolioDelegate *> m_delegates; QList<FolioDelegate *> m_delegates;
}; };

View file

@ -122,8 +122,10 @@ void DelegateDragPosition::setFolder(FolioApplicationFolder *folder)
} }
} }
DragState::DragState(HomeScreenState *state, QObject *parent) DragState::DragState(HomeScreenState *state, HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_homeScreen{parent}
, m_state{state}
, m_changePageTimer{new QTimer{this}} , m_changePageTimer{new QTimer{this}}
, m_openFolderTimer{new QTimer{this}} , m_openFolderTimer{new QTimer{this}}
, m_leaveFolderTimer{new QTimer{this}} , m_leaveFolderTimer{new QTimer{this}}
@ -132,7 +134,6 @@ DragState::DragState(HomeScreenState *state, QObject *parent)
, m_favouritesInsertBetweenTimer{new QTimer{this}} , m_favouritesInsertBetweenTimer{new QTimer{this}}
, m_candidateDropPosition{new DelegateDragPosition{this}} , m_candidateDropPosition{new DelegateDragPosition{this}}
, m_startPosition{new DelegateDragPosition{this}} , m_startPosition{new DelegateDragPosition{this}}
, m_state{state}
{ {
if (!state) { if (!state) {
return; return;
@ -170,7 +171,7 @@ DragState::DragState(HomeScreenState *state, QObject *parent)
connect(m_state, &HomeScreenState::delegateDragFromFolderStarted, this, &DragState::onDelegateDragFromFolderStarted); connect(m_state, &HomeScreenState::delegateDragFromFolderStarted, this, &DragState::onDelegateDragFromFolderStarted);
connect(m_state, &HomeScreenState::delegateDragFromWidgetListStarted, this, &DragState::onDelegateDragFromWidgetListStarted); connect(m_state, &HomeScreenState::delegateDragFromWidgetListStarted, this, &DragState::onDelegateDragFromWidgetListStarted);
connect(m_state, &HomeScreenState::swipeStateChanged, this, [this]() { connect(m_state, &HomeScreenState::swipeStateChanged, this, [this]() {
if (HomeScreenState::self()->swipeState() == HomeScreenState::DraggingDelegate) { if (m_state->swipeState() == HomeScreenState::DraggingDelegate) {
onDelegateDraggingStarted(); onDelegateDraggingStarted();
} }
}); });
@ -314,7 +315,8 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
qreal x = getPointerX(); qreal x = getPointerX();
qreal y = getPointerY(); qreal y = getPointerY();
int dropIndex = FavouritesModel::self()->dropInsertPosition(x, y); FavouritesModel *favouritesModel = m_homeScreen->favouritesModel();
int dropIndex = favouritesModel->dropInsertPosition(x, y);
// if the drop position changed, cancel the open folder timer // if the drop position changed, cancel the open folder timer
if (m_candidateDropPosition->location() != DelegateDragPosition::Favourites || m_candidateDropPosition->favouritesPosition() != dropIndex) { if (m_candidateDropPosition->location() != DelegateDragPosition::Favourites || m_candidateDropPosition->favouritesPosition() != dropIndex) {
@ -329,7 +331,7 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
} }
// ignore this event if the favourites area is full already // ignore this event if the favourites area is full already
if (FavouritesModel::self()->isFull()) { if (favouritesModel->isFull()) {
return; return;
} }
@ -338,7 +340,7 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
return; return;
} }
if (FavouritesModel::self()->dropPositionIsEdge(x, y)) { if (favouritesModel->dropPositionIsEdge(x, y)) {
// if we need to make space for the delegate // if we need to make space for the delegate
// start the insertion timer (so that the user has time to move the delegate away) // start the insertion timer (so that the user has time to move the delegate away)
@ -350,13 +352,13 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
// if we are hovering over the center of a folder or app // if we are hovering over the center of a folder or app
// delete ghost entry if there is one // delete ghost entry if there is one
int ghostEntryPosition = FavouritesModel::self()->getGhostEntryPosition(); int ghostEntryPosition = favouritesModel->getGhostEntryPosition();
if (ghostEntryPosition != -1 && ghostEntryPosition != dropIndex) { if (ghostEntryPosition != -1 && ghostEntryPosition != dropIndex) {
if (dropIndex > ghostEntryPosition) { if (dropIndex > ghostEntryPosition) {
// correct index if deleting the ghost will change the index // correct index if deleting the ghost will change the index
dropIndex--; dropIndex--;
} }
FavouritesModel::self()->deleteGhostEntry(); favouritesModel->deleteGhostEntry();
} }
// update the current drop position // update the current drop position
@ -365,7 +367,7 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
// start folder open timer if hovering over a folder // start folder open timer if hovering over a folder
// get delegate being hovered over // get delegate being hovered over
FolioDelegate *delegate = FavouritesModel::self()->getEntryAt(dropIndex); FolioDelegate *delegate = favouritesModel->getEntryAt(dropIndex);
// check delegate is a folder and the drop delegate is an app // check delegate is a folder and the drop delegate is an app
if (delegate && delegate->type() == FolioDelegate::Folder && m_dropDelegate && m_dropDelegate->type() == FolioDelegate::Application) { if (delegate && delegate->type() == FolioDelegate::Folder && m_dropDelegate && m_dropDelegate->type() == FolioDelegate::Application) {
@ -422,7 +424,7 @@ void DragState::onDelegateDragPositionOverPageViewChanged()
m_candidateDropPosition->setLocation(DelegateDragPosition::Pages); m_candidateDropPosition->setLocation(DelegateDragPosition::Pages);
// start folder open timer if hovering over a folder // start folder open timer if hovering over a folder
PageModel *pageModel = PageListModel::self()->getPage(page); PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
if (pageModel) { if (pageModel) {
// get delegate being hovered over // get delegate being hovered over
FolioDelegate *delegate = pageModel->getDelegate(row, column); FolioDelegate *delegate = pageModel->getDelegate(row, column);
@ -462,7 +464,7 @@ void DragState::onDelegateDraggingStarted()
void DragState::onDelegateDragFromPageStarted(int page, int row, int column) void DragState::onDelegateDragFromPageStarted(int page, int row, int column)
{ {
// fetch delegate at start position // fetch delegate at start position
PageModel *pageModel = PageListModel::self()->getPage(page); PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
if (pageModel) { if (pageModel) {
setDropDelegate(pageModel->getDelegate(row, column)); setDropDelegate(pageModel->getDelegate(row, column));
} else { } else {
@ -479,7 +481,7 @@ void DragState::onDelegateDragFromPageStarted(int page, int row, int column)
void DragState::onDelegateDragFromFavouritesStarted(int position) void DragState::onDelegateDragFromFavouritesStarted(int position)
{ {
// fetch delegate at start position // fetch delegate at start position
setDropDelegate(FavouritesModel::self()->getEntryAt(position)); setDropDelegate(m_homeScreen->favouritesModel()->getEntryAt(position));
// set start location // set start location
m_startPosition->setFavouritesPosition(position); m_startPosition->setFavouritesPosition(position);
@ -490,8 +492,8 @@ void DragState::onDelegateDragFromAppDrawerStarted(QString storageId)
{ {
// fetch delegate at start position // fetch delegate at start position
if (KService::Ptr service = KService::serviceByStorageId(storageId)) { if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
FolioApplication *app = new FolioApplication{this, service}; FolioApplication *app = new FolioApplication{m_homeScreen, service};
setDropDelegate(new FolioDelegate{app, this}); setDropDelegate(new FolioDelegate{app, m_homeScreen});
} else { } else {
setDropDelegate(nullptr); setDropDelegate(nullptr);
} }
@ -515,8 +517,8 @@ void DragState::onDelegateDragFromWidgetListStarted(QString appletPluginId)
{ {
// default widget has dimensions of 1x1, and id of -1 // default widget has dimensions of 1x1, and id of -1
m_createdAppletPluginId = appletPluginId; m_createdAppletPluginId = appletPluginId;
FolioWidget *widget = new FolioWidget{this, -1, 1, 1}; FolioWidget *widget = new FolioWidget{m_homeScreen, -1, 1, 1};
setDropDelegate(new FolioDelegate{widget, this}); setDropDelegate(new FolioDelegate{widget, m_homeScreen});
// set start location // set start location
m_startPosition->setLocation(DelegateDragPosition::WidgetList); m_startPosition->setLocation(DelegateDragPosition::WidgetList);
@ -533,10 +535,10 @@ void DragState::onDelegateDropped()
// delete empty pages at the end if they exist // delete empty pages at the end if they exist
// (it can be created if user drags app to new page, but doesn't place it there) // (it can be created if user drags app to new page, but doesn't place it there)
PageListModel::self()->deleteEmptyPagesAtEnd(); m_homeScreen->pageListModel()->deleteEmptyPagesAtEnd();
// clear ghost position if there is one // clear ghost position if there is one
FavouritesModel::self()->deleteGhostEntry(); m_homeScreen->favouritesModel()->deleteGhostEntry();
// reset timers // reset timers
m_folderInsertBetweenTimer->stop(); m_folderInsertBetweenTimer->stop();
@ -581,6 +583,8 @@ void DragState::onChangePageTimerFinished()
const int leftPagePosition = 0; const int leftPagePosition = 0;
const int rightPagePosition = m_state->pageWidth(); const int rightPagePosition = m_state->pageWidth();
PageListModel *pageListModel = m_homeScreen->pageListModel();
qreal x = getPointerX(); qreal x = getPointerX();
if (qAbs(leftPagePosition - x) <= PAGE_CHANGE_THRESHOLD) { if (qAbs(leftPagePosition - x) <= PAGE_CHANGE_THRESHOLD) {
// if we are at the left edge, go left // if we are at the left edge, go left
@ -594,12 +598,12 @@ void DragState::onChangePageTimerFinished()
int page = m_state->currentPage() + 1; int page = m_state->currentPage() + 1;
// if we are at the right-most page, try to create a new one if the current page isn't empty // if we are at the right-most page, try to create a new one if the current page isn't empty
if (page == PageListModel::self()->rowCount() && !PageListModel::self()->isLastPageEmpty()) { if (page == pageListModel->rowCount() && !pageListModel->isLastPageEmpty()) {
PageListModel::self()->addPageAtEnd(); pageListModel->addPageAtEnd();
} }
// go to page if it exists // go to page if it exists
if (page < PageListModel::self()->rowCount()) { if (page < pageListModel->rowCount()) {
m_state->goToPage(page); m_state->goToPage(page);
} }
} }
@ -618,7 +622,7 @@ void DragState::onOpenFolderTimerFinished()
switch (m_candidateDropPosition->location()) { switch (m_candidateDropPosition->location()) {
case DelegateDragPosition::Pages: { case DelegateDragPosition::Pages: {
// get current page // get current page
PageModel *page = PageListModel::self()->getPage(m_candidateDropPosition->page()); PageModel *page = m_homeScreen->pageListModel()->getPage(m_candidateDropPosition->page());
if (!page) { if (!page) {
return; return;
} }
@ -630,20 +634,19 @@ void DragState::onOpenFolderTimerFinished()
} }
folder = delegate->folder(); folder = delegate->folder();
screenPosition = HomeScreenState::self()->getPageDelegateScreenPosition(m_candidateDropPosition->page(), screenPosition =
m_candidateDropPosition->pageRow(), m_state->getPageDelegateScreenPosition(m_candidateDropPosition->page(), m_candidateDropPosition->pageRow(), m_candidateDropPosition->pageColumn());
m_candidateDropPosition->pageColumn());
break; break;
} }
case DelegateDragPosition::Favourites: { case DelegateDragPosition::Favourites: {
// get delegate being hovered over in favourites bar // get delegate being hovered over in favourites bar
FolioDelegate *delegate = FavouritesModel::self()->getEntryAt(m_candidateDropPosition->favouritesPosition()); FolioDelegate *delegate = m_homeScreen->favouritesModel()->getEntryAt(m_candidateDropPosition->favouritesPosition());
if (!delegate || delegate->type() != FolioDelegate::Folder) { if (!delegate || delegate->type() != FolioDelegate::Folder) {
return; return;
} }
folder = delegate->folder(); folder = delegate->folder();
screenPosition = HomeScreenState::self()->getFavouritesDelegateScreenPosition(m_candidateDropPosition->favouritesPosition()); screenPosition = m_homeScreen->homeScreenState()->getFavouritesDelegateScreenPosition(m_candidateDropPosition->favouritesPosition());
break; break;
} }
default: default:
@ -727,7 +730,7 @@ void DragState::onFavouritesInsertBetweenTimerFinished()
m_candidateDropPosition->setLocation(DelegateDragPosition::Favourites); m_candidateDropPosition->setLocation(DelegateDragPosition::Favourites);
// insert it at this position, shifting existing apps to the side // insert it at this position, shifting existing apps to the side
FavouritesModel::self()->setGhostEntry(m_favouritesInsertBetweenIndex); m_homeScreen->favouritesModel()->setGhostEntry(m_favouritesInsertBetweenIndex);
} }
void DragState::deleteStartPositionDelegate() void DragState::deleteStartPositionDelegate()
@ -735,14 +738,14 @@ void DragState::deleteStartPositionDelegate()
// delete the delegate at the start position // delete the delegate at the start position
switch (m_startPosition->location()) { switch (m_startPosition->location()) {
case DelegateDragPosition::Pages: { case DelegateDragPosition::Pages: {
PageModel *page = PageListModel::self()->getPage(m_startPosition->page()); PageModel *page = m_homeScreen->pageListModel()->getPage(m_startPosition->page());
if (page) { if (page) {
page->removeDelegate(m_startPosition->pageRow(), m_startPosition->pageColumn()); page->removeDelegate(m_startPosition->pageRow(), m_startPosition->pageColumn());
} }
break; break;
} }
case DelegateDragPosition::Favourites: case DelegateDragPosition::Favourites:
FavouritesModel::self()->removeEntry(m_startPosition->favouritesPosition()); m_homeScreen->favouritesModel()->removeEntry(m_startPosition->favouritesPosition());
break; break;
case DelegateDragPosition::Folder: case DelegateDragPosition::Folder:
m_startPosition->folder()->removeDelegate(m_startPosition->folderPosition()); m_startPosition->folder()->removeDelegate(m_startPosition->folderPosition());
@ -767,7 +770,7 @@ bool DragState::createDropPositionDelegate()
switch (m_candidateDropPosition->location()) { switch (m_candidateDropPosition->location()) {
case DelegateDragPosition::Pages: { case DelegateDragPosition::Pages: {
// locate the page we are dropping on // locate the page we are dropping on
PageModel *page = PageListModel::self()->getPage(m_candidateDropPosition->page()); PageModel *page = m_homeScreen->pageListModel()->getPage(m_candidateDropPosition->page());
if (!page) { if (!page) {
break; break;
} }
@ -776,7 +779,7 @@ bool DragState::createDropPositionDelegate()
int column = m_candidateDropPosition->pageColumn(); int column = m_candidateDropPosition->pageColumn();
// delegate to add // delegate to add
FolioPageDelegate *delegate = new FolioPageDelegate{row, column, m_dropDelegate, PageListModel::self()}; FolioPageDelegate *delegate = new FolioPageDelegate{row, column, m_dropDelegate, m_homeScreen};
// delegate that exists at the drop position // delegate that exists at the drop position
FolioPageDelegate *existingDelegate = page->getDelegate(row, column); FolioPageDelegate *existingDelegate = page->getDelegate(row, column);
@ -795,10 +798,10 @@ bool DragState::createDropPositionDelegate()
} else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) { } else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) {
// create a folder from the two apps // create a folder from the two apps
FolioApplicationFolder *folder = new FolioApplicationFolder(this, DEFAULT_FOLDER_NAME); FolioApplicationFolder *folder = new FolioApplicationFolder(m_homeScreen, DEFAULT_FOLDER_NAME);
folder->addDelegate(delegate, 0); folder->addDelegate(delegate, 0);
folder->addDelegate(existingDelegate, 0); folder->addDelegate(existingDelegate, 0);
FolioPageDelegate *folderDelegate = new FolioPageDelegate{row, column, folder, this}; FolioPageDelegate *folderDelegate = new FolioPageDelegate{row, column, folder, m_homeScreen};
page->removeDelegate(row, column); page->removeDelegate(row, column);
page->addDelegate(folderDelegate); page->addDelegate(folderDelegate);
@ -822,7 +825,7 @@ bool DragState::createDropPositionDelegate()
} }
case DelegateDragPosition::Favourites: { case DelegateDragPosition::Favourites: {
// delegate that exists at the drop position // delegate that exists at the drop position
FolioDelegate *existingDelegate = FavouritesModel::self()->getEntryAt(m_candidateDropPosition->favouritesPosition()); FolioDelegate *existingDelegate = m_homeScreen->favouritesModel()->getEntryAt(m_candidateDropPosition->favouritesPosition());
// if a delegate already exists at the spot, check if we can insert/create a folder // if a delegate already exists at the spot, check if we can insert/create a folder
if (existingDelegate) { if (existingDelegate) {
@ -838,13 +841,13 @@ bool DragState::createDropPositionDelegate()
} else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) { } else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) {
// create a folder from the two apps // create a folder from the two apps
FolioApplicationFolder *folder = new FolioApplicationFolder(this, DEFAULT_FOLDER_NAME); FolioApplicationFolder *folder = new FolioApplicationFolder(m_homeScreen, DEFAULT_FOLDER_NAME);
folder->addDelegate(m_dropDelegate, 0); folder->addDelegate(m_dropDelegate, 0);
folder->addDelegate(existingDelegate, 0); folder->addDelegate(existingDelegate, 0);
FolioDelegate *folderDelegate = new FolioDelegate{folder, this}; FolioDelegate *folderDelegate = new FolioDelegate{folder, m_homeScreen};
FavouritesModel::self()->removeEntry(m_candidateDropPosition->favouritesPosition()); m_homeScreen->favouritesModel()->removeEntry(m_candidateDropPosition->favouritesPosition());
FavouritesModel::self()->addEntry(m_candidateDropPosition->favouritesPosition(), folderDelegate); m_homeScreen->favouritesModel()->addEntry(m_candidateDropPosition->favouritesPosition(), folderDelegate);
added = true; added = true;
break; break;
@ -854,7 +857,7 @@ bool DragState::createDropPositionDelegate()
// otherwise, just add the delegate at this position // otherwise, just add the delegate at this position
added = FavouritesModel::self()->addEntry(m_candidateDropPosition->favouritesPosition(), m_dropDelegate); added = m_homeScreen->favouritesModel()->addEntry(m_candidateDropPosition->favouritesPosition(), m_dropDelegate);
// if we couldn't add the delegate, try again but at the start position // if we couldn't add the delegate, try again but at the start position
if (!added && !isStartPositionEqualDropPosition()) { if (!added && !isStartPositionEqualDropPosition()) {
@ -902,8 +905,8 @@ bool DragState::createDropPositionDelegate()
} }
// if we are dropping a new widget, we need to now create the applet in the containment // if we are dropping a new widget, we need to now create the applet in the containment
if (added && m_startPosition->location() == DelegateDragPosition::WidgetList && m_dropDelegate->type() == FolioDelegate::Widget && m_state->containment()) { if (added && m_startPosition->location() == DelegateDragPosition::WidgetList && m_dropDelegate->type() == FolioDelegate::Widget && m_homeScreen) {
Plasma::Applet *applet = m_state->containment()->createApplet(m_createdAppletPluginId); Plasma::Applet *applet = m_homeScreen->createApplet(m_createdAppletPluginId);
// associate the new delegate with the Plasma::Applet // associate the new delegate with the Plasma::Applet
m_dropDelegate->widget()->setApplet(applet); m_dropDelegate->widget()->setApplet(applet);

View file

@ -8,8 +8,10 @@
#include "folioapplicationfolder.h" #include "folioapplicationfolder.h"
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreen.h"
#include "homescreenstate.h" #include "homescreenstate.h"
class HomeScreen;
class HomeScreenState; class HomeScreenState;
class DelegateDragPosition : public QObject class DelegateDragPosition : public QObject
@ -83,7 +85,7 @@ class DragState : public QObject
Q_PROPERTY(FolioDelegate *dropDelegate READ dropDelegate NOTIFY dropDelegateChanged) Q_PROPERTY(FolioDelegate *dropDelegate READ dropDelegate NOTIFY dropDelegateChanged)
public: public:
DragState(HomeScreenState *state = nullptr, QObject *parent = nullptr); DragState(HomeScreenState *state = nullptr, HomeScreen *parent = nullptr);
DelegateDragPosition *candidateDropPosition() const; DelegateDragPosition *candidateDropPosition() const;
DelegateDragPosition *startPosition() const; DelegateDragPosition *startPosition() const;
@ -138,6 +140,9 @@ private:
qreal getPointerX(); qreal getPointerX();
qreal getPointerY(); qreal getPointerY();
HomeScreen *m_homeScreen{nullptr};
HomeScreenState *m_state{nullptr};
QTimer *m_changePageTimer{nullptr}; QTimer *m_changePageTimer{nullptr};
QTimer *m_openFolderTimer{nullptr}; QTimer *m_openFolderTimer{nullptr};
QTimer *m_leaveFolderTimer{nullptr}; QTimer *m_leaveFolderTimer{nullptr};
@ -162,6 +167,4 @@ private:
// when dropping a new widget, this is the applet name // when dropping a new widget, this is the applet name
QString m_createdAppletPluginId{}; QString m_createdAppletPluginId{};
HomeScreenState *m_state{nullptr};
}; };

View file

@ -20,31 +20,26 @@
#include <KSharedConfig> #include <KSharedConfig>
#include <KSycoca> #include <KSycoca>
FavouritesModel *FavouritesModel::self() FavouritesModel::FavouritesModel(HomeScreen *parent)
{
static FavouritesModel *inst = new FavouritesModel();
return inst;
}
FavouritesModel::FavouritesModel(QObject *parent)
: QAbstractListModel{parent} : QAbstractListModel{parent}
, m_homeScreen{parent}
{ {
connect(HomeScreenState::self(), &HomeScreenState::pageWidthChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageWidthChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageHeightChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageHeightChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageCellWidthChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageCellWidthChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageCellHeightChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageCellHeightChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
connect(HomeScreenState::self(), &HomeScreenState::favouritesBarLocationChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::favouritesBarLocationChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageOrientationChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageOrientationChanged, this, [this]() {
evaluateDelegatePositions(true); evaluateDelegatePositions(true);
}); });
} }
@ -173,12 +168,13 @@ FolioDelegate *FavouritesModel::getEntryAt(int row)
bool FavouritesModel::isFull() const bool FavouritesModel::isFull() const
{ {
bool isLocationBottom = HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom; auto homeScreenState = m_homeScreen->homeScreenState();
bool isLocationBottom = homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom;
if (isLocationBottom) { if (isLocationBottom) {
return m_delegates.size() >= HomeScreenState::self()->pageColumns(); return m_delegates.size() >= homeScreenState->pageColumns();
} else { } else {
return m_delegates.size() >= HomeScreenState::self()->pageRows(); return m_delegates.size() >= homeScreenState->pageRows();
} }
} }
@ -209,7 +205,7 @@ void FavouritesModel::setGhostEntry(int row)
// if it doesn't, add a new empty delegate // if it doesn't, add a new empty delegate
if (!found) { if (!found) {
FolioDelegate *ghost = new FolioDelegate{this}; FolioDelegate *ghost = new FolioDelegate{m_homeScreen};
addEntry(row, ghost); addEntry(row, ghost);
} }
} }
@ -218,6 +214,7 @@ void FavouritesModel::replaceGhostEntry(FolioDelegate *delegate)
{ {
for (int i = 0; i < m_delegates.size(); i++) { for (int i = 0; i < m_delegates.size(); i++) {
if (m_delegates[i].delegate->type() == FolioDelegate::None) { if (m_delegates[i].delegate->type() == FolioDelegate::None) {
m_delegates[i].delegate->deleteLater();
m_delegates[i].delegate = delegate; m_delegates[i].delegate = delegate;
Q_EMIT dataChanged(createIndex(i, 0), createIndex(i, 0), {DelegateRole}); Q_EMIT dataChanged(createIndex(i, 0), createIndex(i, 0), {DelegateRole});
@ -230,7 +227,11 @@ void FavouritesModel::deleteGhostEntry()
{ {
for (int i = 0; i < m_delegates.size(); i++) { for (int i = 0; i < m_delegates.size(); i++) {
if (m_delegates[i].delegate->type() == FolioDelegate::None) { if (m_delegates[i].delegate->type() == FolioDelegate::None) {
auto ghostEntry = m_delegates[i].delegate;
removeEntry(i); removeEntry(i);
// ensure ghost entry is deleted
ghostEntry->deleteLater();
} }
} }
} }
@ -253,24 +254,24 @@ QJsonArray FavouritesModel::exportToJson()
void FavouritesModel::save() void FavouritesModel::save()
{ {
if (!m_containment) { if (!m_homeScreen) {
return; return;
} }
QJsonArray arr = exportToJson(); QJsonArray arr = exportToJson();
QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact); QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact);
m_containment->config().writeEntry("Favourites", QString::fromStdString(data.toStdString())); m_homeScreen->config().writeEntry("Favourites", QString::fromStdString(data.toStdString()));
Q_EMIT m_containment->configNeedsSaving(); Q_EMIT m_homeScreen->configNeedsSaving();
} }
void FavouritesModel::load() void FavouritesModel::load()
{ {
if (!m_containment) { if (!m_homeScreen) {
return; return;
} }
QJsonDocument doc = QJsonDocument::fromJson(m_containment->config().readEntry("Favourites", "{}").toUtf8()); QJsonDocument doc = QJsonDocument::fromJson(m_homeScreen->config().readEntry("Favourites", "{}").toUtf8());
loadFromJson(doc.array()); loadFromJson(doc.array());
} }
@ -282,7 +283,7 @@ void FavouritesModel::loadFromJson(QJsonArray arr)
for (QJsonValueRef r : arr) { for (QJsonValueRef r : arr) {
QJsonObject obj = r.toObject(); QJsonObject obj = r.toObject();
FolioDelegate *delegate = FolioDelegate::fromJson(obj, this); FolioDelegate *delegate = FolioDelegate::fromJson(obj, m_homeScreen);
if (delegate) { if (delegate) {
connectSaveRequests(delegate); connectSaveRequests(delegate);
@ -301,16 +302,13 @@ void FavouritesModel::connectSaveRequests(FolioDelegate *delegate)
} }
} }
void FavouritesModel::setContainment(Plasma::Containment *containment)
{
m_containment = containment;
}
bool FavouritesModel::dropPositionIsEdge(qreal x, qreal y) const bool FavouritesModel::dropPositionIsEdge(qreal x, qreal y) const
{ {
auto homeScreenState = m_homeScreen->homeScreenState();
qreal startPosition = getDelegateRowStartPos(); qreal startPosition = getDelegateRowStartPos();
bool isLocationBottom = HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom; bool isLocationBottom = homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom;
qreal cellLength = isLocationBottom ? HomeScreenState::self()->pageCellWidth() : HomeScreenState::self()->pageCellHeight(); qreal cellLength = isLocationBottom ? homeScreenState->pageCellWidth() : homeScreenState->pageCellHeight();
qreal pos = isLocationBottom ? x : y; qreal pos = isLocationBottom ? x : y;
@ -334,9 +332,11 @@ bool FavouritesModel::dropPositionIsEdge(qreal x, qreal y) const
int FavouritesModel::dropInsertPosition(qreal x, qreal y) const int FavouritesModel::dropInsertPosition(qreal x, qreal y) const
{ {
auto homeScreenState = m_homeScreen->homeScreenState();
qreal startPosition = getDelegateRowStartPos(); qreal startPosition = getDelegateRowStartPos();
bool isLocationBottom = HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom; bool isLocationBottom = homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom;
qreal cellLength = isLocationBottom ? HomeScreenState::self()->pageCellWidth() : HomeScreenState::self()->pageCellHeight(); qreal cellLength = isLocationBottom ? homeScreenState->pageCellWidth() : homeScreenState->pageCellHeight();
qreal pos = isLocationBottom ? x : y; qreal pos = isLocationBottom ? x : y;
@ -361,20 +361,21 @@ QPointF FavouritesModel::getDelegateScreenPosition(int position) const
{ {
position = adjustIndex(position); position = adjustIndex(position);
qreal screenHeight = HomeScreenState::self()->viewHeight(); auto homeScreenState = m_homeScreen->homeScreenState();
qreal screenWidth = HomeScreenState::self()->viewWidth(); qreal screenHeight = homeScreenState->viewHeight();
qreal pageHeight = HomeScreenState::self()->pageHeight(); qreal screenWidth = homeScreenState->viewWidth();
qreal pageWidth = HomeScreenState::self()->pageWidth(); qreal pageHeight = homeScreenState->pageHeight();
qreal screenTopPadding = HomeScreenState::self()->viewTopPadding(); qreal pageWidth = homeScreenState->pageWidth();
qreal screenBottomPadding = HomeScreenState::self()->viewBottomPadding(); qreal screenTopPadding = homeScreenState->viewTopPadding();
qreal screenLeftPadding = HomeScreenState::self()->viewLeftPadding(); qreal screenBottomPadding = homeScreenState->viewBottomPadding();
qreal screenRightPadding = HomeScreenState::self()->viewRightPadding(); qreal screenLeftPadding = homeScreenState->viewLeftPadding();
qreal cellHeight = HomeScreenState::self()->pageCellHeight(); qreal screenRightPadding = homeScreenState->viewRightPadding();
qreal cellWidth = HomeScreenState::self()->pageCellWidth(); qreal cellHeight = homeScreenState->pageCellHeight();
qreal cellWidth = homeScreenState->pageCellWidth();
qreal startPosition = getDelegateRowStartPos(); qreal startPosition = getDelegateRowStartPos();
switch (HomeScreenState::self()->favouritesBarLocation()) { switch (homeScreenState->favouritesBarLocation()) {
case HomeScreenState::Bottom: { case HomeScreenState::Bottom: {
qreal favouritesHeight = screenHeight - pageHeight - screenBottomPadding - screenTopPadding; qreal favouritesHeight = screenHeight - pageHeight - screenBottomPadding - screenTopPadding;
qreal x = screenLeftPadding + startPosition + cellWidth * position; qreal x = screenLeftPadding + startPosition + cellWidth * position;
@ -399,8 +400,10 @@ QPointF FavouritesModel::getDelegateScreenPosition(int position) const
void FavouritesModel::evaluateDelegatePositions(bool emitSignal) void FavouritesModel::evaluateDelegatePositions(bool emitSignal)
{ {
bool isLocationBottom = HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom; auto homeScreenState = m_homeScreen->homeScreenState();
qreal cellLength = isLocationBottom ? HomeScreenState::self()->pageCellWidth() : HomeScreenState::self()->pageCellHeight();
bool isLocationBottom = homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom;
qreal cellLength = isLocationBottom ? homeScreenState->pageCellWidth() : homeScreenState->pageCellHeight();
qreal startPosition = getDelegateRowStartPos(); qreal startPosition = getDelegateRowStartPos();
qreal currentPos = startPosition; qreal currentPos = startPosition;
@ -416,13 +419,15 @@ void FavouritesModel::evaluateDelegatePositions(bool emitSignal)
qreal FavouritesModel::getDelegateRowStartPos() const qreal FavouritesModel::getDelegateRowStartPos() const
{ {
const int length = m_delegates.size(); auto homeScreenState = m_homeScreen->homeScreenState();
const bool isLocationBottom = HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom;
const qreal cellLength = isLocationBottom ? HomeScreenState::self()->pageCellWidth() : HomeScreenState::self()->pageCellHeight();
const qreal pageLength = isLocationBottom ? HomeScreenState::self()->pageWidth() : HomeScreenState::self()->pageHeight();
const qreal topMargin = HomeScreenState::self()->viewTopPadding(); const int length = m_delegates.size();
const qreal leftMargin = HomeScreenState::self()->viewLeftPadding(); const bool isLocationBottom = homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom;
const qreal cellLength = isLocationBottom ? homeScreenState->pageCellWidth() : homeScreenState->pageCellHeight();
const qreal pageLength = isLocationBottom ? homeScreenState->pageWidth() : homeScreenState->pageHeight();
const qreal topMargin = homeScreenState->viewTopPadding();
const qreal leftMargin = homeScreenState->viewLeftPadding();
const qreal panelOffset = isLocationBottom ? leftMargin : topMargin; const qreal panelOffset = isLocationBottom ? leftMargin : topMargin;
return (pageLength / 2) - (((qreal)length) / 2) * cellLength + panelOffset; return (pageLength / 2) - (((qreal)length) / 2) * cellLength + panelOffset;
@ -430,8 +435,9 @@ qreal FavouritesModel::getDelegateRowStartPos() const
int FavouritesModel::adjustIndex(int index) const int FavouritesModel::adjustIndex(int index) const
{ {
if (HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Bottom auto homeScreenState = m_homeScreen->homeScreenState();
|| HomeScreenState::self()->favouritesBarLocation() == HomeScreenState::Left) {
if (homeScreenState->favouritesBarLocation() == HomeScreenState::Bottom || homeScreenState->favouritesBarLocation() == HomeScreenState::Left) {
return index; return index;
} else { } else {
// if it's on the right side of the screen, we flip the order of the delegates // if it's on the right side of the screen, we flip the order of the delegates

View file

@ -11,9 +11,13 @@
#include <QQuickItem> #include <QQuickItem>
#include <QSet> #include <QSet>
#include <Plasma/Containment> #include <Plasma/Applet>
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreen.h"
class HomeScreen;
class FolioDelegate;
struct FavouritesDelegate { struct FavouritesDelegate {
FolioDelegate *delegate; FolioDelegate *delegate;
@ -30,8 +34,7 @@ public:
XPositionRole, XPositionRole,
}; };
FavouritesModel(QObject *parent = nullptr); FavouritesModel(HomeScreen *parent = nullptr);
static FavouritesModel *self();
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@ -68,8 +71,6 @@ public:
Q_INVOKABLE void load(); Q_INVOKABLE void load();
void loadFromJson(QJsonArray arr); void loadFromJson(QJsonArray arr);
void setContainment(Plasma::Containment *containment);
private: private:
void connectSaveRequests(FolioDelegate *delegate); void connectSaveRequests(FolioDelegate *delegate);
void evaluateDelegatePositions(bool emitSignal = true); void evaluateDelegatePositions(bool emitSignal = true);
@ -81,7 +82,7 @@ private:
// this is so that we only have to calculate positions assuming one orientation // this is so that we only have to calculate positions assuming one orientation
int adjustIndex(int index) const; int adjustIndex(int index) const;
QList<FavouritesDelegate> m_delegates; HomeScreen *m_homeScreen{nullptr};
Plasma::Containment *m_containment{nullptr}; QList<FavouritesDelegate> m_delegates;
}; };

View file

@ -9,7 +9,7 @@
#include <KNotificationJobUiDelegate> #include <KNotificationJobUiDelegate>
FolioApplication::FolioApplication(QObject *parent, KService::Ptr service) FolioApplication::FolioApplication(HomeScreen *parent, KService::Ptr service)
: QObject{parent} : QObject{parent}
, m_running{false} , m_running{false}
, m_name{service->name()} , m_name{service->name()}
@ -35,7 +35,7 @@ FolioApplication::FolioApplication(QObject *parent, KService::Ptr service)
}); });
} }
FolioApplication *FolioApplication::fromJson(QJsonObject &obj, QObject *parent) FolioApplication *FolioApplication::fromJson(QJsonObject &obj, HomeScreen *parent)
{ {
QString storageId = obj[QStringLiteral("storageId")].toString(); QString storageId = obj[QStringLiteral("storageId")].toString();
if (KService::Ptr service = KService::serviceByStorageId(storageId)) { if (KService::Ptr service = KService::serviceByStorageId(storageId)) {

View file

@ -16,6 +16,10 @@
#include <KWayland/Client/registry.h> #include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h> #include <KWayland/Client/surface.h>
#include "homescreen.h"
class HomeScreen;
/** /**
* @short Object that represents an application. * @short Object that represents an application.
*/ */
@ -28,9 +32,9 @@ class FolioApplication : public QObject
Q_PROPERTY(QString storageId READ storageId NOTIFY storageIdChanged) Q_PROPERTY(QString storageId READ storageId NOTIFY storageIdChanged)
public: public:
FolioApplication(QObject *parent = nullptr, KService::Ptr service = QExplicitlySharedDataPointer<KService>{nullptr}); FolioApplication(HomeScreen *parent = nullptr, KService::Ptr service = QExplicitlySharedDataPointer<KService>{nullptr});
static FolioApplication *fromJson(QJsonObject &obj, QObject *parent); // may return nullptr static FolioApplication *fromJson(QJsonObject &obj, HomeScreen *parent); // may return nullptr
QJsonObject toJson() const; QJsonObject toJson() const;
bool running() const; bool running() const;

View file

@ -7,14 +7,15 @@
#include <QJsonArray> #include <QJsonArray>
#include <algorithm> #include <algorithm>
FolioApplicationFolder::FolioApplicationFolder(QObject *parent, QString name) FolioApplicationFolder::FolioApplicationFolder(HomeScreen *parent, QString name)
: QObject{parent} : QObject{parent}
, m_homeScreen{parent}
, m_name{name} , m_name{name}
, m_applicationFolderModel{new ApplicationFolderModel{this}} , m_applicationFolderModel{new ApplicationFolderModel{this}}
{ {
} }
FolioApplicationFolder *FolioApplicationFolder::fromJson(QJsonObject &obj, QObject *parent) FolioApplicationFolder *FolioApplicationFolder::fromJson(QJsonObject &obj, HomeScreen *parent)
{ {
QString name = obj[QStringLiteral("name")].toString(); QString name = obj[QStringLiteral("name")].toString();
QList<FolioApplication *> apps; QList<FolioApplication *> apps;
@ -86,7 +87,7 @@ void FolioApplicationFolder::setApplications(QList<FolioApplication *> applicati
m_delegates.clear(); m_delegates.clear();
for (auto *app : applications) { for (auto *app : applications) {
m_delegates.append({new FolioDelegate{app, this}, 0, 0}); m_delegates.append({new FolioDelegate{app, m_homeScreen}, 0, 0});
} }
m_applicationFolderModel = new ApplicationFolderModel{this}; m_applicationFolderModel = new ApplicationFolderModel{this};
m_applicationFolderModel->evaluateDelegatePositions(); m_applicationFolderModel->evaluateDelegatePositions();
@ -125,28 +126,29 @@ ApplicationFolderModel::ApplicationFolderModel(FolioApplicationFolder *folder)
: QAbstractListModel{folder} : QAbstractListModel{folder}
, m_folder{folder} , m_folder{folder}
{ {
connect(HomeScreenState::self(), &HomeScreenState::folderPageWidthChanged, this, [this]() { HomeScreenState *homeScreenState = folder->m_homeScreen->homeScreenState();
connect(homeScreenState, &HomeScreenState::folderPageWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::folderPageHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::folderPageContentWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageContentWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::folderPageContentHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageContentHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::viewWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::viewWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::viewHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::viewHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageCellWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::pageCellWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
connect(HomeScreenState::self(), &HomeScreenState::pageCellHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::pageCellHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegatePositions();
}); });
} }
@ -312,7 +314,7 @@ void ApplicationFolderModel::setGhostEntry(int index)
} }
if (!ghost) { if (!ghost) {
ghost = new FolioDelegate{HomeScreenState::self()}; ghost = new FolioDelegate{m_folder->m_homeScreen};
} }
// add empty delegate at new position // add empty delegate at new position
@ -342,8 +344,8 @@ void ApplicationFolderModel::deleteGhostEntry()
int ApplicationFolderModel::dropInsertPosition(int page, qreal x, qreal y) int ApplicationFolderModel::dropInsertPosition(int page, qreal x, qreal y)
{ {
qreal cellWidth = HomeScreenState::self()->pageCellWidth(); qreal cellWidth = m_folder->m_homeScreen->homeScreenState()->pageCellWidth();
qreal cellHeight = HomeScreenState::self()->pageCellHeight(); qreal cellHeight = m_folder->m_homeScreen->homeScreenState()->pageCellHeight();
int row = (y - topMarginFromScreenEdge()) / cellHeight; int row = (y - topMarginFromScreenEdge()) / cellHeight;
row = std::max(0, std::min(numRowsOnPage(), row)); row = std::max(0, std::min(numRowsOnPage(), row));
@ -369,18 +371,18 @@ int ApplicationFolderModel::dropInsertPosition(int page, qreal x, qreal y)
bool ApplicationFolderModel::isDropPositionOutside(qreal x, qreal y) bool ApplicationFolderModel::isDropPositionOutside(qreal x, qreal y)
{ {
return (x < leftMarginFromScreenEdge()) || (x > (HomeScreenState::self()->viewWidth() - leftMarginFromScreenEdge())) || (y < topMarginFromScreenEdge()) return (x < leftMarginFromScreenEdge()) || (x > (m_folder->m_homeScreen->homeScreenState()->viewWidth() - leftMarginFromScreenEdge()))
|| (y > HomeScreenState::self()->viewHeight() - topMarginFromScreenEdge()); || (y < topMarginFromScreenEdge()) || (y > m_folder->m_homeScreen->homeScreenState()->viewHeight() - topMarginFromScreenEdge());
} }
void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal) void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal)
{ {
qreal pageWidth = HomeScreenState::self()->folderPageWidth(); qreal pageWidth = m_folder->m_homeScreen->homeScreenState()->folderPageWidth();
qreal topMargin = verticalPageMargin(); qreal topMargin = verticalPageMargin();
qreal leftMargin = horizontalPageMargin(); qreal leftMargin = horizontalPageMargin();
qreal cellWidth = HomeScreenState::self()->pageCellWidth(); qreal cellWidth = m_folder->m_homeScreen->homeScreenState()->pageCellWidth();
qreal cellHeight = HomeScreenState::self()->pageCellHeight(); qreal cellHeight = m_folder->m_homeScreen->homeScreenState()->pageCellHeight();
int rows = numRowsOnPage(); int rows = numRowsOnPage();
int columns = numColumnsOnPage(); int columns = numColumnsOnPage();
@ -418,7 +420,7 @@ void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal)
QPointF ApplicationFolderModel::getDelegateStartPosition(int page) QPointF ApplicationFolderModel::getDelegateStartPosition(int page)
{ {
qreal pageWidth = HomeScreenState::self()->folderPageWidth(); qreal pageWidth = m_folder->m_homeScreen->homeScreenState()->folderPageWidth();
qreal x = pageWidth * page + leftMarginFromScreenEdge(); qreal x = pageWidth * page + leftMarginFromScreenEdge();
qreal y = topMarginFromScreenEdge(); qreal y = topMarginFromScreenEdge();
@ -433,48 +435,54 @@ int ApplicationFolderModel::numTotalPages()
int ApplicationFolderModel::numRowsOnPage() int ApplicationFolderModel::numRowsOnPage()
{ {
qreal contentHeight = HomeScreenState::self()->folderPageContentHeight(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal cellHeight = HomeScreenState::self()->pageCellHeight(); qreal contentHeight = homeScreenState->folderPageContentHeight();
qreal cellHeight = homeScreenState->pageCellHeight();
return std::max(0.0, contentHeight / cellHeight); return std::max(0.0, contentHeight / cellHeight);
} }
int ApplicationFolderModel::numColumnsOnPage() int ApplicationFolderModel::numColumnsOnPage()
{ {
qreal contentWidth = HomeScreenState::self()->folderPageContentWidth(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal cellWidth = HomeScreenState::self()->pageCellWidth(); qreal contentWidth = homeScreenState->folderPageContentWidth();
qreal cellWidth = homeScreenState->pageCellWidth();
return std::max(0.0, contentWidth / cellWidth); return std::max(0.0, contentWidth / cellWidth);
} }
qreal ApplicationFolderModel::leftMarginFromScreenEdge() qreal ApplicationFolderModel::leftMarginFromScreenEdge()
{ {
qreal viewWidth = HomeScreenState::self()->viewWidth(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal folderPageWidth = HomeScreenState::self()->folderPageWidth(); qreal viewWidth = homeScreenState->viewWidth();
qreal folderPageWidth = homeScreenState->folderPageWidth();
return (viewWidth - folderPageWidth) / 2 + horizontalPageMargin(); return (viewWidth - folderPageWidth) / 2 + horizontalPageMargin();
} }
qreal ApplicationFolderModel::topMarginFromScreenEdge() qreal ApplicationFolderModel::topMarginFromScreenEdge()
{ {
qreal viewHeight = HomeScreenState::self()->viewHeight(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal folderPageHeight = HomeScreenState::self()->folderPageHeight(); qreal viewHeight = homeScreenState->viewHeight();
qreal folderPageHeight = homeScreenState->folderPageHeight();
return (viewHeight - folderPageHeight) / 2 + verticalPageMargin(); return (viewHeight - folderPageHeight) / 2 + verticalPageMargin();
} }
qreal ApplicationFolderModel::horizontalPageMargin() qreal ApplicationFolderModel::horizontalPageMargin()
{ {
qreal pageWidth = HomeScreenState::self()->folderPageWidth(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal pageContentWidth = HomeScreenState::self()->folderPageContentWidth(); qreal pageWidth = homeScreenState->folderPageWidth();
qreal pageContentWidth = homeScreenState->folderPageContentWidth();
return (pageWidth - pageContentWidth) / 2; return (pageWidth - pageContentWidth) / 2;
} }
qreal ApplicationFolderModel::verticalPageMargin() qreal ApplicationFolderModel::verticalPageMargin()
{ {
qreal pageHeight = HomeScreenState::self()->folderPageHeight(); HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal pageContentHeight = HomeScreenState::self()->folderPageContentHeight(); qreal pageHeight = homeScreenState->folderPageHeight();
qreal pageContentHeight = homeScreenState->folderPageContentHeight();
return (pageHeight - pageContentHeight) / 2; return (pageHeight - pageContentHeight) / 2;
} }

View file

@ -5,6 +5,7 @@
#include "folioapplication.h" #include "folioapplication.h"
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreen.h"
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
@ -17,9 +18,11 @@
#include <KWayland/Client/registry.h> #include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h> #include <KWayland/Client/surface.h>
class HomeScreen;
struct ApplicationDelegate; struct ApplicationDelegate;
class ApplicationFolderModel; class ApplicationFolderModel;
class FolioDelegate; class FolioDelegate;
class FolioApplication;
/** /**
* @short Object that represents an application folder. * @short Object that represents an application folder.
@ -33,9 +36,9 @@ class FolioApplicationFolder : public QObject
Q_PROPERTY(ApplicationFolderModel *applications READ applications NOTIFY applicationsReset) Q_PROPERTY(ApplicationFolderModel *applications READ applications NOTIFY applicationsReset)
public: public:
FolioApplicationFolder(QObject *parent = nullptr, QString name = QString{}); FolioApplicationFolder(HomeScreen *parent = nullptr, QString name = QString{});
static FolioApplicationFolder *fromJson(QJsonObject &obj, QObject *parent); static FolioApplicationFolder *fromJson(QJsonObject &obj, HomeScreen *parent);
QJsonObject toJson() const; QJsonObject toJson() const;
QString name() const; QString name() const;
@ -60,9 +63,11 @@ Q_SIGNALS:
void applicationsReset(); void applicationsReset();
private: private:
HomeScreen *m_homeScreen{nullptr};
QString m_name; QString m_name;
QList<ApplicationDelegate> m_delegates; QList<ApplicationDelegate> m_delegates;
ApplicationFolderModel *m_applicationFolderModel; ApplicationFolderModel *m_applicationFolderModel{nullptr};
friend class ApplicationFolderModel; friend class ApplicationFolderModel;
}; };

View file

@ -4,7 +4,7 @@
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreenstate.h" #include "homescreenstate.h"
FolioDelegate::FolioDelegate(QObject *parent) FolioDelegate::FolioDelegate(HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_type{FolioDelegate::None} , m_type{FolioDelegate::None}
, m_application{nullptr} , m_application{nullptr}
@ -13,7 +13,7 @@ FolioDelegate::FolioDelegate(QObject *parent)
{ {
} }
FolioDelegate::FolioDelegate(FolioApplication *application, QObject *parent) FolioDelegate::FolioDelegate(FolioApplication *application, HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_type{FolioDelegate::Application} , m_type{FolioDelegate::Application}
, m_application{application} , m_application{application}
@ -22,7 +22,7 @@ FolioDelegate::FolioDelegate(FolioApplication *application, QObject *parent)
{ {
} }
FolioDelegate::FolioDelegate(FolioApplicationFolder *folder, QObject *parent) FolioDelegate::FolioDelegate(FolioApplicationFolder *folder, HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_type{FolioDelegate::Folder} , m_type{FolioDelegate::Folder}
, m_application{nullptr} , m_application{nullptr}
@ -31,7 +31,7 @@ FolioDelegate::FolioDelegate(FolioApplicationFolder *folder, QObject *parent)
{ {
} }
FolioDelegate::FolioDelegate(FolioWidget *widget, QObject *parent) FolioDelegate::FolioDelegate(FolioWidget *widget, HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_type{FolioDelegate::Widget} , m_type{FolioDelegate::Widget}
, m_application{nullptr} , m_application{nullptr}
@ -40,7 +40,7 @@ FolioDelegate::FolioDelegate(FolioWidget *widget, QObject *parent)
{ {
} }
FolioDelegate *FolioDelegate::fromJson(QJsonObject &obj, QObject *parent) FolioDelegate *FolioDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
{ {
const QString type = obj[QStringLiteral("type")].toString(); const QString type = obj[QStringLiteral("type")].toString();
if (type == "application") { if (type == "application") {
@ -112,3 +112,277 @@ FolioWidget *FolioDelegate::widget()
{ {
return m_widget; return m_widget;
} }
FolioPageDelegate::FolioPageDelegate(int row, int column, HomeScreen *parent)
: FolioDelegate{parent}
, m_homeScreen{parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplication *application, HomeScreen *parent)
: FolioDelegate{application, parent}
, m_homeScreen{parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplicationFolder *folder, HomeScreen *parent)
: FolioDelegate{folder, parent}
, m_homeScreen{parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioWidget *widget, HomeScreen *parent)
: FolioDelegate{widget, parent}
, m_homeScreen{parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioDelegate *delegate, HomeScreen *parent)
: FolioDelegate{parent}
, m_homeScreen{parent}
, m_row{row}
, m_column{column}
{
m_type = delegate->type();
m_application = delegate->application();
m_folder = delegate->folder();
m_widget = delegate->widget();
init();
}
void FolioPageDelegate::init()
{
HomeScreenState *homeScreenState = m_homeScreen->homeScreenState();
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (homeScreenState->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realRow = m_row;
m_realColumn = m_column;
break;
case HomeScreenState::RotateClockwise:
m_realRow = homeScreenState->pageColumns() - m_column - 1;
m_realColumn = m_row;
if (m_widget) {
// since top-left in cw is bottom-left in portrait
m_realRow -= m_widget->realGridHeight() - 1;
}
break;
case HomeScreenState::RotateCounterClockwise:
m_realRow = m_column;
m_realColumn = homeScreenState->pageRows() - m_row - 1;
if (m_widget) {
// since top-left in ccw is top-right in portrait
m_realColumn -= m_widget->realGridWidth() - 1;
}
break;
case HomeScreenState::RotateUpsideDown:
m_realRow = homeScreenState->pageRows() - m_row - 1;
m_realColumn = homeScreenState->pageColumns() - m_column - 1;
if (m_widget) {
// since top-left in upside-down is bottom-right in portrait
m_realRow -= m_widget->realGridHeight() - 1;
m_realColumn -= m_widget->realGridWidth() - 1;
}
break;
}
if (m_widget) {
connect(m_widget, &FolioWidget::realTopLeftPositionChanged, this, [this](int rowOffset, int columnOffset) {
m_realRow += rowOffset;
m_realColumn += columnOffset;
});
}
connect(homeScreenState, &HomeScreenState::pageOrientationChanged, this, [this]() {
setRowOnly(getTranslatedTopLeftRow(m_homeScreen, m_realRow, m_realColumn, this));
setColumnOnly(getTranslatedTopLeftColumn(m_homeScreen, m_realRow, m_realColumn, this));
});
}
FolioPageDelegate *FolioPageDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
{
FolioDelegate *fd = FolioDelegate::fromJson(obj, parent);
if (!fd) {
return nullptr;
}
int realRow = obj[QStringLiteral("row")].toInt();
int realColumn = obj[QStringLiteral("column")].toInt();
int row = getTranslatedTopLeftRow(parent, realRow, realColumn, fd);
int column = getTranslatedTopLeftColumn(parent, realRow, realColumn, fd);
FolioPageDelegate *delegate = new FolioPageDelegate{row, column, fd, parent};
fd->deleteLater();
return delegate;
}
int FolioPageDelegate::getTranslatedTopLeftRow(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd)
{
int row = getTranslatedRow(homeScreen, realRow, realColumn);
int column = getTranslatedColumn(homeScreen, realRow, realColumn);
// special logic to return "top left" for widgets, since they take more than one tile
if (fd->type() == FolioDelegate::Widget) {
return fd->widget()->topLeftCorner(row, column).row;
} else {
return row;
}
}
int FolioPageDelegate::getTranslatedTopLeftColumn(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd)
{
int row = getTranslatedRow(homeScreen, realRow, realColumn);
int column = getTranslatedColumn(homeScreen, realRow, realColumn);
// special logic to return "top left" for widgets, since they take more than one tile
if (fd->type() == FolioDelegate::Widget) {
return fd->widget()->topLeftCorner(row, column).column;
} else {
return column;
}
}
int FolioPageDelegate::getTranslatedRow(HomeScreen *homeScreen, int realRow, int realColumn)
{
HomeScreenState *homeScreenState = homeScreen->homeScreenState();
FolioSettings *folioSettings = homeScreen->folioSettings();
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (homeScreenState->pageOrientation()) {
case HomeScreenState::RegularPosition:
return realRow;
case HomeScreenState::RotateClockwise:
return realColumn;
case HomeScreenState::RotateCounterClockwise:
return folioSettings->homeScreenColumns() - realColumn - 1;
case HomeScreenState::RotateUpsideDown:
return folioSettings->homeScreenRows() - realRow - 1;
}
return realRow;
}
int FolioPageDelegate::getTranslatedColumn(HomeScreen *homeScreen, int realRow, int realColumn)
{
HomeScreenState *homeScreenState = homeScreen->homeScreenState();
FolioSettings *folioSettings = homeScreen->folioSettings();
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (homeScreenState->pageOrientation()) {
case HomeScreenState::RegularPosition:
return realColumn;
case HomeScreenState::RotateClockwise:
return folioSettings->homeScreenRows() - realRow - 1;
case HomeScreenState::RotateCounterClockwise:
return realRow;
case HomeScreenState::RotateUpsideDown:
return folioSettings->homeScreenColumns() - realColumn - 1;
}
return realRow;
}
QJsonObject FolioPageDelegate::toJson() const
{
QJsonObject o = FolioDelegate::toJson();
o[QStringLiteral("row")] = m_realRow;
o[QStringLiteral("column")] = m_realColumn;
return o;
}
int FolioPageDelegate::row()
{
return m_row;
}
void FolioPageDelegate::setRow(int row)
{
HomeScreenState *homeScreenState = m_homeScreen->homeScreenState();
if (m_row != row) {
// adjust stored data too
switch (homeScreenState->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realRow = row;
break;
case HomeScreenState::RotateClockwise:
m_realColumn += row - m_row;
break;
case HomeScreenState::RotateCounterClockwise:
m_realColumn += m_row - row;
break;
case HomeScreenState::RotateUpsideDown:
m_realRow += m_row - row;
break;
}
setRowOnly(row);
}
}
void FolioPageDelegate::setRowOnly(int row)
{
if (m_row != row) {
m_row = row;
Q_EMIT rowChanged();
}
}
int FolioPageDelegate::column()
{
return m_column;
}
void FolioPageDelegate::setColumn(int column)
{
HomeScreenState *homeScreenState = m_homeScreen->homeScreenState();
if (m_column != column) {
// adjust stored data too
switch (homeScreenState->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realColumn = column;
break;
case HomeScreenState::RotateClockwise:
m_realRow += m_column - column;
break;
case HomeScreenState::RotateCounterClockwise:
m_realRow += column - m_column;
break;
case HomeScreenState::RotateUpsideDown:
m_realColumn += m_column - column;
break;
}
setColumnOnly(column);
}
}
void FolioPageDelegate::setColumnOnly(int column)
{
if (m_column != column) {
m_column = column;
Q_EMIT columnChanged();
}
}

View file

@ -8,9 +8,13 @@
#include "folioapplication.h" #include "folioapplication.h"
#include "folioapplicationfolder.h" #include "folioapplicationfolder.h"
#include "foliowidget.h" #include "foliowidget.h"
#include "homescreen.h"
class HomeScreen;
class FolioApplication; class FolioApplication;
class FolioApplicationFolder; class FolioApplicationFolder;
class FolioWidget;
class FolioDelegate : public QObject class FolioDelegate : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -28,12 +32,12 @@ public:
}; };
Q_ENUM(Type) Q_ENUM(Type)
FolioDelegate(QObject *parent = nullptr); FolioDelegate(HomeScreen *parent = nullptr);
FolioDelegate(FolioApplication *application, QObject *parent); FolioDelegate(FolioApplication *application, HomeScreen *parent);
FolioDelegate(FolioApplicationFolder *folder, QObject *parent); FolioDelegate(FolioApplicationFolder *folder, HomeScreen *parent);
FolioDelegate(FolioWidget *widget, QObject *parent); FolioDelegate(FolioWidget *widget, HomeScreen *parent);
static FolioDelegate *fromJson(QJsonObject &obj, QObject *parent); static FolioDelegate *fromJson(QJsonObject &obj, HomeScreen *parent);
virtual QJsonObject toJson() const; virtual QJsonObject toJson() const;
@ -48,3 +52,48 @@ protected:
FolioApplicationFolder *m_folder{nullptr}; FolioApplicationFolder *m_folder{nullptr};
FolioWidget *m_widget{nullptr}; FolioWidget *m_widget{nullptr};
}; };
class FolioPageDelegate : public FolioDelegate
{
Q_OBJECT
Q_PROPERTY(int row READ row NOTIFY rowChanged)
Q_PROPERTY(int column READ column NOTIFY columnChanged)
QML_UNCREATABLE("")
public:
FolioPageDelegate(int row = 0, int column = 0, HomeScreen *parent = nullptr);
FolioPageDelegate(int row, int column, FolioApplication *application, HomeScreen *parent);
FolioPageDelegate(int row, int column, FolioApplicationFolder *folder, HomeScreen *parent);
FolioPageDelegate(int row, int column, FolioWidget *widget, HomeScreen *parent);
FolioPageDelegate(int row, int column, FolioDelegate *delegate, HomeScreen *parent);
static FolioPageDelegate *fromJson(QJsonObject &obj, HomeScreen *parent);
static int getTranslatedTopLeftRow(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd);
static int getTranslatedTopLeftColumn(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd);
static int getTranslatedRow(HomeScreen *homeScreen, int realRow, int realColumn);
static int getTranslatedColumn(HomeScreen *homeScreen, int realRow, int realColumn);
virtual QJsonObject toJson() const override;
int row();
void setRow(int row);
int column();
void setColumn(int column);
Q_SIGNALS:
void rowChanged();
void columnChanged();
private:
void setRowOnly(int row);
void setColumnOnly(int column);
void init();
HomeScreen *m_homeScreen{nullptr};
int m_realRow;
int m_realColumn;
int m_row;
int m_column;
};

View file

@ -10,17 +10,12 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QTextStream> #include <QTextStream>
FolioSettings::FolioSettings(QObject *parent) FolioSettings::FolioSettings(HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_homeScreen{parent}
{ {
} }
FolioSettings *FolioSettings::self()
{
static FolioSettings *settings = new FolioSettings;
return settings;
}
int FolioSettings::homeScreenRows() const int FolioSettings::homeScreenRows() const
{ {
// ensure that this is fetched fast and cached (it is called extremely often) // ensure that this is fetched fast and cached (it is called extremely often)
@ -134,43 +129,38 @@ void FolioSettings::setShowWallpaperBlur(bool showWallpaperBlur)
} }
} }
void FolioSettings::setApplet(Plasma::Applet *applet)
{
m_applet = applet;
}
void FolioSettings::save() void FolioSettings::save()
{ {
if (!m_applet) { if (!m_homeScreen) {
return; return;
} }
m_applet->config().writeEntry("homeScreenRows", m_homeScreenRows); m_homeScreen->config().writeEntry("homeScreenRows", m_homeScreenRows);
m_applet->config().writeEntry("homeScreenColumns", m_homeScreenColumns); m_homeScreen->config().writeEntry("homeScreenColumns", m_homeScreenColumns);
m_applet->config().writeEntry("showPagesAppLabels", m_showPagesAppLabels); m_homeScreen->config().writeEntry("showPagesAppLabels", m_showPagesAppLabels);
m_applet->config().writeEntry("showFavouritesAppLabels", m_showFavouritesAppLabels); m_homeScreen->config().writeEntry("showFavouritesAppLabels", m_showFavouritesAppLabels);
m_applet->config().writeEntry("delegateIconSize", m_delegateIconSize); m_homeScreen->config().writeEntry("delegateIconSize", m_delegateIconSize);
m_applet->config().writeEntry("showFavouritesBarBackground", m_showFavouritesBarBackground); m_homeScreen->config().writeEntry("showFavouritesBarBackground", m_showFavouritesBarBackground);
m_applet->config().writeEntry("pageTransitionEffect", (int)m_pageTransitionEffect); m_homeScreen->config().writeEntry("pageTransitionEffect", (int)m_pageTransitionEffect);
m_applet->config().writeEntry("showWallpaperBlur", m_showWallpaperBlur); m_homeScreen->config().writeEntry("showWallpaperBlur", m_showWallpaperBlur);
Q_EMIT m_applet->configNeedsSaving(); Q_EMIT m_homeScreen->configNeedsSaving();
} }
void FolioSettings::load() void FolioSettings::load()
{ {
if (!m_applet) { if (!m_homeScreen) {
return; return;
} }
m_homeScreenRows = m_applet->config().readEntry("homeScreenRows", 5); m_homeScreenRows = m_homeScreen->config().readEntry("homeScreenRows", 5);
m_homeScreenColumns = m_applet->config().readEntry("homeScreenColumns", 4); m_homeScreenColumns = m_homeScreen->config().readEntry("homeScreenColumns", 4);
m_showPagesAppLabels = m_applet->config().readEntry("showPagesAppLabels", true); m_showPagesAppLabels = m_homeScreen->config().readEntry("showPagesAppLabels", true);
m_showFavouritesAppLabels = m_applet->config().readEntry("showFavoritesAppLabels", false); m_showFavouritesAppLabels = m_homeScreen->config().readEntry("showFavoritesAppLabels", false);
m_delegateIconSize = m_applet->config().readEntry("delegateIconSize", 48); m_delegateIconSize = m_homeScreen->config().readEntry("delegateIconSize", 48);
m_showFavouritesBarBackground = m_applet->config().readEntry("showFavoritesBarBackground", true); m_showFavouritesBarBackground = m_homeScreen->config().readEntry("showFavoritesBarBackground", true);
m_pageTransitionEffect = static_cast<PageTransitionEffect>(m_applet->config().readEntry("pageTransitionEffect", (int)SlideTransition)); m_pageTransitionEffect = static_cast<PageTransitionEffect>(m_homeScreen->config().readEntry("pageTransitionEffect", (int)SlideTransition));
m_showWallpaperBlur = m_applet->config().readEntry("showWallpaperBlur", true); m_showWallpaperBlur = m_homeScreen->config().readEntry("showWallpaperBlur", true);
Q_EMIT homeScreenRowsChanged(); Q_EMIT homeScreenRowsChanged();
Q_EMIT homeScreenColumnsChanged(); Q_EMIT homeScreenColumnsChanged();
@ -182,12 +172,16 @@ void FolioSettings::load()
bool FolioSettings::saveLayoutToFile(QString path) bool FolioSettings::saveLayoutToFile(QString path)
{ {
if (!m_homeScreen) {
return false;
}
if (path.startsWith(QStringLiteral("file://"))) { if (path.startsWith(QStringLiteral("file://"))) {
path = path.replace(QStringLiteral("file://"), QString()); path = path.replace(QStringLiteral("file://"), QString());
} }
QJsonArray favourites = FavouritesModel::self()->exportToJson(); QJsonArray favourites = m_homeScreen->favouritesModel()->exportToJson();
QJsonArray pages = PageListModel::self()->exportToJson(); QJsonArray pages = m_homeScreen->pageListModel()->exportToJson();
QJsonObject obj; QJsonObject obj;
obj[QStringLiteral("Favourites")] = favourites; obj[QStringLiteral("Favourites")] = favourites;
@ -209,6 +203,10 @@ bool FolioSettings::saveLayoutToFile(QString path)
bool FolioSettings::loadLayoutFromFile(QString path) bool FolioSettings::loadLayoutFromFile(QString path)
{ {
if (!m_homeScreen) {
return false;
}
if (path.startsWith(QStringLiteral("file://"))) { if (path.startsWith(QStringLiteral("file://"))) {
path = path.replace(QStringLiteral("file://"), QString()); path = path.replace(QStringLiteral("file://"), QString());
} }
@ -227,11 +225,11 @@ bool FolioSettings::loadLayoutFromFile(QString path)
QJsonObject obj = doc.object(); QJsonObject obj = doc.object();
// TODO error checking // TODO error checking
FavouritesModel::self()->loadFromJson(obj[QStringLiteral("Favourites")].toArray()); m_homeScreen->favouritesModel()->loadFromJson(obj[QStringLiteral("Favourites")].toArray());
PageListModel::self()->loadFromJson(obj[QStringLiteral("Pages")].toArray()); m_homeScreen->pageListModel()->loadFromJson(obj[QStringLiteral("Pages")].toArray());
FavouritesModel::self()->save(); m_homeScreen->favouritesModel()->save();
PageListModel::self()->save(); m_homeScreen->pageListModel()->save();
return true; return true;
} }

View file

@ -7,6 +7,10 @@
#include <Plasma/Applet> #include <Plasma/Applet>
#include "homescreen.h"
class HomeScreen;
class FolioSettings : public QObject class FolioSettings : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -21,9 +25,7 @@ class FolioSettings : public QObject
Q_PROPERTY(bool showWallpaperBlur READ showWallpaperBlur WRITE setShowWallpaperBlur NOTIFY showWallpaperBlurChanged) Q_PROPERTY(bool showWallpaperBlur READ showWallpaperBlur WRITE setShowWallpaperBlur NOTIFY showWallpaperBlurChanged)
public: public:
FolioSettings(QObject *parent = nullptr); FolioSettings(HomeScreen *parent = nullptr);
static FolioSettings *self();
// ensure that existing enum values are the same when modifying, since this value is saved // ensure that existing enum values are the same when modifying, since this value is saved
enum PageTransitionEffect { enum PageTransitionEffect {
@ -67,8 +69,6 @@ public:
Q_INVOKABLE bool saveLayoutToFile(QString path); Q_INVOKABLE bool saveLayoutToFile(QString path);
Q_INVOKABLE bool loadLayoutFromFile(QString path); Q_INVOKABLE bool loadLayoutFromFile(QString path);
Q_INVOKABLE void setApplet(Plasma::Applet *applet);
Q_SIGNALS: Q_SIGNALS:
void homeScreenRowsChanged(); void homeScreenRowsChanged();
void homeScreenColumnsChanged(); void homeScreenColumnsChanged();
@ -82,6 +82,8 @@ Q_SIGNALS:
private: private:
void save(); void save();
HomeScreen *m_homeScreen{nullptr};
int m_homeScreenRows{5}; int m_homeScreenRows{5};
int m_homeScreenColumns{4}; int m_homeScreenColumns{4};
bool m_showPagesAppLabels{false}; bool m_showPagesAppLabels{false};
@ -90,6 +92,4 @@ private:
bool m_showFavouritesBarBackground{false}; bool m_showFavouritesBarBackground{false};
PageTransitionEffect m_pageTransitionEffect{SlideTransition}; PageTransitionEffect m_pageTransitionEffect{SlideTransition};
bool m_showWallpaperBlur{false}; bool m_showWallpaperBlur{false};
Plasma::Applet *m_applet{nullptr};
}; };

View file

@ -5,23 +5,25 @@
#include "homescreenstate.h" #include "homescreenstate.h"
#include "widgetsmanager.h" #include "widgetsmanager.h"
FolioWidget::FolioWidget(QObject *parent, int id, int realGridWidth, int realGridHeight) FolioWidget::FolioWidget(HomeScreen *parent, int id, int realGridWidth, int realGridHeight)
: QObject{parent} : QObject{parent}
, m_homeScreen{parent}
, m_id{id} , m_id{id}
, m_realGridWidth{realGridWidth} , m_realGridWidth{realGridWidth}
, m_realGridHeight{realGridHeight} , m_realGridHeight{realGridHeight}
, m_applet{nullptr} , m_applet{nullptr}
, m_quickApplet{nullptr} , m_quickApplet{nullptr}
{ {
auto *applet = WidgetsManager::self()->getWidget(id); auto *applet = m_homeScreen->widgetsManager()->getWidget(id);
if (applet) { if (applet) {
setApplet(applet); setApplet(applet);
} }
init(); init();
} }
FolioWidget::FolioWidget(QObject *parent, Plasma::Applet *applet, int realGridWidth, int realGridHeight) FolioWidget::FolioWidget(HomeScreen *parent, Plasma::Applet *applet, int realGridWidth, int realGridHeight)
: QObject{parent} : QObject{parent}
, m_homeScreen{parent}
, m_id{applet ? static_cast<int>(applet->id()) : -1} , m_id{applet ? static_cast<int>(applet->id()) : -1}
, m_realGridWidth{realGridWidth} , m_realGridWidth{realGridWidth}
, m_realGridHeight{realGridHeight} , m_realGridHeight{realGridHeight}
@ -32,24 +34,24 @@ FolioWidget::FolioWidget(QObject *parent, Plasma::Applet *applet, int realGridWi
void FolioWidget::init() void FolioWidget::init()
{ {
connect(HomeScreenState::self(), &HomeScreenState::pageOrientationChanged, this, [this]() { connect(m_homeScreen->homeScreenState(), &HomeScreenState::pageOrientationChanged, this, [this]() {
Q_EMIT gridWidthChanged(); Q_EMIT gridWidthChanged();
Q_EMIT gridHeightChanged(); Q_EMIT gridHeightChanged();
}); });
connect(WidgetsManager::self(), &WidgetsManager::widgetAdded, this, [this](Plasma::Applet *applet) { connect(m_homeScreen->widgetsManager(), &WidgetsManager::widgetAdded, this, [this](Plasma::Applet *applet) {
if (applet && static_cast<int>(applet->id()) == m_id) { if (applet && static_cast<int>(applet->id()) == m_id) {
setApplet(applet); setApplet(applet);
} }
}); });
connect(WidgetsManager::self(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) { connect(m_homeScreen->widgetsManager(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) {
if (applet && static_cast<int>(applet->id()) == m_id) { if (applet && static_cast<int>(applet->id()) == m_id) {
setApplet(nullptr); setApplet(nullptr);
} }
}); });
} }
FolioWidget *FolioWidget::fromJson(QJsonObject &obj, QObject *parent) FolioWidget *FolioWidget::fromJson(QJsonObject &obj, HomeScreen *parent)
{ {
int id = obj[QStringLiteral("id")].toInt(); int id = obj[QStringLiteral("id")].toInt();
int gridWidth = obj[QStringLiteral("gridWidth")].toInt(); int gridWidth = obj[QStringLiteral("gridWidth")].toInt();
@ -74,7 +76,7 @@ int FolioWidget::id() const
int FolioWidget::gridWidth() const int FolioWidget::gridWidth() const
{ {
switch (HomeScreenState::self()->pageOrientation()) { switch (m_homeScreen->homeScreenState()->pageOrientation()) {
case HomeScreenState::RegularPosition: case HomeScreenState::RegularPosition:
return m_realGridWidth; return m_realGridWidth;
case HomeScreenState::RotateClockwise: case HomeScreenState::RotateClockwise:
@ -89,7 +91,7 @@ int FolioWidget::gridWidth() const
void FolioWidget::setGridWidth(int gridWidth) void FolioWidget::setGridWidth(int gridWidth)
{ {
switch (HomeScreenState::self()->pageOrientation()) { switch (m_homeScreen->homeScreenState()->pageOrientation()) {
case HomeScreenState::RegularPosition: case HomeScreenState::RegularPosition:
setRealGridWidth(gridWidth); setRealGridWidth(gridWidth);
break; break;
@ -113,7 +115,7 @@ void FolioWidget::setGridWidth(int gridWidth)
int FolioWidget::gridHeight() const int FolioWidget::gridHeight() const
{ {
switch (HomeScreenState::self()->pageOrientation()) { switch (m_homeScreen->homeScreenState()->pageOrientation()) {
case HomeScreenState::RegularPosition: case HomeScreenState::RegularPosition:
return m_realGridHeight; return m_realGridHeight;
case HomeScreenState::RotateClockwise: case HomeScreenState::RotateClockwise:
@ -128,7 +130,7 @@ int FolioWidget::gridHeight() const
void FolioWidget::setGridHeight(int gridHeight) void FolioWidget::setGridHeight(int gridHeight)
{ {
switch (HomeScreenState::self()->pageOrientation()) { switch (m_homeScreen->homeScreenState()->pageOrientation()) {
case HomeScreenState::RegularPosition: case HomeScreenState::RegularPosition:
setRealGridHeight(gridHeight); setRealGridHeight(gridHeight);
break; break;
@ -188,7 +190,7 @@ void FolioWidget::setRealGridHeight(int gridHeight)
GridPosition FolioWidget::topLeftCorner(int row, int column) GridPosition FolioWidget::topLeftCorner(int row, int column)
{ {
switch (HomeScreenState::self()->pageOrientation()) { switch (m_homeScreen->homeScreenState()->pageOrientation()) {
case HomeScreenState::RegularPosition: case HomeScreenState::RegularPosition:
return {row, column}; return {row, column};
case HomeScreenState::RotateClockwise: case HomeScreenState::RotateClockwise:

View file

@ -3,11 +3,15 @@
#pragma once #pragma once
#include "homescreen.h"
#include <QObject> #include <QObject>
#include <Plasma/Applet> #include <Plasma/Applet>
#include <PlasmaQuick/AppletQuickItem> #include <PlasmaQuick/AppletQuickItem>
class HomeScreen;
struct GridPosition { struct GridPosition {
Q_GADGET Q_GADGET
public: public:
@ -28,10 +32,10 @@ class FolioWidget : public QObject
Q_PROPERTY(PlasmaQuick::AppletQuickItem *visualApplet READ visualApplet NOTIFY visualAppletChanged) Q_PROPERTY(PlasmaQuick::AppletQuickItem *visualApplet READ visualApplet NOTIFY visualAppletChanged)
public: public:
FolioWidget(QObject *parent = nullptr, int id = -1, int gridWidth = 0, int gridHeight = 0); FolioWidget(HomeScreen *parent = nullptr, int id = -1, int gridWidth = 0, int gridHeight = 0);
FolioWidget(QObject *parent, Plasma::Applet *applet, int gridWidth, int gridHeight); FolioWidget(HomeScreen *parent, Plasma::Applet *applet, int gridWidth, int gridHeight);
static FolioWidget *fromJson(QJsonObject &obj, QObject *parent); static FolioWidget *fromJson(QJsonObject &obj, HomeScreen *parent);
QJsonObject toJson() const; QJsonObject toJson() const;
int id() const; int id() const;
@ -80,10 +84,12 @@ private:
void init(); void init();
void setVisualApplet(PlasmaQuick::AppletQuickItem *quickApplet); void setVisualApplet(PlasmaQuick::AppletQuickItem *quickApplet);
int m_id = -1; HomeScreen *m_homeScreen{nullptr};
int m_realGridWidth = 1;
int m_realGridHeight = 1;
Plasma::Applet *m_applet = nullptr; int m_id{-1};
PlasmaQuick::AppletQuickItem *m_quickApplet = nullptr; int m_realGridWidth{1};
int m_realGridHeight{1};
Plasma::Applet *m_applet{nullptr};
PlasmaQuick::AppletQuickItem *m_quickApplet{nullptr};
}; };

View file

@ -4,20 +4,6 @@
#include "homescreen.h" #include "homescreen.h"
#include "applicationlistmodel.h"
#include "delegatetoucharea.h"
#include "favouritesmodel.h"
#include "folioapplication.h"
#include "folioapplicationfolder.h"
#include "foliodelegate.h"
#include "foliosettings.h"
#include "foliowidget.h"
#include "homescreenstate.h"
#include "pagelistmodel.h"
#include "pagemodel.h"
#include "widgetcontainer.h"
#include "widgetsmanager.h"
#include <KWindowSystem> #include <KWindowSystem>
#include <QDebug> #include <QDebug>
@ -27,50 +13,35 @@
HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args) HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
: Plasma::Containment{parent, data, args} : Plasma::Containment{parent, data, args}
, m_folioSettings{new FolioSettings{this}}
, m_homeScreenState{new HomeScreenState{this}}
, m_widgetsManager{new WidgetsManager{this}}
, m_applicationListModel{new ApplicationListModel{this}}
, m_favouritesModel{new FavouritesModel{this}}
, m_pageListModel{new PageListModel{this}}
{ {
setHasConfigurationInterface(true); // HomeScreenState init() has dependencies on other objects
m_homeScreenState->init();
const char *uri = "org.kde.private.mobile.homescreen.folio"; const char *uri = "org.kde.private.mobile.homescreen.folio";
qmlRegisterUncreatableType<HomeScreen>(uri, 1, 0, "HomeScreen", "");
// pre-initialize qmlRegisterUncreatableType<ApplicationListModel>(uri, 1, 0, "ApplicationListModel", "");
FolioSettings::self()->setApplet(this); qmlRegisterUncreatableType<FavouritesModel>(uri, 1, 0, "FavouritesModel", "");
HomeScreenState::self()->setContainment(this); qmlRegisterUncreatableType<PageListModel>(uri, 1, 0, "PageListModel", "");
WidgetsManager::self(); qmlRegisterUncreatableType<FolioSettings>(uri, 1, 0, "FolioSettings", "");
qmlRegisterUncreatableType<HomeScreenState>(uri, 1, 0, "HomeScreenState", "");
// models are loaded in main.qml qmlRegisterUncreatableType<FolioApplication>(uri, 1, 0, "FolioApplication", "");
ApplicationListModel::self(); qmlRegisterUncreatableType<FolioApplicationFolder>(uri, 1, 0, "FolioApplicationFolder", "");
FavouritesModel::self()->setContainment(this); qmlRegisterUncreatableType<FolioWidget>(uri, 1, 0, "FolioWidget", "");
PageListModel::self()->setContainment(this); qmlRegisterUncreatableType<FolioDelegate>(uri, 1, 0, "FolioDelegate", "");
qmlRegisterUncreatableType<PageModel>(uri, 1, 0, "PageModel", "");
qmlRegisterSingletonType<ApplicationListModel>(uri, 1, 0, "ApplicationListModel", [](QQmlEngine *, QJSEngine *) -> QObject * { qmlRegisterUncreatableType<FolioPageDelegate>(uri, 1, 0, "FolioPageDelegate", "");
return ApplicationListModel::self();
});
qmlRegisterSingletonType<FavouritesModel>(uri, 1, 0, "FavouritesModel", [](QQmlEngine *, QJSEngine *) -> QObject * {
return FavouritesModel::self();
});
qmlRegisterSingletonType<PageListModel>(uri, 1, 0, "PageListModel", [](QQmlEngine *, QJSEngine *) -> QObject * {
return PageListModel::self();
});
qmlRegisterSingletonType<FolioSettings>(uri, 1, 0, "FolioSettings", [](QQmlEngine *, QJSEngine *) -> QObject * {
return FolioSettings::self();
});
qmlRegisterSingletonType<HomeScreenState>(uri, 1, 0, "HomeScreenState", [](QQmlEngine *, QJSEngine *) -> QObject * {
return HomeScreenState::self();
});
qmlRegisterType<FolioApplication>(uri, 1, 0, "FolioApplication");
qmlRegisterType<FolioApplicationFolder>(uri, 1, 0, "FolioApplicationFolder");
qmlRegisterType<FolioWidget>(uri, 1, 0, "FolioWidget");
qmlRegisterType<FolioDelegate>(uri, 1, 0, "FolioDelegate");
qmlRegisterType<PageModel>(uri, 1, 0, "PageModel");
qmlRegisterType<FolioPageDelegate>(uri, 1, 0, "FolioPageDelegate");
qmlRegisterType<DelegateTouchArea>(uri, 1, 0, "DelegateTouchArea"); qmlRegisterType<DelegateTouchArea>(uri, 1, 0, "DelegateTouchArea");
qmlRegisterType<DelegateDragPosition>(uri, 1, 0, "DelegateDragPosition"); qmlRegisterUncreatableType<DelegateDragPosition>(uri, 1, 0, "DelegateDragPosition", "");
qmlRegisterType<WidgetContainer>(uri, 1, 0, "WidgetContainer"); qmlRegisterType<WidgetContainer>(uri, 1, 0, "WidgetContainer");
setHasConfigurationInterface(true);
connect(KWindowSystem::self(), &KWindowSystem::showingDesktopChanged, this, &HomeScreen::showingDesktopChanged); connect(KWindowSystem::self(), &KWindowSystem::showingDesktopChanged, this, &HomeScreen::showingDesktopChanged);
connect(this, &Plasma::Containment::appletAdded, this, &HomeScreen::onAppletAdded); connect(this, &Plasma::Containment::appletAdded, this, &HomeScreen::onAppletAdded);
@ -86,12 +57,43 @@ void HomeScreen::configChanged()
void HomeScreen::onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint) void HomeScreen::onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint)
{ {
WidgetsManager::self()->addWidget(applet); Q_UNUSED(geometryHint)
widgetsManager()->addWidget(applet);
} }
void HomeScreen::onAppletAboutToBeRemoved(Plasma::Applet *applet) void HomeScreen::onAppletAboutToBeRemoved(Plasma::Applet *applet)
{ {
WidgetsManager::self()->removeWidget(applet); widgetsManager()->removeWidget(applet);
}
FolioSettings *HomeScreen::folioSettings()
{
return m_folioSettings;
}
HomeScreenState *HomeScreen::homeScreenState()
{
return m_homeScreenState;
}
WidgetsManager *HomeScreen::widgetsManager()
{
return m_widgetsManager;
}
ApplicationListModel *HomeScreen::applicationListModel()
{
return m_applicationListModel;
}
FavouritesModel *HomeScreen::favouritesModel()
{
return m_favouritesModel;
}
PageListModel *HomeScreen::pageListModel()
{
return m_pageListModel;
} }
K_PLUGIN_CLASS(HomeScreen) K_PLUGIN_CLASS(HomeScreen)

View file

@ -7,9 +7,36 @@
#include <Plasma/Containment> #include <Plasma/Containment>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "applicationlistmodel.h"
#include "delegatetoucharea.h"
#include "favouritesmodel.h"
#include "folioapplication.h"
#include "folioapplicationfolder.h"
#include "foliodelegate.h"
#include "foliosettings.h"
#include "foliowidget.h"
#include "homescreenstate.h"
#include "pagelistmodel.h"
#include "pagemodel.h"
#include "widgetcontainer.h"
#include "widgetsmanager.h"
class FolioSettings;
class PageListModel;
class WidgetsManager;
class HomeScreenState;
class FavouritesModel;
class ApplicationListModel;
class HomeScreen : public Plasma::Containment class HomeScreen : public Plasma::Containment
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(FolioSettings *FolioSettings READ folioSettings CONSTANT)
Q_PROPERTY(HomeScreenState *HomeScreenState READ homeScreenState CONSTANT)
Q_PROPERTY(WidgetsManager *WidgetsManager READ widgetsManager CONSTANT)
Q_PROPERTY(ApplicationListModel *ApplicationListModel READ applicationListModel CONSTANT)
Q_PROPERTY(FavouritesModel *FavouritesModel READ favouritesModel CONSTANT)
Q_PROPERTY(PageListModel *PageListModel READ pageListModel CONSTANT)
public: public:
HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args); HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
@ -17,10 +44,25 @@ public:
void configChanged() override; void configChanged() override;
FolioSettings *folioSettings();
HomeScreenState *homeScreenState();
WidgetsManager *widgetsManager();
ApplicationListModel *applicationListModel();
FavouritesModel *favouritesModel();
PageListModel *pageListModel();
Q_SIGNALS: Q_SIGNALS:
void showingDesktopChanged(bool showingDesktop); void showingDesktopChanged(bool showingDesktop);
private Q_SLOTS: private Q_SLOTS:
void onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint); void onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint);
void onAppletAboutToBeRemoved(Plasma::Applet *applet); void onAppletAboutToBeRemoved(Plasma::Applet *applet);
private:
FolioSettings *m_folioSettings{nullptr};
HomeScreenState *m_homeScreenState{nullptr};
WidgetsManager *m_widgetsManager{nullptr};
ApplicationListModel *m_applicationListModel{nullptr};
FavouritesModel *m_favouritesModel{nullptr};
PageListModel *m_pageListModel{nullptr};
}; };

View file

@ -17,12 +17,6 @@ constexpr qreal DETERMINE_SWIPE_THRESHOLD = 10;
constexpr qreal VERTICAL_FAVOURITES_BAR_THRESHOLD = 400; constexpr qreal VERTICAL_FAVOURITES_BAR_THRESHOLD = 400;
HomeScreenState *HomeScreenState::self()
{
static HomeScreenState *inst = new HomeScreenState{nullptr};
return inst;
}
QPropertyAnimation *HomeScreenState::setupAnimation(QByteArray property, int duration, QEasingCurve::Type curve, qreal endValue) QPropertyAnimation *HomeScreenState::setupAnimation(QByteArray property, int duration, QEasingCurve::Type curve, qreal endValue)
{ {
auto anim = new QPropertyAnimation{this, property, this}; auto anim = new QPropertyAnimation{this, property, this};
@ -32,11 +26,16 @@ QPropertyAnimation *HomeScreenState::setupAnimation(QByteArray property, int dur
return anim; return anim;
} }
HomeScreenState::HomeScreenState(QObject *parent) HomeScreenState::HomeScreenState(HomeScreen *parent)
: QObject{parent} : QObject{parent}
, m_dragState{new DragState{this, this}} , m_homeScreen{parent}
, m_dragState{new DragState{this, parent}}
, m_appDrawerY{APP_DRAWER_OPEN_DIST} , m_appDrawerY{APP_DRAWER_OPEN_DIST}
, m_searchWidgetY{SEARCH_WIDGET_OPEN_DIST} , m_searchWidgetY{SEARCH_WIDGET_OPEN_DIST}
{
}
void HomeScreenState::init()
{ {
const int expoDuration = 800; const int expoDuration = 800;
const int cubicDuration = 400; const int cubicDuration = 400;
@ -136,11 +135,11 @@ HomeScreenState::HomeScreenState(QObject *parent)
Q_EMIT favouritesBarLocationChanged(); Q_EMIT favouritesBarLocationChanged();
}); });
connect(FolioSettings::self(), &FolioSettings::homeScreenRowsChanged, this, [this]() { connect(m_homeScreen->folioSettings(), &FolioSettings::homeScreenRowsChanged, this, [this]() {
Q_EMIT pageRowsChanged(); Q_EMIT pageRowsChanged();
Q_EMIT pageColumnsChanged(); Q_EMIT pageColumnsChanged();
}); });
connect(FolioSettings::self(), &FolioSettings::homeScreenColumnsChanged, this, [this]() { connect(m_homeScreen->folioSettings(), &FolioSettings::homeScreenColumnsChanged, this, [this]() {
Q_EMIT pageRowsChanged(); Q_EMIT pageRowsChanged();
Q_EMIT pageColumnsChanged(); Q_EMIT pageColumnsChanged();
}); });
@ -277,18 +276,18 @@ HomeScreenState::FavouritesBarLocation HomeScreenState::favouritesBarLocation()
int HomeScreenState::pageRows() const int HomeScreenState::pageRows() const
{ {
if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) { if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) {
return FolioSettings::self()->homeScreenRows(); return m_homeScreen->folioSettings()->homeScreenRows();
} else { } else {
return FolioSettings::self()->homeScreenColumns(); return m_homeScreen->folioSettings()->homeScreenColumns();
} }
} }
int HomeScreenState::pageColumns() const int HomeScreenState::pageColumns() const
{ {
if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) { if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) {
return FolioSettings::self()->homeScreenColumns(); return m_homeScreen->folioSettings()->homeScreenColumns();
} else { } else {
return FolioSettings::self()->homeScreenRows(); return m_homeScreen->folioSettings()->homeScreenRows();
} }
} }
@ -622,7 +621,7 @@ int HomeScreenState::currentFolderPage()
FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column) FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
{ {
PageModel *pageModel = PageListModel::self()->getPage(page); PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
if (!pageModel) { if (!pageModel) {
return nullptr; return nullptr;
} }
@ -637,7 +636,7 @@ FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
FolioDelegate *HomeScreenState::getFavouritesDelegateAt(int position) FolioDelegate *HomeScreenState::getFavouritesDelegateAt(int position)
{ {
return FavouritesModel::self()->getEntryAt(position); return m_homeScreen->favouritesModel()->getEntryAt(position);
} }
FolioDelegate *HomeScreenState::getFolderDelegateAt(int position) FolioDelegate *HomeScreenState::getFolderDelegateAt(int position)
@ -659,7 +658,7 @@ QPointF HomeScreenState::getPageDelegateScreenPosition(int page, int row, int co
QPointF HomeScreenState::getFavouritesDelegateScreenPosition(int position) QPointF HomeScreenState::getFavouritesDelegateScreenPosition(int position)
{ {
return FavouritesModel::self()->getDelegateScreenPosition(position); return m_homeScreen->favouritesModel()->getDelegateScreenPosition(position);
} }
QPointF HomeScreenState::getFolderDelegateScreenPosition(int position) QPointF HomeScreenState::getFolderDelegateScreenPosition(int position)
@ -679,16 +678,6 @@ QPointF HomeScreenState::getFolderDelegateScreenPosition(int position)
return {x, y}; return {x, y};
} }
Plasma::Containment *HomeScreenState::containment()
{
return m_containment;
}
void HomeScreenState::setContainment(Plasma::Containment *containment)
{
m_containment = containment;
}
void HomeScreenState::openAppDrawer() void HomeScreenState::openAppDrawer()
{ {
cancelAppDrawerAnimations(); cancelAppDrawerAnimations();
@ -719,7 +708,7 @@ void HomeScreenState::closeSearchWidget()
void HomeScreenState::snapPage() void HomeScreenState::snapPage()
{ {
const int numOfPages = PageListModel::self()->rowCount(); const int numOfPages = m_homeScreen->pageListModel()->rowCount();
const int leftPage = qBound(0.0, (m_pageViewX / m_pageWidth), numOfPages - 1.0); const int leftPage = qBound(0.0, (m_pageViewX / m_pageWidth), numOfPages - 1.0);
const qreal leftPagePos = -leftPage * m_pageWidth; const qreal leftPagePos = -leftPage * m_pageWidth;
@ -745,7 +734,7 @@ void HomeScreenState::goToPage(int page)
page = 0; page = 0;
} }
const int numOfPages = PageListModel::self()->rowCount(); const int numOfPages = m_homeScreen->pageListModel()->rowCount();
if (page >= numOfPages) { if (page >= numOfPages) {
page = std::max(0, numOfPages - 1); page = std::max(0, numOfPages - 1);
} }

View file

@ -10,8 +10,10 @@
#include <Plasma/Applet> #include <Plasma/Applet>
#include "dragstate.h" #include "dragstate.h"
#include "homescreen.h"
class DragState; class DragState;
class HomeScreen;
/** /**
* @short The homescreen state, containing information on positioning panels as well as any swipe events. * @short The homescreen state, containing information on positioning panels as well as any swipe events.
@ -110,9 +112,8 @@ public:
}; };
Q_ENUM(PageOrientation) Q_ENUM(PageOrientation)
static HomeScreenState *self(); HomeScreenState(HomeScreen *parent = nullptr);
void init(); // separate function due to dependencies on other classes
HomeScreenState(QObject *parent = nullptr);
// the current state of swipe interaction // the current state of swipe interaction
SwipeState swipeState() const; SwipeState swipeState() const;
@ -257,9 +258,6 @@ public:
Q_INVOKABLE QPointF getFavouritesDelegateScreenPosition(int position); Q_INVOKABLE QPointF getFavouritesDelegateScreenPosition(int position);
Q_INVOKABLE QPointF getFolderDelegateScreenPosition(int position); Q_INVOKABLE QPointF getFolderDelegateScreenPosition(int position);
Plasma::Containment *containment();
void setContainment(Plasma::Containment *containment);
Q_SIGNALS: Q_SIGNALS:
void swipeStateChanged(); void swipeStateChanged();
void viewStateChanged(); void viewStateChanged();
@ -354,6 +352,8 @@ private:
QPropertyAnimation *setupAnimation(QByteArray property, int duration, QEasingCurve::Type curve, qreal endValue); QPropertyAnimation *setupAnimation(QByteArray property, int duration, QEasingCurve::Type curve, qreal endValue);
HomeScreen *m_homeScreen{nullptr};
SwipeState m_swipeState{SwipeState::None}; SwipeState m_swipeState{SwipeState::None};
ViewState m_viewState{ViewState::PageView}; ViewState m_viewState{ViewState::PageView};
@ -414,6 +414,4 @@ private:
QPropertyAnimation *m_folderPageAnim{nullptr}; QPropertyAnimation *m_folderPageAnim{nullptr};
QPropertyAnimation *m_openSettingsAnim{nullptr}; QPropertyAnimation *m_openSettingsAnim{nullptr};
QPropertyAnimation *m_closeSettingsAnim{nullptr}; QPropertyAnimation *m_closeSettingsAnim{nullptr};
Plasma::Containment *m_containment{nullptr};
}; };

View file

@ -10,11 +10,13 @@ import org.kde.plasma.components 3.0 as PC3
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.private.mobile.homescreen.folio as Folio
import 'private' import 'private'
Item { Item {
id: root id: root
required property Folio.HomeScreen folio
property var homeScreen property var homeScreen
@ -53,6 +55,7 @@ Item {
AppDrawerGrid { AppDrawerGrid {
id: appDrawerGrid id: appDrawerGrid
folio: root.folio
homeScreen: root.homeScreen homeScreen: root.homeScreen
height: parent.height - drawerHeader.height height: parent.height - drawerHeader.height
anchors.left: parent.left anchors.left: parent.left

View file

@ -17,6 +17,8 @@ import "./delegate"
MobileShell.GridView { MobileShell.GridView {
id: root id: root
property Folio.HomeScreen folio
cacheBuffer: cellHeight * 20 cacheBuffer: cellHeight * 20
reuseItems: true reuseItems: true
layer.enabled: true layer.enabled: true
@ -24,14 +26,14 @@ MobileShell.GridView {
property var homeScreen property var homeScreen
property real headerHeight property real headerHeight
readonly property int reservedSpaceForLabel: Folio.HomeScreenState.pageDelegateLabelHeight readonly property int reservedSpaceForLabel: folio.HomeScreenState.pageDelegateLabelHeight
readonly property real effectiveContentWidth: width - leftMargin - rightMargin readonly property real effectiveContentWidth: width - leftMargin - rightMargin
readonly property real horizontalMargin: Math.round(width * 0.05) readonly property real horizontalMargin: Math.round(width * 0.05)
leftMargin: horizontalMargin leftMargin: horizontalMargin
rightMargin: horizontalMargin rightMargin: horizontalMargin
cellWidth: effectiveContentWidth / Math.min(Math.floor(effectiveContentWidth / (Folio.FolioSettings.delegateIconSize + Kirigami.Units.largeSpacing * 3.5)), 8) cellWidth: effectiveContentWidth / Math.min(Math.floor(effectiveContentWidth / (folio.FolioSettings.delegateIconSize + Kirigami.Units.largeSpacing * 3.5)), 8)
cellHeight: cellWidth + reservedSpaceForLabel cellHeight: cellWidth + reservedSpaceForLabel
boundsBehavior: Flickable.DragAndOvershootBounds boundsBehavior: Flickable.DragAndOvershootBounds
@ -41,14 +43,14 @@ MobileShell.GridView {
// HACK: the first swipe from the top of the app drawer is done from HomeScreenState, not the flickable // HACK: the first swipe from the top of the app drawer is done from HomeScreenState, not the flickable
// due to issues with Flickable getting its swipe stolen by SwipeArea // due to issues with Flickable getting its swipe stolen by SwipeArea
interactive: (dragging || !atYBeginning) // allow us to drag to the top interactive: (dragging || !atYBeginning) // allow us to drag to the top
&& Folio.HomeScreenState.swipeState !== Folio.HomeScreenState.SwipingAppDrawerGrid && folio.HomeScreenState.swipeState !== Folio.HomeScreenState.SwipingAppDrawerGrid
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.SwipingAppDrawerGrid) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.SwipingAppDrawerGrid) {
velocityCalculator.startMeasure(); velocityCalculator.startMeasure();
velocityCalculator.changePosition(root.contentY); velocityCalculator.changePosition(root.contentY);
} }
@ -76,10 +78,12 @@ MobileShell.GridView {
id: velocityCalculator id: velocityCalculator
} }
model: Folio.ApplicationListModel model: folio.ApplicationListModel
delegate: AppDelegate { delegate: AppDelegate {
id: delegate id: appDelegate
folio: root.folio
shadow: false shadow: false
application: model.delegate.application application: model.delegate.application
@ -87,18 +91,18 @@ MobileShell.GridView {
height: root.cellHeight height: root.cellHeight
onPressAndHold: { onPressAndHold: {
const mappedCoords = root.homeScreen.prepareStartDelegateDrag(model.delegate, delegate.delegateItem); const mappedCoords = root.homeScreen.prepareStartDelegateDrag(model.delegate, appDelegate.delegateItem);
Folio.HomeScreenState.closeAppDrawer(); folio.HomeScreenState.closeAppDrawer();
// we need to adjust because app drawer delegates have a different size than regular homescreen delegates // we need to adjust because app drawer delegates have a different size than regular homescreen delegates
const centerX = mappedCoords.x + root.cellWidth / 2; const centerX = mappedCoords.x + root.cellWidth / 2;
const centerY = mappedCoords.y + root.cellHeight / 2; const centerY = mappedCoords.y + root.cellHeight / 2;
Folio.HomeScreenState.startDelegateAppDrawerDrag( folio.HomeScreenState.startDelegateAppDrawerDrag(
centerX - Folio.HomeScreenState.pageCellWidth / 2, centerX - folio.HomeScreenState.pageCellWidth / 2,
centerY - Folio.HomeScreenState.pageCellHeight / 2, centerY - folio.HomeScreenState.pageCellHeight / 2,
delegate.pressPosition.x * (Folio.HomeScreenState.pageCellWidth / root.cellWidth), appDelegate.pressPosition.x * (folio.HomeScreenState.pageCellWidth / root.cellWidth),
delegate.pressPosition.y * (Folio.HomeScreenState.pageCellHeight / root.cellHeight), appDelegate.pressPosition.y * (folio.HomeScreenState.pageCellHeight / root.cellHeight),
model.delegate.application.storageId model.delegate.application.storageId
); );
} }

View file

@ -11,25 +11,26 @@ import "./delegate"
Item { Item {
id: root id: root
width: Folio.HomeScreenState.pageCellWidth property Folio.HomeScreen folio
height: Folio.HomeScreenState.pageCellHeight
property Folio.FolioDelegate delegate property Folio.FolioDelegate delegate
width: folio.HomeScreenState.pageCellWidth
height: folio.HomeScreenState.pageCellHeight
readonly property real dropAnimationRunning: dragXAnim.running || dragYAnim.running readonly property real dropAnimationRunning: dragXAnim.running || dragYAnim.running
// ignore widget dragging, that is not handled by this component // ignore widget dragging, that is not handled by this component
readonly property bool isWidgetDrag: Folio.HomeScreenState.dragState.dropDelegate && Folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget readonly property bool isWidgetDrag: folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
visible: false visible: false
x: Folio.HomeScreenState.delegateDragX x: folio.HomeScreenState.delegateDragX
y: Folio.HomeScreenState.delegateDragY y: folio.HomeScreenState.delegateDragY
function setXBinding() { function setXBinding() {
x = Qt.binding(() => Folio.HomeScreenState.delegateDragX); x = Qt.binding(() => folio.HomeScreenState.delegateDragX);
} }
function setYBinding() { function setYBinding() {
y = Qt.binding(() => Folio.HomeScreenState.delegateDragY); y = Qt.binding(() => folio.HomeScreenState.delegateDragY);
} }
// animate drop x // animate drop x
@ -67,13 +68,13 @@ Item {
Connections { Connections {
id: stateWatcher id: stateWatcher
target: Folio.HomeScreenState target: folio.HomeScreenState
property var delegateDroppedOn: null property var delegateDroppedOn: null
// reset and show drag item // reset and show drag item
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && !isWidgetDrag) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && !isWidgetDrag) {
root.scale = 1.0; root.scale = 1.0;
root.visible = true; root.visible = true;
} }
@ -85,15 +86,15 @@ Item {
return; return;
} }
let dragState = Folio.HomeScreenState.dragState; let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition; let dropPosition = dragState.candidateDropPosition;
switch (dropPosition.location) { switch (dropPosition.location) {
case Folio.DelegateDragPosition.Pages: case Folio.DelegateDragPosition.Pages:
stateWatcher.delegateDroppedOn = Folio.HomeScreenState.getPageDelegateAt(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn); stateWatcher.delegateDroppedOn = folio.HomeScreenState.getPageDelegateAt(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
break; break;
case Folio.DelegateDragPosition.Favourites: case Folio.DelegateDragPosition.Favourites:
stateWatcher.delegateDroppedOn = Folio.HomeScreenState.getFavouritesDelegateAt(dropPosition.favouritesPosition); stateWatcher.delegateDroppedOn = folio.HomeScreenState.getFavouritesDelegateAt(dropPosition.favouritesPosition);
break; break;
case Folio.DelegateDragPosition.Folder: case Folio.DelegateDragPosition.Folder:
stateWatcher.delegateDroppedOn = null; stateWatcher.delegateDroppedOn = null;
@ -103,7 +104,7 @@ Item {
} }
Connections { Connections {
target: Folio.HomeScreenState.dragState target: folio.HomeScreenState.dragState
// animate from when the delegate is dropped to its drop position // animate from when the delegate is dropped to its drop position
function onDelegateDroppedAndPlaced() { function onDelegateDroppedAndPlaced() {
@ -111,20 +112,20 @@ Item {
return; return;
} }
let dragState = Folio.HomeScreenState.dragState; let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition; let dropPosition = dragState.candidateDropPosition;
let pos = null; let pos = null;
switch (dropPosition.location) { switch (dropPosition.location) {
case Folio.DelegateDragPosition.Pages: case Folio.DelegateDragPosition.Pages:
pos = Folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn); pos = folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
break; break;
case Folio.DelegateDragPosition.Favourites: case Folio.DelegateDragPosition.Favourites:
pos = Folio.HomeScreenState.getFavouritesDelegateScreenPosition(dropPosition.favouritesPosition); pos = folio.HomeScreenState.getFavouritesDelegateScreenPosition(dropPosition.favouritesPosition);
break; break;
case Folio.DelegateDragPosition.Folder: case Folio.DelegateDragPosition.Folder:
pos = Folio.HomeScreenState.getFolderDelegateScreenPosition(dropPosition.folderPosition); pos = folio.HomeScreenState.getFolderDelegateScreenPosition(dropPosition.folderPosition);
break; break;
} }
@ -156,9 +157,10 @@ Item {
// icon // icon
DelegateIconLoader { DelegateIconLoader {
id: loader id: loader
folio: root.folio
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.minimumWidth: Folio.FolioSettings.delegateIconSize Layout.minimumWidth: folio.FolioSettings.delegateIconSize
Layout.minimumHeight: Folio.FolioSettings.delegateIconSize Layout.minimumHeight: folio.FolioSettings.delegateIconSize
Layout.preferredHeight: Layout.minimumHeight Layout.preferredHeight: Layout.minimumHeight
delegate: root.delegate delegate: root.delegate
@ -173,8 +175,8 @@ Item {
opacity: 0 opacity: 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Folio.HomeScreenState.pageDelegateLabelHeight Layout.preferredHeight: folio.HomeScreenState.pageDelegateLabelHeight
Layout.topMargin: Folio.HomeScreenState.pageDelegateLabelSpacing Layout.topMargin: folio.HomeScreenState.pageDelegateLabelSpacing
Layout.leftMargin: -parent.anchors.leftMargin + Kirigami.Units.smallSpacing Layout.leftMargin: -parent.anchors.leftMargin + Kirigami.Units.smallSpacing
Layout.rightMargin: -parent.anchors.rightMargin + Kirigami.Units.smallSpacing Layout.rightMargin: -parent.anchors.rightMargin + Kirigami.Units.smallSpacing
} }

View file

@ -16,6 +16,7 @@ import "./delegate"
MouseArea { MouseArea {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
@ -25,10 +26,10 @@ MouseArea {
signal delegateDragRequested(var item) signal delegateDragRequested(var item)
onPressAndHold: Folio.HomeScreenState.openSettingsView() onPressAndHold: folio.HomeScreenState.openSettingsView()
Repeater { Repeater {
model: Folio.FavouritesModel model: folio.FavouritesModel
delegate: Item { delegate: Item {
id: delegate id: delegate
@ -36,10 +37,10 @@ MouseArea {
property var delegateModel: model.delegate property var delegateModel: model.delegate
property int index: model.index property int index: model.index
property var dragState: Folio.HomeScreenState.dragState property var dragState: folio.HomeScreenState.dragState
property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Favourites && property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Favourites &&
dragState.candidateDropPosition.favouritesPosition === delegate.index dragState.candidateDropPosition.favouritesPosition === delegate.index
property bool isAppHoveredOver: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && property bool isAppHoveredOver: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
dragState.dropDelegate && dragState.dropDelegate &&
dragState.dropDelegate.type === Folio.FolioDelegate.Application && dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
isDropPositionThis isDropPositionThis
@ -49,8 +50,8 @@ MouseArea {
x: model.xPosition - leftMargin x: model.xPosition - leftMargin
y: model.xPosition - topMargin y: model.xPosition - topMargin
anchors.verticalCenter: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? parent.verticalCenter : undefined anchors.verticalCenter: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? parent.verticalCenter : undefined
anchors.horizontalCenter: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? undefined : parent.horizontalCenter anchors.horizontalCenter: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? undefined : parent.horizontalCenter
Behavior on x { Behavior on x {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad } NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
@ -59,10 +60,10 @@ MouseArea {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad } NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
} }
implicitWidth: Folio.HomeScreenState.pageCellWidth implicitWidth: folio.HomeScreenState.pageCellWidth
implicitHeight: Folio.HomeScreenState.pageCellHeight implicitHeight: folio.HomeScreenState.pageCellHeight
width: Folio.HomeScreenState.pageCellWidth width: folio.HomeScreenState.pageCellWidth
height: Folio.HomeScreenState.pageCellHeight height: folio.HomeScreenState.pageCellHeight
Loader { Loader {
anchors.fill: parent anchors.fill: parent
@ -90,12 +91,13 @@ MouseArea {
AppDelegate { AppDelegate {
id: appDelegate id: appDelegate
folio: root.folio
application: delegate.delegateModel.application application: delegate.delegateModel.application
name: Folio.FolioSettings.showFavouritesAppLabels ? delegate.delegateModel.application.name : "" name: folio.FolioSettings.showFavouritesAppLabels ? delegate.delegateModel.application.name : ""
shadow: true shadow: true
turnToFolder: delegate.isAppHoveredOver turnToFolder: delegate.isAppHoveredOver
turnToFolderAnimEnabled: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate turnToFolderAnimEnabled: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate
// do not show if the drop animation is running to this delegate // do not show if the drop animation is running to this delegate
visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis) visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis)
@ -118,7 +120,7 @@ MouseArea {
onPressAndHoldReleased: { onPressAndHoldReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
homeScreen.cancelDelegateDrag(); homeScreen.cancelDelegateDrag();
} }
} }
@ -132,10 +134,10 @@ MouseArea {
// close menu when drag starts // close menu when drag starts
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
contextMenu.close(); contextMenu.close();
} }
} }
@ -145,7 +147,7 @@ MouseArea {
Kirigami.Action { Kirigami.Action {
icon.name: "emblem-favorite" icon.name: "emblem-favorite"
text: i18n("Remove") text: i18n("Remove")
onTriggered: Folio.FavouritesModel.removeEntry(delegate.index) onTriggered: folio.FavouritesModel.removeEntry(delegate.index)
} }
] ]
} }
@ -157,9 +159,10 @@ MouseArea {
AppFolderDelegate { AppFolderDelegate {
id: appFolderDelegate id: appFolderDelegate
folio: root.folio
shadow: true shadow: true
folder: delegate.delegateModel.folder folder: delegate.delegateModel.folder
name: Folio.FolioSettings.showFavouritesAppLabels ? delegate.delegateModel.folder.name : "" name: folio.FolioSettings.showFavouritesAppLabels ? delegate.delegateModel.folder.name : ""
// do not show if the drop animation is running to this delegate, and the drop delegate is a folder // do not show if the drop animation is running to this delegate, and the drop delegate is a folder
visible: !(root.homeScreen.dropAnimationRunning && visible: !(root.homeScreen.dropAnimationRunning &&
@ -173,12 +176,12 @@ MouseArea {
onAfterClickAnimation: { onAfterClickAnimation: {
const pos = homeScreen.prepareFolderOpen(appFolderDelegate.contentItem); const pos = homeScreen.prepareFolderOpen(appFolderDelegate.contentItem);
Folio.HomeScreenState.openFolder(pos.x, pos.y, delegate.delegateModel.folder); folio.HomeScreenState.openFolder(pos.x, pos.y, delegate.delegateModel.folder);
} }
onPressAndHold: { onPressAndHold: {
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.delegateModel, appFolderDelegate.delegateItem); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.delegateModel, appFolderDelegate.delegateItem);
Folio.HomeScreenState.startDelegateFavouritesDrag( folio.HomeScreenState.startDelegateFavouritesDrag(
mappedCoords.x, mappedCoords.x,
mappedCoords.y, mappedCoords.y,
appFolderDelegate.pressPosition.x, appFolderDelegate.pressPosition.x,
@ -191,7 +194,7 @@ MouseArea {
onPressAndHoldReleased: { onPressAndHoldReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
root.homeScreen.cancelDelegateDrag(); root.homeScreen.cancelDelegateDrag();
} }
} }
@ -205,10 +208,10 @@ MouseArea {
// close menu when drag starts // close menu when drag starts
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
contextMenu.close(); contextMenu.close();
} }
} }
@ -225,7 +228,7 @@ MouseArea {
ConfirmDeleteFolderDialogLoader { ConfirmDeleteFolderDialogLoader {
id: deleteDialog id: deleteDialog
parent: root.homeScreen parent: root.homeScreen
onAccepted: Folio.FavouritesModel.removeEntry(delegate.index) onAccepted: folio.FavouritesModel.removeEntry(delegate.index)
} }
} }
} }

View file

@ -16,6 +16,7 @@ import "./delegate"
Folio.DelegateTouchArea { Folio.DelegateTouchArea {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
@ -23,25 +24,26 @@ Folio.DelegateTouchArea {
property real folderPositionX property real folderPositionX
property real folderPositionY property real folderPositionY
property Folio.FolioApplicationFolder folder: Folio.HomeScreenState.currentFolder property Folio.FolioApplicationFolder folder: folio.HomeScreenState.currentFolder
onClicked: close(); onClicked: close();
function close() { function close() {
Folio.HomeScreenState.closeFolder(); folio.HomeScreenState.closeFolder();
} }
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onFolderAboutToOpen(x, y) { function onFolderAboutToOpen(x, y) {
root.folderPositionX = x - Folio.HomeScreenState.viewLeftPadding; root.folderPositionX = x - folio.HomeScreenState.viewLeftPadding;
root.folderPositionY = y - Folio.HomeScreenState.viewRightPadding; root.folderPositionY = y - folio.HomeScreenState.viewRightPadding;
} }
} }
FolderViewTitle { FolderViewTitle {
id: titleText id: titleText
folio: root.folio
width: root.width width: root.width
// have to use y instead of anchors to avoid animations // have to use y instead of anchors to avoid animations
@ -59,18 +61,18 @@ Folio.DelegateTouchArea {
function updateContentWidth() { function updateContentWidth() {
let margin = folderBackground.margin; let margin = folderBackground.margin;
let columns = Math.floor((folderBackground.width - margin * 2) / Folio.HomeScreenState.pageCellWidth); let columns = Math.floor((folderBackground.width - margin * 2) / folio.HomeScreenState.pageCellWidth);
Folio.HomeScreenState.folderPageContentWidth = columns * Folio.HomeScreenState.pageCellWidth; folio.HomeScreenState.folderPageContentWidth = columns * folio.HomeScreenState.pageCellWidth;
} }
function updateContentHeight() { function updateContentHeight() {
let margin = folderBackground.margin; let margin = folderBackground.margin;
let rows = Math.floor((folderBackground.height - margin * 2) / Folio.HomeScreenState.pageCellHeight); let rows = Math.floor((folderBackground.height - margin * 2) / folio.HomeScreenState.pageCellHeight);
Folio.HomeScreenState.folderPageContentHeight = rows * Folio.HomeScreenState.pageCellHeight; folio.HomeScreenState.folderPageContentHeight = rows * folio.HomeScreenState.pageCellHeight;
} }
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onPageCellWidthChanged() { function onPageCellWidthChanged() {
root.updateContentWidth(); root.updateContentWidth();
@ -94,31 +96,31 @@ Folio.DelegateTouchArea {
width: { width: {
let perRow = 0; let perRow = 0;
if (root.width < root.height) { if (root.width < root.height) {
perRow = Math.floor((maxLength - margin * 2) / Folio.HomeScreenState.pageCellWidth); perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellWidth);
} else { } else {
// try to get the same number of rows as columns // try to get the same number of rows as columns
perRow = Math.floor((maxLength - margin * 2) / Folio.HomeScreenState.pageCellHeight); perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellHeight);
} }
return Math.min(root.width * 0.9, perRow * Folio.HomeScreenState.pageCellWidth + margin * 2); return Math.min(root.width * 0.9, perRow * folio.HomeScreenState.pageCellWidth + margin * 2);
} }
height: { height: {
let perRow = 0; let perRow = 0;
if (root.width < root.height) { if (root.width < root.height) {
// try to get the same number of rows as columns // try to get the same number of rows as columns
perRow = Math.floor((maxLength - margin * 2) / Folio.HomeScreenState.pageCellWidth); perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellWidth);
} else { } else {
perRow = Math.floor((maxLength - margin * 2) / Folio.HomeScreenState.pageCellHeight); perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellHeight);
} }
return Math.min(root.height * 0.9, perRow * Folio.HomeScreenState.pageCellHeight + margin * 2); return Math.min(root.height * 0.9, perRow * folio.HomeScreenState.pageCellHeight + margin * 2);
} }
onWidthChanged: { onWidthChanged: {
Folio.HomeScreenState.folderPageWidth = width; folio.HomeScreenState.folderPageWidth = width;
root.updateContentWidth(); root.updateContentWidth();
root.updateContentHeight(); root.updateContentHeight();
} }
onHeightChanged: { onHeightChanged: {
Folio.HomeScreenState.folderPageHeight = height; folio.HomeScreenState.folderPageHeight = height;
root.updateContentWidth(); root.updateContentWidth();
root.updateContentHeight(); root.updateContentHeight();
} }
@ -126,12 +128,12 @@ Folio.DelegateTouchArea {
x: { x: {
const folderPos = root.folderPositionX; const folderPos = root.folderPositionX;
const centerX = (root.width / 2) - (width / 2); const centerX = (root.width / 2) - (width / 2);
return Math.round(folderPos + (centerX - folderPos) * Folio.HomeScreenState.folderOpenProgress); return Math.round(folderPos + (centerX - folderPos) * folio.HomeScreenState.folderOpenProgress);
} }
y: { y: {
const folderPos = root.folderPositionY; const folderPos = root.folderPositionY;
const centerY = (root.height / 2) - (height / 2); const centerY = (root.height / 2) - (height / 2);
return Math.round(folderPos + (centerY - folderPos) * Folio.HomeScreenState.folderOpenProgress); return Math.round(folderPos + (centerY - folderPos) * folio.HomeScreenState.folderOpenProgress);
} }
transform: [ transform: [
@ -140,15 +142,15 @@ Folio.DelegateTouchArea {
origin.y: 0 origin.y: 0
xScale: { xScale: {
const iconSize = Folio.FolioSettings.delegateIconSize; const iconSize = folio.FolioSettings.delegateIconSize;
const fullWidth = folderBackground.width; const fullWidth = folderBackground.width;
const candidate = iconSize + (fullWidth - iconSize) * Folio.HomeScreenState.folderOpenProgress; const candidate = iconSize + (fullWidth - iconSize) * folio.HomeScreenState.folderOpenProgress;
return Math.max(0, Math.min(1, candidate / fullWidth)); return Math.max(0, Math.min(1, candidate / fullWidth));
} }
yScale: { yScale: {
const iconSize = Folio.FolioSettings.delegateIconSize; const iconSize = folio.FolioSettings.delegateIconSize;
const fullHeight = folderBackground.height; const fullHeight = folderBackground.height;
const candidate = iconSize + (fullHeight - iconSize) * Folio.HomeScreenState.folderOpenProgress; const candidate = iconSize + (fullHeight - iconSize) * folio.HomeScreenState.folderOpenProgress;
return Math.max(0, Math.min(1, candidate / fullHeight)); return Math.max(0, Math.min(1, candidate / fullHeight));
} }
} }
@ -163,7 +165,7 @@ Folio.DelegateTouchArea {
Item { Item {
id: contentContainer id: contentContainer
x: Folio.HomeScreenState.folderViewX x: folio.HomeScreenState.folderViewX
Repeater { Repeater {
model: root.folder ? root.folder.applications : [] model: root.folder ? root.folder.applications : []
@ -174,7 +176,7 @@ Folio.DelegateTouchArea {
property var delegateModel: model.delegate property var delegateModel: model.delegate
property int index: model.index property int index: model.index
property var dragState: Folio.HomeScreenState.dragState property var dragState: folio.HomeScreenState.dragState
property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Folder && property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Folder &&
dragState.candidateDropPosition.folderPosition === index dragState.candidateDropPosition.folderPosition === index
@ -188,10 +190,10 @@ Folio.DelegateTouchArea {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad } NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
} }
implicitWidth: Folio.HomeScreenState.pageCellWidth implicitWidth: folio.HomeScreenState.pageCellWidth
implicitHeight: Folio.HomeScreenState.pageCellHeight implicitHeight: folio.HomeScreenState.pageCellHeight
width: Folio.HomeScreenState.pageCellWidth width: folio.HomeScreenState.pageCellWidth
height: Folio.HomeScreenState.pageCellHeight height: folio.HomeScreenState.pageCellHeight
Loader { Loader {
id: delegateLoader id: delegateLoader
@ -217,6 +219,7 @@ Folio.DelegateTouchArea {
AppDelegate { AppDelegate {
id: appDelegate id: appDelegate
folio: root.folio
application: delegate.delegateModel.application application: delegate.delegateModel.application
// do not show if the drop animation is running to this delegate // do not show if the drop animation is running to this delegate
@ -227,7 +230,7 @@ Folio.DelegateTouchArea {
onPressAndHold: { onPressAndHold: {
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.delegateModel, appDelegate.delegateItem); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.delegateModel, appDelegate.delegateItem);
Folio.HomeScreenState.startDelegateFolderDrag( folio.HomeScreenState.startDelegateFolderDrag(
mappedCoords.x, mappedCoords.x,
mappedCoords.y, mappedCoords.y,
appDelegate.pressPosition.x, appDelegate.pressPosition.x,
@ -241,7 +244,7 @@ Folio.DelegateTouchArea {
onPressAndHoldReleased: { onPressAndHoldReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
homeScreen.cancelDelegateDrag(); homeScreen.cancelDelegateDrag();
} }
} }
@ -255,10 +258,10 @@ Folio.DelegateTouchArea {
// close menu when drag starts // close menu when drag starts
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
contextMenu.close(); contextMenu.close();
} }
} }
@ -289,8 +292,8 @@ Folio.DelegateTouchArea {
y: Math.round((root.height / 2) + (folderBackground.height / 2) + Kirigami.Units.largeSpacing) y: Math.round((root.height / 2) + (folderBackground.height / 2) + Kirigami.Units.largeSpacing)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
currentIndex: Folio.HomeScreenState.currentFolderPage currentIndex: folio.HomeScreenState.currentFolderPage
count: Folio.HomeScreenState.currentFolder ? Folio.HomeScreenState.currentFolder.applications.numberOfPages : 0 count: folio.HomeScreenState.currentFolder ? folio.HomeScreenState.currentFolder.applications.numberOfPages : 0
opacity: (root.opacity === 1) ? 1 : 0 opacity: (root.opacity === 1) ? 1 : 0
Behavior on opacity { Behavior on opacity {

View file

@ -13,12 +13,13 @@ import org.kde.private.mobile.homescreen.folio 1.0 as Folio
MobileShell.BaseItem { MobileShell.BaseItem {
id: root id: root
property Folio.HomeScreen folio
property Folio.FolioApplicationFolder folder property Folio.FolioApplicationFolder folder
property bool inFolderTitleEditMode: false property bool inFolderTitleEditMode: false
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onLeftCurrentFolder() { function onLeftCurrentFolder() {
root.inFolderTitleEditMode = false; root.inFolderTitleEditMode = false;

View file

@ -19,6 +19,8 @@ import "./settings"
Item { Item {
id: root id: root
property Folio.HomeScreen folio
property Folio.HomeScreenState homeScreenState: folio.HomeScreenState
property real topMargin: 0 property real topMargin: 0
property real bottomMargin: 0 property real bottomMargin: 0
@ -27,8 +29,6 @@ Item {
property bool interactive: true property bool interactive: true
property Folio.HomeScreenState homeScreenState: Folio.HomeScreenState
// non-widget drop animation // non-widget drop animation
readonly property bool dropAnimationRunning: delegateDragItem.dropAnimationRunning || widgetDragItem.dropAnimationRunning readonly property bool dropAnimationRunning: delegateDragItem.dropAnimationRunning || widgetDragItem.dropAnimationRunning
@ -38,10 +38,10 @@ Item {
// how much to scale out in the settings mode // how much to scale out in the settings mode
readonly property real settingsModeHomeScreenScale: 0.8 readonly property real settingsModeHomeScreenScale: 0.8
onTopMarginChanged: Folio.HomeScreenState.viewTopPadding = root.topMargin onTopMarginChanged: folio.HomeScreenState.viewTopPadding = root.topMargin
onBottomMarginChanged: Folio.HomeScreenState.viewBottomPadding = root.bottomMargin onBottomMarginChanged: folio.HomeScreenState.viewBottomPadding = root.bottomMargin
onLeftMarginChanged: Folio.HomeScreenState.viewLeftPadding = root.leftMargin onLeftMarginChanged: folio.HomeScreenState.viewLeftPadding = root.leftMargin
onRightMarginChanged: Folio.HomeScreenState.viewRightPadding = root.rightMargin onRightMarginChanged: folio.HomeScreenState.viewRightPadding = root.rightMargin
// called by any delegates when starting drag // called by any delegates when starting drag
// returns the mapped coordinates to be used in the home screen state // returns the mapped coordinates to be used in the home screen state
@ -73,10 +73,10 @@ Item {
text: "M\nM" text: "M\nM"
visible: false visible: false
onHeightChanged: Folio.HomeScreenState.pageDelegateLabelHeight = appLabelMetrics.height onHeightChanged: folio.HomeScreenState.pageDelegateLabelHeight = appLabelMetrics.height
Component.onCompleted: { Component.onCompleted: {
Folio.HomeScreenState.pageDelegateLabelWidth = Kirigami.Units.smallSpacing; folio.HomeScreenState.pageDelegateLabelWidth = Kirigami.Units.smallSpacing;
} }
} }
@ -85,8 +85,8 @@ Item {
id: screenDimensions id: screenDimensions
anchors.fill: parent anchors.fill: parent
onWidthChanged: Folio.HomeScreenState.viewWidth = width; onWidthChanged: folio.HomeScreenState.viewWidth = width;
onHeightChanged: Folio.HomeScreenState.viewHeight = height; onHeightChanged: folio.HomeScreenState.viewHeight = height;
} }
// a way of stopping focus // a way of stopping focus
@ -102,10 +102,10 @@ Item {
interactive: root.interactive && interactive: root.interactive &&
settings.homeScreenInteractive && settings.homeScreenInteractive &&
(appDrawer.flickable.contentY <= 10 || // disable the swipe area when we are swiping in the app drawer, and not in drag-and-drop (appDrawer.flickable.contentY <= 10 || // disable the swipe area when we are swiping in the app drawer, and not in drag-and-drop
Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate || folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate ||
Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate || folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate ||
Folio.HomeScreenState.swipeState === Folio.HomeScreenState.SwipingAppDrawerGrid || folio.HomeScreenState.swipeState === Folio.HomeScreenState.SwipingAppDrawerGrid ||
Folio.HomeScreenState.viewState !== Folio.HomeScreenState.AppDrawerView) folio.HomeScreenState.viewState !== Folio.HomeScreenState.AppDrawerView)
onSwipeStarted: { onSwipeStarted: {
homeScreenState.swipeStarted(); homeScreenState.swipeStarted();
@ -126,9 +126,10 @@ Item {
SettingsComponent { SettingsComponent {
id: settings id: settings
folio: root.folio
width: parent.width width: parent.width
height: parent.height height: parent.height
opacity: Folio.HomeScreenState.settingsOpenProgress opacity: folio.HomeScreenState.settingsOpenProgress
z: 1 z: 1
// move the settings out of the way if it is not visible // move the settings out of the way if it is not visible
@ -160,12 +161,13 @@ Item {
HomeScreenPages { HomeScreenPages {
id: homeScreenPages id: homeScreenPages
folio: root.folio
homeScreen: root homeScreen: root
anchors.topMargin: root.topMargin anchors.topMargin: root.topMargin
anchors.leftMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : root.leftMargin anchors.leftMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : root.leftMargin
anchors.rightMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : root.rightMargin anchors.rightMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : root.rightMargin
anchors.bottomMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : root.bottomMargin anchors.bottomMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : root.bottomMargin
// update the model with page dimensions // update the model with page dimensions
onWidthChanged: { onWidthChanged: {
@ -178,7 +180,7 @@ Item {
transform: [ transform: [
Scale { Scale {
// animation when settings opens // animation when settings opens
property real scaleFactor: 1 - Folio.HomeScreenState.settingsOpenProgress * (1 - settingsModeHomeScreenScale) property real scaleFactor: 1 - folio.HomeScreenState.settingsOpenProgress * (1 - settingsModeHomeScreenScale)
origin.x: root.leftMargin + (root.width - root.rightMargin - root.leftMargin) / 2 origin.x: root.leftMargin + (root.width - root.rightMargin - root.leftMargin) / 2
origin.y: root.height * settingsModeHomeScreenScale / 2 origin.y: root.height * settingsModeHomeScreenScale / 2
xScale: scaleFactor xScale: scaleFactor
@ -189,7 +191,7 @@ Item {
states: [ states: [
State { State {
name: "bottom" name: "bottom"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
AnchorChanges { AnchorChanges {
target: homeScreenPages target: homeScreenPages
anchors.top: parent.top anchors.top: parent.top
@ -199,7 +201,7 @@ Item {
} }
}, State { }, State {
name: "left" name: "left"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left
AnchorChanges { AnchorChanges {
target: homeScreenPages target: homeScreenPages
anchors.top: parent.top anchors.top: parent.top
@ -209,7 +211,7 @@ Item {
} }
}, State { }, State {
name: "right" name: "right"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right
AnchorChanges { AnchorChanges {
target: homeScreenPages target: homeScreenPages
anchors.top: parent.top anchors.top: parent.top
@ -226,29 +228,30 @@ Item {
color: Qt.rgba(255, 255, 255, 0.2) color: Qt.rgba(255, 255, 255, 0.2)
// don't show in settings mode // don't show in settings mode
opacity: 1 - Folio.HomeScreenState.settingsOpenProgress opacity: 1 - folio.HomeScreenState.settingsOpenProgress
visible: Folio.FolioSettings.showFavouritesBarBackground visible: folio.FolioSettings.showFavouritesBarBackground
anchors.top: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? favouritesBar.top : parent.top anchors.top: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? favouritesBar.top : parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? favouritesBar.left : parent.left anchors.left: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? favouritesBar.left : parent.left
anchors.right: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? favouritesBar.right : parent.right anchors.right: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? favouritesBar.right : parent.right
// because of the scale animation, we need to extend the panel out a bit // because of the scale animation, we need to extend the panel out a bit
anchors.topMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : -Kirigami.Units.gridUnit * 5 anchors.topMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : -Kirigami.Units.gridUnit * 5
anchors.bottomMargin: -Kirigami.Units.gridUnit * 5 anchors.bottomMargin: -Kirigami.Units.gridUnit * 5
anchors.leftMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : -Kirigami.Units.gridUnit * 5 anchors.leftMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : -Kirigami.Units.gridUnit * 5
anchors.rightMargin: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : -Kirigami.Units.gridUnit * 5 anchors.rightMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : -Kirigami.Units.gridUnit * 5
} }
FavouritesBar { FavouritesBar {
id: favouritesBar id: favouritesBar
folio: root.folio
homeScreen: root homeScreen: root
leftMargin: root.leftMargin leftMargin: root.leftMargin
topMargin: root.topMargin topMargin: root.topMargin
// don't show in settings mode // don't show in settings mode
opacity: 1 - Folio.HomeScreenState.settingsOpenProgress opacity: 1 - folio.HomeScreenState.settingsOpenProgress
visible: opacity > 0 visible: opacity > 0
// one is ignored as anchors are set // one is ignored as anchors are set
@ -263,7 +266,7 @@ Item {
states: [ states: [
State { State {
name: "bottom" name: "bottom"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
AnchorChanges { AnchorChanges {
target: favouritesBar target: favouritesBar
anchors.top: undefined anchors.top: undefined
@ -277,7 +280,7 @@ Item {
} }
}, State { }, State {
name: "left" name: "left"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left
AnchorChanges { AnchorChanges {
target: favouritesBar target: favouritesBar
anchors.top: parent.top anchors.top: parent.top
@ -291,7 +294,7 @@ Item {
} }
}, State { }, State {
name: "right" name: "right"
when: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right
AnchorChanges { AnchorChanges {
target: favouritesBar target: favouritesBar
anchors.top: parent.top anchors.top: parent.top
@ -309,10 +312,10 @@ Item {
Item { Item {
id: pageIndicatorWrapper id: pageIndicatorWrapper
property bool favouritesBarAtBottom: Folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom property bool favouritesBarAtBottom: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
// don't show in settings mode // don't show in settings mode
opacity: 1 - Folio.HomeScreenState.settingsOpenProgress opacity: 1 - folio.HomeScreenState.settingsOpenProgress
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
@ -333,11 +336,11 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
currentIndex: Folio.HomeScreenState.currentPage currentIndex: folio.HomeScreenState.currentPage
count: Folio.PageListModel.length count: folio.PageListModel.length
TapHandler { TapHandler {
onTapped: Folio.HomeScreenState.openAppDrawer() onTapped: folio.HomeScreenState.openAppDrawer()
} }
} }
@ -346,18 +349,18 @@ Item {
source: 'arrow-up' source: 'arrow-up'
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
visible: Folio.PageListModel.length <= 1 visible: folio.PageListModel.length <= 1
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.smallSpacing anchors.bottomMargin: Kirigami.Units.smallSpacing
TapHandler { TapHandler {
onTapped: Folio.HomeScreenState.openAppDrawer() onTapped: folio.HomeScreenState.openAppDrawer()
} }
} }
} }
@ -366,6 +369,7 @@ Item {
// folder view // folder view
FolderView { FolderView {
id: folderView id: folderView
folio: root.folio
anchors.fill: parent anchors.fill: parent
anchors.topMargin: root.topMargin anchors.topMargin: root.topMargin
anchors.leftMargin: root.leftMargin anchors.leftMargin: root.leftMargin
@ -380,16 +384,19 @@ Item {
// drag and drop component // drag and drop component
DelegateDragItem { DelegateDragItem {
id: delegateDragItem id: delegateDragItem
folio: root.folio
} }
// drag and drop for widgets // drag and drop for widgets
WidgetDragItem { WidgetDragItem {
id: widgetDragItem id: widgetDragItem
folio: root.folio
} }
// bottom app drawer // bottom app drawer
AppDrawer { AppDrawer {
id: appDrawer id: appDrawer
folio: root.folio
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -416,7 +423,7 @@ Item {
rightPadding: root.rightMargin rightPadding: root.rightMargin
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onAppDrawerClosed() { function onAppDrawerClosed() {
// reset app drawer position when closed // reset app drawer position when closed
@ -443,7 +450,7 @@ Item {
// focus the search bar if it opens // focus the search bar if it opens
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSearchWidgetOpenProgressChanged() { function onSearchWidgetOpenProgressChanged() {
if (homeScreenState.searchWidgetOpenProgress === 1.0) { if (homeScreenState.searchWidgetOpenProgress === 1.0) {

View file

@ -17,6 +17,7 @@ import "./private"
Item { Item {
id: root id: root
property Folio.HomeScreen folio
property int pageNum property int pageNum
@ -28,43 +29,44 @@ Item {
id: settingsViewBackground id: settingsViewBackground
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(255, 255, 255, 0.2) color: Qt.rgba(255, 255, 255, 0.2)
opacity: Folio.HomeScreenState.settingsOpenProgress opacity: folio.HomeScreenState.settingsOpenProgress
radius: Kirigami.Units.largeSpacing radius: Kirigami.Units.largeSpacing
} }
// square that shows when hovering over a spot to drop a delegate on // square that shows when hovering over a spot to drop a delegate on
PlaceholderDelegate { PlaceholderDelegate {
id: dragDropFeedback id: dragDropFeedback
width: Folio.HomeScreenState.pageCellWidth folio: root.folio
height: Folio.HomeScreenState.pageCellHeight width: folio.HomeScreenState.pageCellWidth
height: folio.HomeScreenState.pageCellHeight
property var dropPosition: Folio.HomeScreenState.dragState.candidateDropPosition property var dropPosition: folio.HomeScreenState.dragState.candidateDropPosition
property var dropDelegate: Folio.HomeScreenState.dragState.dropDelegate property var dropDelegate: folio.HomeScreenState.dragState.dropDelegate
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
// only show if it is an empty spot on this page // only show if it is an empty spot on this page
visible: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && visible: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
dropPosition.location === Folio.DelegateDragPosition.Pages && dropPosition.location === Folio.DelegateDragPosition.Pages &&
dropPosition.page === root.pageNum && dropPosition.page === root.pageNum &&
!dropDelegateIsWidget && !dropDelegateIsWidget &&
Folio.HomeScreenState.getPageDelegateAt(root.pageNum, dropPosition.pageRow, dropPosition.pageColumn) === null folio.HomeScreenState.getPageDelegateAt(root.pageNum, dropPosition.pageRow, dropPosition.pageColumn) === null
x: dropPosition.pageColumn * Folio.HomeScreenState.pageCellWidth x: dropPosition.pageColumn * folio.HomeScreenState.pageCellWidth
y: dropPosition.pageRow * Folio.HomeScreenState.pageCellHeight y: dropPosition.pageRow * folio.HomeScreenState.pageCellHeight
} }
// square that shows when a widget hovers over a spot to drop a delegate on // square that shows when a widget hovers over a spot to drop a delegate on
Rectangle { Rectangle {
id: widgetDragDropFeedback id: widgetDragDropFeedback
width: (dropDelegateIsWidget ? dropDelegate.widget.gridWidth : 0) * Folio.HomeScreenState.pageCellWidth width: (dropDelegateIsWidget ? dropDelegate.widget.gridWidth : 0) * folio.HomeScreenState.pageCellWidth
height: (dropDelegateIsWidget ? dropDelegate.widget.gridHeight : 0) * Folio.HomeScreenState.pageCellHeight height: (dropDelegateIsWidget ? dropDelegate.widget.gridHeight : 0) * folio.HomeScreenState.pageCellHeight
property var dropPosition: Folio.HomeScreenState.dragState.candidateDropPosition property var dropPosition: folio.HomeScreenState.dragState.candidateDropPosition
property var dropDelegate: Folio.HomeScreenState.dragState.dropDelegate property var dropDelegate: folio.HomeScreenState.dragState.dropDelegate
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
// only show if the widget can be placed here // only show if the widget can be placed here
visible: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && visible: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
dropPosition.location === Folio.DelegateDragPosition.Pages && dropPosition.location === Folio.DelegateDragPosition.Pages &&
dropPosition.page === root.pageNum && dropPosition.page === root.pageNum &&
dropDelegateIsWidget && dropDelegateIsWidget &&
@ -73,8 +75,8 @@ Item {
radius: Kirigami.Units.smallSpacing radius: Kirigami.Units.smallSpacing
color: Qt.rgba(255, 255, 255, 0.3) color: Qt.rgba(255, 255, 255, 0.3)
x: dropPosition.pageColumn * Folio.HomeScreenState.pageCellWidth x: dropPosition.pageColumn * folio.HomeScreenState.pageCellWidth
y: dropPosition.pageRow * Folio.HomeScreenState.pageCellHeight y: dropPosition.pageRow * folio.HomeScreenState.pageCellHeight
layer.enabled: true layer.enabled: true
layer.effect: DelegateShadow {} layer.effect: DelegateShadow {}
@ -91,14 +93,14 @@ Item {
property int row: pageDelegate.row property int row: pageDelegate.row
property int column: pageDelegate.column property int column: pageDelegate.column
property var dragState: Folio.HomeScreenState.dragState property var dragState: folio.HomeScreenState.dragState
property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Pages && property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Pages &&
dragState.candidateDropPosition.page === root.pageNum && dragState.candidateDropPosition.page === root.pageNum &&
dragState.candidateDropPosition.pageRow === delegate.pageDelegate.row && dragState.candidateDropPosition.pageRow === delegate.pageDelegate.row &&
dragState.candidateDropPosition.pageColumn === delegate.pageDelegate.column dragState.candidateDropPosition.pageColumn === delegate.pageDelegate.column
property bool isAppHoveredOver: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && property bool isAppHoveredOver: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
dragState.dropDelegate && dragState.dropDelegate &&
dragState.dropDelegate.type === Folio.FolioDelegate.Application && dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
isDropPositionThis isDropPositionThis
@ -108,20 +110,21 @@ Item {
width: loader.item ? loader.item.width : 0 width: loader.item ? loader.item.width : 0
height: loader.item ? loader.item.height : 0 height: loader.item ? loader.item.height : 0
x: column * Folio.HomeScreenState.pageCellWidth x: column * folio.HomeScreenState.pageCellWidth
y: row * Folio.HomeScreenState.pageCellHeight y: row * folio.HomeScreenState.pageCellHeight
visible: row >= 0 && row < Folio.HomeScreenState.pageRows && visible: row >= 0 && row < folio.HomeScreenState.pageRows &&
column >= 0 && column < Folio.HomeScreenState.pageColumns column >= 0 && column < folio.HomeScreenState.pageColumns
// called when we want to delete this delegate // called when we want to delete this delegate
function removeSelf() { function removeSelf() {
// remove from model // remove from model
root.pageModel.removeDelegate(delegate.row, delegate.column); root.pageModel.removeDelegate(delegate.row, delegate.column);
// delete empty pages at the end, and snap position to page that exists // TODO: this doesn't work, because the removeDelegate calls removes this entire object and the calls fail
Folio.PageListModel.deleteEmptyPagesAtEnd(); // // delete empty pages at the end, and snap position to page that exists
Folio.HomeScreenState.snapPage(); // folio.PageListModel.deleteEmptyPagesAtEnd();
// folio.HomeScreenState.snapPage();
} }
Loader { Loader {
@ -153,15 +156,16 @@ Item {
AppDelegate { AppDelegate {
id: appDelegate id: appDelegate
name: Folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.application.name : "" folio: root.folio
name: folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.application.name : ""
application: delegate.pageDelegate.application application: delegate.pageDelegate.application
turnToFolder: delegate.isAppHoveredOver turnToFolder: delegate.isAppHoveredOver
turnToFolderAnimEnabled: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate turnToFolderAnimEnabled: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate
implicitWidth: Folio.HomeScreenState.pageCellWidth implicitWidth: folio.HomeScreenState.pageCellWidth
implicitHeight: Folio.HomeScreenState.pageCellHeight implicitHeight: folio.HomeScreenState.pageCellHeight
width: Folio.HomeScreenState.pageCellWidth width: folio.HomeScreenState.pageCellWidth
height: Folio.HomeScreenState.pageCellHeight height: folio.HomeScreenState.pageCellHeight
// do not show if the drop animation is running to this delegate // do not show if the drop animation is running to this delegate
visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis) visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis)
@ -171,7 +175,7 @@ Item {
onPressAndHold: { onPressAndHold: {
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appDelegate.delegateItem); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appDelegate.delegateItem);
Folio.HomeScreenState.startDelegatePageDrag( folio.HomeScreenState.startDelegatePageDrag(
mappedCoords.x, mappedCoords.x,
mappedCoords.y, mappedCoords.y,
appDelegate.pressPosition.x, appDelegate.pressPosition.x,
@ -185,7 +189,7 @@ Item {
} }
onPressAndHoldReleased: { onPressAndHoldReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
homeScreen.cancelDelegateDrag(); homeScreen.cancelDelegateDrag();
} }
} }
@ -199,10 +203,10 @@ Item {
// close menu when drag starts // close menu when drag starts
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
contextMenu.close(); contextMenu.close();
} }
} }
@ -224,13 +228,14 @@ Item {
AppFolderDelegate { AppFolderDelegate {
id: appFolderDelegate id: appFolderDelegate
name: Folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.folder.name : "" folio: root.folio
name: folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.folder.name : ""
folder: delegate.pageDelegate.folder folder: delegate.pageDelegate.folder
implicitWidth: Folio.HomeScreenState.pageCellWidth implicitWidth: folio.HomeScreenState.pageCellWidth
implicitHeight: Folio.HomeScreenState.pageCellHeight implicitHeight: folio.HomeScreenState.pageCellHeight
width: Folio.HomeScreenState.pageCellWidth width: folio.HomeScreenState.pageCellWidth
height: Folio.HomeScreenState.pageCellHeight height: folio.HomeScreenState.pageCellHeight
// do not show if the drop animation is running to this delegate, and the drop delegate is a folder // do not show if the drop animation is running to this delegate, and the drop delegate is a folder
visible: !(root.homeScreen.dropAnimationRunning && visible: !(root.homeScreen.dropAnimationRunning &&
@ -244,12 +249,12 @@ Item {
onAfterClickAnimation: { onAfterClickAnimation: {
const pos = homeScreen.prepareFolderOpen(appFolderDelegate.contentItem); const pos = homeScreen.prepareFolderOpen(appFolderDelegate.contentItem);
Folio.HomeScreenState.openFolder(pos.x, pos.y, folder); folio.HomeScreenState.openFolder(pos.x, pos.y, folder);
} }
onPressAndHold: { onPressAndHold: {
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appFolderDelegate.delegateItem); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appFolderDelegate.delegateItem);
Folio.HomeScreenState.startDelegatePageDrag( folio.HomeScreenState.startDelegatePageDrag(
mappedCoords.x, mappedCoords.x,
mappedCoords.y, mappedCoords.y,
appFolderDelegate.pressPosition.x, appFolderDelegate.pressPosition.x,
@ -264,7 +269,7 @@ Item {
onPressAndHoldReleased: { onPressAndHoldReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
homeScreen.cancelDelegateDrag(); homeScreen.cancelDelegateDrag();
} }
} }
@ -278,10 +283,10 @@ Item {
// close menu when drag starts // close menu when drag starts
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
contextMenu.close(); contextMenu.close();
} }
} }
@ -309,6 +314,7 @@ Item {
WidgetDelegate { WidgetDelegate {
id: widgetDelegate id: widgetDelegate
folio: root.folio
// don't reparent applet if the drop animation is running to this delegate // don't reparent applet if the drop animation is running to this delegate
// background: there is only one "visual" instance of the widget, once this delegate loads // background: there is only one "visual" instance of the widget, once this delegate loads
@ -321,7 +327,7 @@ Item {
onStartEditMode: (pressPoint) => { onStartEditMode: (pressPoint) => {
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, widgetDelegate); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, widgetDelegate);
Folio.HomeScreenState.startDelegatePageDrag( folio.HomeScreenState.startDelegatePageDrag(
mappedCoords.x, mappedCoords.x,
mappedCoords.y, mappedCoords.y,
pressPoint.x - mappedCoords.x, pressPoint.x - mappedCoords.x,
@ -336,8 +342,8 @@ Item {
onPressReleased: { onPressReleased: {
// cancel the event if the delegate is not dragged // cancel the event if the delegate is not dragged
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
Folio.HomeScreenState.cancelDelegateDrag(); folio.HomeScreenState.cancelDelegateDrag();
widgetConfig.fullyOpen(); widgetConfig.fullyOpen();
} }
} }
@ -352,6 +358,7 @@ Item {
WidgetDelegateConfig { WidgetDelegateConfig {
id: widgetConfig id: widgetConfig
folio: root.folio
homeScreen: root.homeScreen homeScreen: root.homeScreen
pageModel: root.pageModel pageModel: root.pageModel

View file

@ -11,19 +11,21 @@ import org.kde.private.mobile.homescreen.folio 1.0 as Folio
MouseArea { MouseArea {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
readonly property real verticalMargin: Math.round((Folio.HomeScreenState.pageHeight - Folio.HomeScreenState.pageContentHeight) / 2) readonly property real verticalMargin: Math.round((folio.HomeScreenState.pageHeight - folio.HomeScreenState.pageContentHeight) / 2)
readonly property real horizontalMargin: Math.round((Folio.HomeScreenState.pageWidth - Folio.HomeScreenState.pageContentWidth) / 2) readonly property real horizontalMargin: Math.round((folio.HomeScreenState.pageWidth - folio.HomeScreenState.pageContentWidth) / 2)
onPressAndHold: Folio.HomeScreenState.openSettingsView() onPressAndHold: folio.HomeScreenState.openSettingsView()
Repeater { Repeater {
model: Folio.PageListModel model: folio.PageListModel
delegate: HomeScreenPage { delegate: HomeScreenPage {
id: homeScreenPage id: homeScreenPage
folio: root.folio
pageNum: model.index pageNum: model.index
pageModel: model.delegate pageModel: model.delegate
homeScreen: root.homeScreen homeScreen: root.homeScreen
@ -35,13 +37,13 @@ MouseArea {
anchors.bottomMargin: root.verticalMargin anchors.bottomMargin: root.verticalMargin
// animation so that full opacity is only when the page is in view // animation so that full opacity is only when the page is in view
readonly property real distanceToCenter: Math.abs(-Folio.HomeScreenState.pageViewX - root.width * pageNum) readonly property real distanceToCenter: Math.abs(-folio.HomeScreenState.pageViewX - root.width * pageNum)
readonly property real positionX: root.width * index + Folio.HomeScreenState.pageViewX readonly property real positionX: root.width * index + folio.HomeScreenState.pageViewX
readonly property real progressToCenter: 1 - Math.min(1, Math.max(0, distanceToCenter / root.width)) readonly property real progressToCenter: 1 - Math.min(1, Math.max(0, distanceToCenter / root.width))
visible: opacity > 0 visible: opacity > 0
opacity: { opacity: {
switch (Folio.FolioSettings.pageTransitionEffect) { switch (folio.FolioSettings.pageTransitionEffect) {
case Folio.FolioSettings.StackTransition: case Folio.FolioSettings.StackTransition:
return (positionX < 0) ? progressToCenter : return (positionX < 0) ? progressToCenter :
((progressToCenter < 0.3) ? 0 : ((1 / 0.7) * (progressToCenter - 0.3))) ((progressToCenter < 0.3) ? 0 : ((1 / 0.7) * (progressToCenter - 0.3)))
@ -52,7 +54,7 @@ MouseArea {
// x position of page // x position of page
transform: { transform: {
switch (Folio.FolioSettings.pageTransitionEffect) { switch (folio.FolioSettings.pageTransitionEffect) {
case Folio.FolioSettings.SlideTransition: case Folio.FolioSettings.SlideTransition:
return [translate]; return [translate];
case Folio.FolioSettings.CubeTransition: case Folio.FolioSettings.CubeTransition:
@ -75,8 +77,8 @@ MouseArea {
Scale { Scale {
id: stackScale id: stackScale
origin.x: Folio.HomeScreenState.pageWidth / 2 origin.x: folio.HomeScreenState.pageWidth / 2
origin.y: Folio.HomeScreenState.pageHeight / 2 origin.y: folio.HomeScreenState.pageHeight / 2
xScale: (homeScreenPage.positionX < 0) ? 1 : 0.5 + homeScreenPage.progressToCenter * 0.5 xScale: (homeScreenPage.positionX < 0) ? 1 : 0.5 + homeScreenPage.progressToCenter * 0.5
yScale: (homeScreenPage.positionX < 0) ? 1 : 0.5 + homeScreenPage.progressToCenter * 0.5 yScale: (homeScreenPage.positionX < 0) ? 1 : 0.5 + homeScreenPage.progressToCenter * 0.5
} }
@ -89,8 +91,8 @@ MouseArea {
Rotation { Rotation {
id: cubeTransitionRotation id: cubeTransitionRotation
origin.x: (positionX < 0) ? origin.x: (positionX < 0) ?
(Folio.HomeScreenState.pageWidth / 2) * homeScreenPage.progressToCenter : (folio.HomeScreenState.pageWidth / 2) * homeScreenPage.progressToCenter :
(Folio.HomeScreenState.pageWidth / 2) + (Folio.HomeScreenState.pageWidth / 2) * (1 - homeScreenPage.progressToCenter); (folio.HomeScreenState.pageWidth / 2) + (folio.HomeScreenState.pageWidth / 2) * (1 - homeScreenPage.progressToCenter);
origin.y: Folio.HomeScreenState.pageHeight / 2; origin.y: Folio.HomeScreenState.pageHeight / 2;
axis { x: 0; y: 1; z: 0 } axis { x: 0; y: 1; z: 0 }
angle: { angle: {
@ -101,8 +103,8 @@ MouseArea {
Rotation { Rotation {
id: rotationTransitionRotation id: rotationTransitionRotation
origin.x: (positionX < 0) ? origin.x: (positionX < 0) ?
(Folio.HomeScreenState.pageWidth / 2) * homeScreenPage.progressToCenter : (folio.HomeScreenState.pageWidth / 2) * homeScreenPage.progressToCenter :
(Folio.HomeScreenState.pageWidth / 2) + (Folio.HomeScreenState.pageWidth / 2) * (1 - homeScreenPage.progressToCenter); (folio.HomeScreenState.pageWidth / 2) + (folio.HomeScreenState.pageWidth / 2) * (1 - homeScreenPage.progressToCenter);
origin.y: 0 origin.y: 0
axis { x: -0.2; y: 0.3; z: 0.5 } axis { x: -0.2; y: 0.3; z: 0.5 }
angle: { angle: {

View file

@ -11,8 +11,10 @@ import "./delegate"
Item { Item {
id: root id: root
width: Folio.HomeScreenState.pageCellWidth property Folio.HomeScreen folio
height: Folio.HomeScreenState.pageCellHeight
width: folio.HomeScreenState.pageCellWidth
height: folio.HomeScreenState.pageCellHeight
// we need to simulate the position of the icon if it is placed at this spot // we need to simulate the position of the icon if it is placed at this spot
ColumnLayout { ColumnLayout {
@ -26,8 +28,8 @@ Item {
radius: Kirigami.Units.largeSpacing radius: Kirigami.Units.largeSpacing
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.minimumWidth: Folio.FolioSettings.delegateIconSize Layout.minimumWidth: folio.FolioSettings.delegateIconSize
Layout.minimumHeight: Folio.FolioSettings.delegateIconSize Layout.minimumHeight: folio.FolioSettings.delegateIconSize
Layout.preferredHeight: Layout.minimumHeight Layout.preferredHeight: Layout.minimumHeight
layer.enabled: true layer.enabled: true
layer.effect: DelegateShadow {} layer.effect: DelegateShadow {}
@ -38,8 +40,8 @@ Item {
id: label id: label
opacity: 0 opacity: 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Folio.HomeScreenState.pageDelegateLabelHeight Layout.preferredHeight: folio.HomeScreenState.pageDelegateLabelHeight
Layout.topMargin: Folio.HomeScreenState.pageDelegateLabelSpacing Layout.topMargin: folio.HomeScreenState.pageDelegateLabelSpacing
} }
} }
} }

View file

@ -18,17 +18,19 @@ import './private'
Item { Item {
id: root id: root
property Folio.HomeScreen folio
width: widgetLoader.item ? widgetLoader.item.width : 0 width: widgetLoader.item ? widgetLoader.item.width : 0
height: widgetLoader.item ? widgetLoader.item.height : 0 height: widgetLoader.item ? widgetLoader.item.height : 0
property Folio.FolioWidget widget property Folio.FolioWidget widget
readonly property bool isWidgetDelegate: Folio.HomeScreenState.dragState.dropDelegate && Folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget readonly property bool isWidgetDelegate: folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
visible: false visible: false
x: Math.round(Folio.HomeScreenState.delegateDragX) x: Math.round(folio.HomeScreenState.delegateDragX)
y: Math.round(Folio.HomeScreenState.delegateDragY) y: Math.round(folio.HomeScreenState.delegateDragY)
function startDrag(widget) { function startDrag(widget) {
root.widget = widget; root.widget = widget;
@ -36,10 +38,10 @@ Item {
} }
function setXBinding() { function setXBinding() {
x = Qt.binding(() => Math.round(Folio.HomeScreenState.delegateDragX)); x = Qt.binding(() => Math.round(folio.HomeScreenState.delegateDragX));
} }
function setYBinding() { function setYBinding() {
y = Qt.binding(() => Math.round(Folio.HomeScreenState.delegateDragY)); y = Qt.binding(() => Math.round(folio.HomeScreenState.delegateDragY));
} }
// animate drop x // animate drop x
@ -70,20 +72,20 @@ Item {
Connections { Connections {
id: stateWatcher id: stateWatcher
target: Folio.HomeScreenState target: folio.HomeScreenState
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
Folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate &&
Folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget) { folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget) {
root.startDrag(Folio.HomeScreenState.dragState.dropDelegate.widget); root.startDrag(folio.HomeScreenState.dragState.dropDelegate.widget);
} }
} }
} }
Connections { Connections {
target: Folio.HomeScreenState.dragState target: folio.HomeScreenState.dragState
// animate from when the delegate is dropped to its drop position // animate from when the delegate is dropped to its drop position
function onDelegateDroppedAndPlaced() { function onDelegateDroppedAndPlaced() {
@ -91,10 +93,10 @@ Item {
return; return;
} }
let dragState = Folio.HomeScreenState.dragState; let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition; let dropPosition = dragState.candidateDropPosition;
let pos = Folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn); let pos = folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
dragXAnim.to = pos.x; dragXAnim.to = pos.x;
dragYAnim.to = pos.y; dragYAnim.to = pos.y;
@ -114,6 +116,7 @@ Item {
active: root.widget active: root.widget
sourceComponent: WidgetDelegate { sourceComponent: WidgetDelegate {
folio: root.folio
widget: root.widget widget: root.widget
layer.enabled: true layer.enabled: true

View file

@ -16,7 +16,8 @@ import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
Folio.DelegateTouchArea { Folio.DelegateTouchArea {
id: delegate id: root
property Folio.HomeScreen folio
property string name property string name
property bool shadow: false property bool shadow: false
@ -37,7 +38,7 @@ Folio.DelegateTouchArea {
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1 duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
to: ShellSettings.Settings.animationsEnabled ? 0.8 : 1 to: ShellSettings.Settings.animationsEnabled ? 0.8 : 1
onFinished: { onFinished: {
if (!delegate.pressed) { if (!root.pressed) {
growAnim.restart(); growAnim.restart();
} }
} }
@ -49,9 +50,9 @@ Folio.DelegateTouchArea {
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1 duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
to: 1 to: 1
onFinished: { onFinished: {
if (delegate.clickRequested) { if (root.clickRequested) {
delegate.afterClickAnimation(); root.afterClickAnimation();
delegate.clickRequested = false; root.clickRequested = false;
} }
} }
} }
@ -68,7 +69,7 @@ Folio.DelegateTouchArea {
// trigger handled by press animation // trigger handled by press animation
onClicked: clickRequested = true; onClicked: clickRequested = true;
layer.enabled: delegate.shadow layer.enabled: root.shadow
layer.effect: DelegateShadow {} layer.effect: DelegateShadow {}
Item { Item {
@ -83,24 +84,24 @@ Folio.DelegateTouchArea {
// affects the delegate's x and y position, which messes up the starting drag and drop // affects the delegate's x and y position, which messes up the starting drag and drop
// position (for mapFromItem in HomeScreen.qml) // position (for mapFromItem in HomeScreen.qml)
transform: Scale { transform: Scale {
origin.x: delegate.width / 2; origin.x: root.width / 2;
origin.y: delegate.height / 2; origin.y: root.height / 2;
xScale: delegate.zoomScale xScale: root.zoomScale
yScale: delegate.zoomScale yScale: root.zoomScale
} }
MobileShell.BaseItem { MobileShell.BaseItem {
id: visualItem id: visualItem
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.minimumWidth: Folio.FolioSettings.delegateIconSize Layout.minimumWidth: folio.FolioSettings.delegateIconSize
Layout.minimumHeight: Folio.FolioSettings.delegateIconSize Layout.minimumHeight: folio.FolioSettings.delegateIconSize
Layout.preferredHeight: Layout.minimumHeight Layout.preferredHeight: Layout.minimumHeight
// darken effect when hovered // darken effect when hovered
// TODO: removed for now, since hovered property seems to overlap with the touch pressed event // TODO: removed for now, since hovered property seems to overlap with the touch pressed event
// layer { // layer {
// enabled: delegate.hovered // enabled: root.hovered
// effect: ColorOverlay { // effect: ColorOverlay {
// color: Qt.rgba(0, 0, 0, 0.3) // color: Qt.rgba(0, 0, 0, 0.3)
// } // }
@ -112,12 +113,12 @@ Folio.DelegateTouchArea {
opacity: text.length > 0 opacity: text.length > 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Folio.HomeScreenState.pageDelegateLabelHeight Layout.preferredHeight: folio.HomeScreenState.pageDelegateLabelHeight
Layout.topMargin: Folio.HomeScreenState.pageDelegateLabelSpacing Layout.topMargin: folio.HomeScreenState.pageDelegateLabelSpacing
Layout.leftMargin: -parent.anchors.leftMargin + Kirigami.Units.smallSpacing Layout.leftMargin: -parent.anchors.leftMargin + Kirigami.Units.smallSpacing
Layout.rightMargin: -parent.anchors.rightMargin + Kirigami.Units.smallSpacing Layout.rightMargin: -parent.anchors.rightMargin + Kirigami.Units.smallSpacing
text: delegate.name text: root.name
color: "white" color: "white"
} }
} }

View file

@ -14,6 +14,7 @@ import org.kde.plasma.private.mobileshell as MobileShell
AbstractDelegate { AbstractDelegate {
id: root id: root
shadow: true shadow: true
name: application.name name: application.name
@ -43,8 +44,8 @@ AbstractDelegate {
} }
contentItem: Item { contentItem: Item {
height: Folio.FolioSettings.delegateIconSize height: folio.FolioSettings.delegateIconSize
width: Folio.FolioSettings.delegateIconSize width: folio.FolioSettings.delegateIconSize
// background for folder creation animation // background for folder creation animation
Rectangle { Rectangle {
@ -76,6 +77,7 @@ AbstractDelegate {
// app icon // app icon
DelegateAppIcon { DelegateAppIcon {
id: icon id: icon
folio: root.folio
anchors.fill: parent anchors.fill: parent
source: root.application.icon source: root.application.icon

View file

@ -18,6 +18,7 @@ AbstractDelegate {
property bool appHoveredOver: false property bool appHoveredOver: false
contentItem: DelegateFolderIcon { contentItem: DelegateFolderIcon {
folio: root.folio
folder: root.folder folder: root.folder
expandBackground: root.appHoveredOver expandBackground: root.appHoveredOver
} }

View file

@ -12,7 +12,8 @@ import org.kde.private.mobile.homescreen.folio 1.0 as Folio
Kirigami.Icon { Kirigami.Icon {
id: root id: root
property Folio.HomeScreen folio
height: Folio.FolioSettings.delegateIconSize height: folio.FolioSettings.delegateIconSize
width: Folio.FolioSettings.delegateIconSize width: folio.FolioSettings.delegateIconSize
} }

View file

@ -12,13 +12,14 @@ import org.kde.private.mobile.homescreen.folio 1.0 as Folio
Item { Item {
id: root id: root
property Folio.HomeScreen folio
property Folio.FolioApplicationFolder folder property Folio.FolioApplicationFolder folder
property bool expandBackground: false property bool expandBackground: false
height: Folio.FolioSettings.delegateIconSize height: folio.FolioSettings.delegateIconSize
width: Folio.FolioSettings.delegateIconSize width: folio.FolioSettings.delegateIconSize
Rectangle { Rectangle {
id: rect id: rect

View file

@ -12,9 +12,10 @@ import org.kde.private.mobile.homescreen.folio 1.0 as Folio
Loader { Loader {
id: root id: root
property Folio.HomeScreen folio
height: Folio.FolioSettings.delegateIconSize height: folio.FolioSettings.delegateIconSize
width: Folio.FolioSettings.delegateIconSize width: folio.FolioSettings.delegateIconSize
property Folio.FolioDelegate delegate property Folio.FolioDelegate delegate
@ -39,6 +40,7 @@ Loader {
id: appIcon id: appIcon
DelegateAppIcon { DelegateAppIcon {
folio: root.folio
source: delegate.application.icon source: delegate.application.icon
} }
} }
@ -47,6 +49,7 @@ Loader {
id: folderIcon id: folderIcon
DelegateFolderIcon { DelegateFolderIcon {
folio: root.folio
folder: delegate.folder folder: delegate.folder
} }
} }

View file

@ -17,6 +17,7 @@ import '../private'
Folio.WidgetContainer { Folio.WidgetContainer {
id: root id: root
property Folio.HomeScreen folio
property Folio.FolioWidget widget property Folio.FolioWidget widget
@ -28,8 +29,8 @@ Folio.WidgetContainer {
readonly property real leftWidgetBackgroundPadding: widgetBackground.margins.left readonly property real leftWidgetBackgroundPadding: widgetBackground.margins.left
readonly property real rightWidgetBackgroundPadding: widgetBackground.margins.right readonly property real rightWidgetBackgroundPadding: widgetBackground.margins.right
implicitWidth: (widget ? widget.gridWidth : 0) * Folio.HomeScreenState.pageCellWidth implicitWidth: (widget ? widget.gridWidth : 0) * folio.HomeScreenState.pageCellWidth
implicitHeight: (widget ? widget.gridHeight : 0) * Folio.HomeScreenState.pageCellHeight implicitHeight: (widget ? widget.gridHeight : 0) * folio.HomeScreenState.pageCellHeight
width: implicitWidth width: implicitWidth
height: implicitHeight height: implicitHeight

View file

@ -17,6 +17,7 @@ import '../private'
Item { Item {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
@ -85,11 +86,11 @@ Item {
} }
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
// if we are starting drag-and-drop, close the menu immediately // if we are starting drag-and-drop, close the menu immediately
function onSwipeStateChanged() { function onSwipeStateChanged() {
if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) { if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
configOverlay.animClose(); configOverlay.animClose();
root.closed(); root.closed();
} }
@ -104,7 +105,7 @@ Item {
} }
} }
// this is the actual interactive popup for widget settings, only // this is the actual interactive popup for widget settings, only
// opened when the user releases their press (and doesn't drag) // opened when the user releases their press (and doesn't drag)
QQC2.Popup { QQC2.Popup {
id: configPopup id: configPopup
@ -136,7 +137,7 @@ Item {
} }
Connections { Connections {
target: Folio.HomeScreenState target: folio.HomeScreenState
// don't show config overlay if we have navigated to another page // don't show config overlay if we have navigated to another page
function onCurrentPageChanged() { function onCurrentPageChanged() {
@ -153,6 +154,7 @@ Item {
WidgetResizeHandleFrame { WidgetResizeHandleFrame {
id: resizeFrame id: resizeFrame
folio: root.folio
anchors.fill: parent anchors.fill: parent
widgetWidth: root.widgetWidth widgetWidth: root.widgetWidth

View file

@ -20,12 +20,12 @@ import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
ContainmentItem { ContainmentItem {
id: root id: root
property Folio.HomeScreen folio: root.plasmoid
Component.onCompleted: { Component.onCompleted: {
Folio.FolioSettings.load(); folio.FolioSettings.load();
Folio.ApplicationListModel.load(); folio.FavouritesModel.load();
Folio.FavouritesModel.load(); folio.PageListModel.load();
Folio.PageListModel.load();
// ensure the gestures work immediately on load // ensure the gestures work immediately on load
forceActiveFocus(); forceActiveFocus();
@ -33,7 +33,7 @@ ContainmentItem {
Loader { Loader {
id: wallpaperBlurLoader id: wallpaperBlurLoader
active: Folio.FolioSettings.showWallpaperBlur active: folio.FolioSettings.showWallpaperBlur
anchors.fill: parent anchors.fill: parent
sourceComponent: Item { sourceComponent: Item {
@ -60,12 +60,12 @@ ContainmentItem {
source: controlledWallpaperSource source: controlledWallpaperSource
anchors.fill: parent anchors.fill: parent
visible: opacity > 0 visible: opacity > 0
opacity: Math.min(1, opacity: Math.min(1,
Math.max( Math.max(
1 - homeScreen.contentOpacity, 1 - homeScreen.contentOpacity,
Folio.HomeScreenState.appDrawerOpenProgress * 2, // blur faster during swipe folio.HomeScreenState.appDrawerOpenProgress * 2, // blur faster during swipe
Folio.HomeScreenState.searchWidgetOpenProgress * 1.5, // blur faster during swipe folio.HomeScreenState.searchWidgetOpenProgress * 1.5, // blur faster during swipe
Folio.HomeScreenState.folderOpenProgress folio.HomeScreenState.folderOpenProgress
) )
) )
} }
@ -83,30 +83,30 @@ ContainmentItem {
if (isInWindow) { if (isInWindow) {
// only minimize windows and go to homescreen when not in docked mode // only minimize windows and go to homescreen when not in docked mode
if (!ShellSettings.Settings.convergenceModeEnabled) { if (!ShellSettings.Settings.convergenceModeEnabled) {
Folio.HomeScreenState.closeFolder(); folio.HomeScreenState.closeFolder();
Folio.HomeScreenState.closeSearchWidget(); folio.HomeScreenState.closeSearchWidget();
Folio.HomeScreenState.closeAppDrawer(); folio.HomeScreenState.closeAppDrawer();
Folio.HomeScreenState.goToPage(0); folio.HomeScreenState.goToPage(0);
WindowPlugin.WindowUtil.minimizeAll(); WindowPlugin.WindowUtil.minimizeAll();
} }
} else { // if we are on the homescreen } else { // if we are on the homescreen
switch (Folio.HomeScreenState.viewState) { switch (folio.HomeScreenState.viewState) {
case Folio.HomeScreenState.PageView: case Folio.HomeScreenState.PageView:
if (Folio.HomeScreenState.currentPage === 0) { if (folio.HomeScreenState.currentPage === 0) {
Folio.HomeScreenState.openAppDrawer(); folio.HomeScreenState.openAppDrawer();
} else { } else {
Folio.HomeScreenState.goToPage(0); folio.HomeScreenState.goToPage(0);
} }
break; break;
case Folio.HomeScreenState.AppDrawerView: case Folio.HomeScreenState.AppDrawerView:
Folio.HomeScreenState.closeAppDrawer(); folio.HomeScreenState.closeAppDrawer();
break; break;
case Folio.HomeScreenState.SearchWidgetView: case Folio.HomeScreenState.SearchWidgetView:
Folio.HomeScreenState.closeSearchWidget(); folio.HomeScreenState.closeSearchWidget();
break; break;
case Folio.HomeScreenState.FolderView: case Folio.HomeScreenState.FolderView:
Folio.HomeScreenState.closeFolder(); folio.HomeScreenState.closeFolder();
break; break;
} }
} }
@ -119,7 +119,7 @@ ContainmentItem {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.6) color: Qt.rgba(0, 0, 0, 0.6)
opacity: Folio.HomeScreenState.appDrawerOpenProgress opacity: folio.HomeScreenState.appDrawerOpenProgress
} }
Rectangle { Rectangle {
@ -127,7 +127,7 @@ ContainmentItem {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.3) color: Qt.rgba(0, 0, 0, 0.3)
opacity: Folio.HomeScreenState.searchWidgetOpenProgress opacity: folio.HomeScreenState.searchWidgetOpenProgress
} }
Rectangle { Rectangle {
@ -135,7 +135,7 @@ ContainmentItem {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.3) color: Qt.rgba(0, 0, 0, 0.3)
opacity: Folio.HomeScreenState.settingsOpenProgress opacity: folio.HomeScreenState.settingsOpenProgress
} }
MobileShell.HomeScreen { MobileShell.HomeScreen {
@ -154,6 +154,7 @@ ContainmentItem {
// homescreen component // homescreen component
HomeScreen { HomeScreen {
id: folioHomeScreen id: folioHomeScreen
folio: root.folio
anchors.fill: parent anchors.fill: parent
topMargin: homeScreen.topMargin topMargin: homeScreen.topMargin
@ -168,7 +169,7 @@ ContainmentItem {
// listen to app launch errors // listen to app launch errors
Connections { Connections {
target: Folio.ApplicationListModel target: folio.ApplicationListModel
function onLaunchError(msg) { function onLaunchError(msg) {
MobileShellState.ShellDBusClient.closeAppLaunchAnimation() MobileShellState.ShellDBusClient.closeAppLaunchAnimation()
} }

View file

@ -13,6 +13,7 @@ import '../delegate'
Item { Item {
id: root id: root
property Folio.HomeScreen folio
// given by parent: // given by parent:
@ -117,16 +118,16 @@ Item {
handleContainer.height = root.startDragHeight + bottomEdgeDelta + topEdgeDelta; handleContainer.height = root.startDragHeight + bottomEdgeDelta + topEdgeDelta;
// update the widget dimensions and position // update the widget dimensions and position
const columnsMovedRight = Math.round((handleContainer.x - root.startX) / Folio.HomeScreenState.pageCellWidth); const columnsMovedRight = Math.round((handleContainer.x - root.startX) / folio.HomeScreenState.pageCellWidth);
const rowsMovedDown = Math.round((handleContainer.y - root.startY) / Folio.HomeScreenState.pageCellHeight); const rowsMovedDown = Math.round((handleContainer.y - root.startY) / folio.HomeScreenState.pageCellHeight);
const realWidgetWidth = handleContainer.width + widgetLeftMargin + widgetRightMargin; const realWidgetWidth = handleContainer.width + widgetLeftMargin + widgetRightMargin;
const realWidgetHeight = handleContainer.height + widgetTopMargin + widgetBottomMargin; const realWidgetHeight = handleContainer.height + widgetTopMargin + widgetBottomMargin;
const widgetRowAfterDrag = startWidgetRow + rowsMovedDown; const widgetRowAfterDrag = startWidgetRow + rowsMovedDown;
const widgetColumnAfterDrag = startWidgetColumn + columnsMovedRight; const widgetColumnAfterDrag = startWidgetColumn + columnsMovedRight;
const widgetGridWidthAfterDrag = Math.round(realWidgetWidth / Folio.HomeScreenState.pageCellWidth); const widgetGridWidthAfterDrag = Math.round(realWidgetWidth / folio.HomeScreenState.pageCellWidth);
const widgetGridHeightAfterDrag = Math.round(realWidgetHeight / Folio.HomeScreenState.pageCellHeight); const widgetGridHeightAfterDrag = Math.round(realWidgetHeight / folio.HomeScreenState.pageCellHeight);
root.widgetChangeAfterDrag(widgetRowAfterDrag, widgetColumnAfterDrag, widgetGridWidthAfterDrag, widgetGridHeightAfterDrag); root.widgetChangeAfterDrag(widgetRowAfterDrag, widgetColumnAfterDrag, widgetGridWidthAfterDrag, widgetGridHeightAfterDrag);
} }

View file

@ -19,6 +19,7 @@ import '../private'
MouseArea { MouseArea {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
@ -116,13 +117,13 @@ MouseArea {
onPressAndHold: { onPressAndHold: {
root.requestClose(); root.requestClose();
Folio.HomeScreenState.closeSettingsView(); folio.HomeScreenState.closeSettingsView();
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(null, delegate); let mappedCoords = root.homeScreen.prepareStartDelegateDrag(null, delegate);
const widthOffset = Folio.HomeScreenState.pageCellWidth / 2; const widthOffset = folio.HomeScreenState.pageCellWidth / 2;
const heightOffset = Folio.HomeScreenState.pageCellHeight / 2; const heightOffset = folio.HomeScreenState.pageCellHeight / 2;
Folio.HomeScreenState.startDelegateWidgetListDrag( folio.HomeScreenState.startDelegateWidgetListDrag(
mappedCoords.x + mouseX - widthOffset, mappedCoords.x + mouseX - widthOffset,
mappedCoords.y + mouseY - heightOffset, mappedCoords.y + mouseY - heightOffset,
widthOffset, widthOffset,

View file

@ -16,6 +16,7 @@ import '../delegate'
Item { Item {
id: root id: root
property Folio.HomeScreen folio
property var homeScreen property var homeScreen
property real settingsModeHomeScreenScale property real settingsModeHomeScreenScale
@ -31,7 +32,7 @@ Item {
anchors.bottom: settingsBar.top anchors.bottom: settingsBar.top
onClicked: { onClicked: {
Folio.HomeScreenState.closeSettingsView(); folio.HomeScreenState.closeSettingsView();
} }
} }
@ -66,7 +67,7 @@ Item {
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: 'edit-image' source: 'edit-image'
} }
QQC2.Label { QQC2.Label {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
text: i18n('Wallpapers') text: i18n('Wallpapers')
@ -76,7 +77,7 @@ Item {
onClicked: { onClicked: {
wallpaperSelectorLoader.active = true; wallpaperSelectorLoader.active = true;
Folio.HomeScreenState.closeSettingsView(); folio.HomeScreenState.closeSettingsView();
} }
} }
@ -94,7 +95,7 @@ Item {
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: 'settings-configure' source: 'settings-configure'
} }
QQC2.Label { QQC2.Label {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
text: i18n('Settings') text: i18n('Settings')
@ -123,7 +124,7 @@ Item {
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: 'widget-alternatives' source: 'widget-alternatives'
} }
QQC2.Label { QQC2.Label {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
text: i18n('Widgets') text: i18n('Widgets')
@ -140,6 +141,7 @@ Item {
AppletListViewer { AppletListViewer {
id: appletListViewer id: appletListViewer
folio: root.folio
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -162,6 +164,7 @@ Item {
SettingsWindow { SettingsWindow {
id: settingsWindow id: settingsWindow
folio: root.folio
visible: false visible: false
onRequestConfigureMenu: { onRequestConfigureMenu: {

View file

@ -16,6 +16,8 @@ import '../delegate'
Window { Window {
id: root id: root
property Folio.HomeScreen folio
flags: Qt.FramelessWindowHint flags: Qt.FramelessWindowHint
color: 'transparent' color: 'transparent'
@ -92,18 +94,19 @@ Window {
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
Item { Item {
Layout.preferredHeight: Folio.HomeScreenState.pageCellHeight Layout.preferredHeight: folio.HomeScreenState.pageCellHeight
Layout.fillWidth: true Layout.fillWidth: true
AbstractDelegate { AbstractDelegate {
folio: root.folio
anchors.centerIn: parent anchors.centerIn: parent
implicitHeight: Folio.HomeScreenState.pageCellHeight implicitHeight: folio.HomeScreenState.pageCellHeight
implicitWidth: Folio.HomeScreenState.pageCellWidth implicitWidth: folio.HomeScreenState.pageCellWidth
name: i18n('Application') name: i18n('Application')
contentItem: DelegateAppIcon { contentItem: DelegateAppIcon {
height: Folio.FolioSettings.delegateIconSize height: folio.FolioSettings.delegateIconSize
width: Folio.FolioSettings.delegateIconSize width: folio.FolioSettings.delegateIconSize
source: 'applications-system' source: 'applications-system'
} }
} }
@ -112,8 +115,8 @@ Window {
FormCard.FormCard { FormCard.FormCard {
id: iconsCard id: iconsCard
readonly property bool isVerticalOrientation: Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RegularPosition || readonly property bool isVerticalOrientation: folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RegularPosition ||
Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RotateUpsideDown folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RotateUpsideDown
readonly property string numOfRowsText: i18n("Number of rows") readonly property string numOfRowsText: i18n("Number of rows")
readonly property string numOfColumnsText: i18n("Number of columns") readonly property string numOfColumnsText: i18n("Number of columns")
@ -123,10 +126,10 @@ Window {
label: i18n("Size of icons on homescreen") label: i18n("Size of icons on homescreen")
from: 16 from: 16
to: 128 to: 128
value: Folio.FolioSettings.delegateIconSize value: folio.FolioSettings.delegateIconSize
onValueChanged: { onValueChanged: {
if (value !== Folio.FolioSettings.delegateIconSize) { if (value !== folio.FolioSettings.delegateIconSize) {
Folio.FolioSettings.delegateIconSize = value; folio.FolioSettings.delegateIconSize = value;
} }
} }
} }
@ -136,10 +139,10 @@ Window {
label: iconsCard.isVerticalOrientation ? iconsCard.numOfRowsText : iconsCard.numOfColumnsText label: iconsCard.isVerticalOrientation ? iconsCard.numOfRowsText : iconsCard.numOfColumnsText
from: 3 from: 3
to: 10 to: 10
value: Folio.FolioSettings.homeScreenRows value: folio.FolioSettings.homeScreenRows
onValueChanged: { onValueChanged: {
if (value !== Folio.FolioSettings.homeScreenRows) { if (value !== folio.FolioSettings.homeScreenRows) {
Folio.FolioSettings.homeScreenRows = value; folio.FolioSettings.homeScreenRows = value;
} }
} }
} }
@ -149,10 +152,10 @@ Window {
label: iconsCard.isVerticalOrientation ? iconsCard.numOfColumnsText : iconsCard.numOfRowsText label: iconsCard.isVerticalOrientation ? iconsCard.numOfColumnsText : iconsCard.numOfRowsText
from: 3 from: 3
to: 10 to: 10
value: Folio.FolioSettings.homeScreenColumns value: folio.FolioSettings.homeScreenColumns
onValueChanged: { onValueChanged: {
if (value !== Folio.FolioSettings.homeScreenColumns) { if (value !== folio.FolioSettings.homeScreenColumns) {
Folio.FolioSettings.homeScreenColumns = value; folio.FolioSettings.homeScreenColumns = value;
} }
} }
} }
@ -170,10 +173,10 @@ Window {
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
id: showLabelsOnHomeScreen id: showLabelsOnHomeScreen
text: i18n("Show labels on homescreen") text: i18n("Show labels on homescreen")
checked: Folio.FolioSettings.showPagesAppLabels checked: folio.FolioSettings.showPagesAppLabels
onCheckedChanged: { onCheckedChanged: {
if (checked != Folio.FolioSettings.showPagesAppLabels) { if (checked != folio.FolioSettings.showPagesAppLabels) {
Folio.FolioSettings.showPagesAppLabels = checked; folio.FolioSettings.showPagesAppLabels = checked;
} }
} }
} }
@ -183,10 +186,10 @@ Window {
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
id: showLabelsInFavourites id: showLabelsInFavourites
text: i18n("Show labels in favorites bar") text: i18n("Show labels in favorites bar")
checked: Folio.FolioSettings.showFavouritesAppLabels checked: folio.FolioSettings.showFavouritesAppLabels
onCheckedChanged: { onCheckedChanged: {
if (checked != Folio.FolioSettings.showFavouritesAppLabels) { if (checked != folio.FolioSettings.showFavouritesAppLabels) {
Folio.FolioSettings.showFavouritesAppLabels = checked; folio.FolioSettings.showFavouritesAppLabels = checked;
} }
} }
} }
@ -197,7 +200,7 @@ Window {
id: pageTransitionCombobox id: pageTransitionCombobox
text: i18n("Page transition effect") text: i18n("Page transition effect")
currentIndex: indexOfValue(Folio.FolioSettings.pageTransitionEffect) currentIndex: indexOfValue(folio.FolioSettings.pageTransitionEffect)
model: ListModel { model: ListModel {
// we can't use i18n with ListElement // we can't use i18n with ListElement
Component.onCompleted: { Component.onCompleted: {
@ -208,14 +211,14 @@ Window {
append({"name": i18n("Rotation"), "value": Folio.FolioSettings.RotationTransition}); append({"name": i18n("Rotation"), "value": Folio.FolioSettings.RotationTransition});
// indexOfValue doesn't bind to model changes unfortunately, set currentIndex manually here // indexOfValue doesn't bind to model changes unfortunately, set currentIndex manually here
pageTransitionCombobox.currentIndex = pageTransitionCombobox.indexOfValue(Folio.FolioSettings.pageTransitionEffect) pageTransitionCombobox.currentIndex = pageTransitionCombobox.indexOfValue(folio.FolioSettings.pageTransitionEffect)
} }
} }
textRole: "name" textRole: "name"
valueRole: "value" valueRole: "value"
onCurrentValueChanged: Folio.FolioSettings.pageTransitionEffect = currentValue onCurrentValueChanged: folio.FolioSettings.pageTransitionEffect = currentValue
} }
} }
@ -227,10 +230,10 @@ Window {
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
text: i18n('Show background') text: i18n('Show background')
icon.name: 'draw-rectangle' icon.name: 'draw-rectangle'
checked: Folio.FolioSettings.showFavouritesBarBackground checked: folio.FolioSettings.showFavouritesBarBackground
onCheckedChanged: { onCheckedChanged: {
if (checked !== Folio.FolioSettings.showFavouritesBarBackground) { if (checked !== folio.FolioSettings.showFavouritesBarBackground) {
Folio.FolioSettings.showFavouritesBarBackground = checked; folio.FolioSettings.showFavouritesBarBackground = checked;
} }
} }
} }
@ -244,10 +247,10 @@ Window {
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
id: showWallpaperBlur id: showWallpaperBlur
text: i18nc("@option:check", "Show wallpaper blur effect") text: i18nc("@option:check", "Show wallpaper blur effect")
checked: Folio.FolioSettings.showWallpaperBlur checked: folio.FolioSettings.showWallpaperBlur
onCheckedChanged: { onCheckedChanged: {
if (checked != Folio.FolioSettings.showWallpaperBlur) { if (checked != folio.FolioSettings.showWallpaperBlur) {
Folio.FolioSettings.showWallpaperBlur = checked; folio.FolioSettings.showWallpaperBlur = checked;
} }
} }
} }
@ -295,7 +298,7 @@ Window {
onAccepted: { onAccepted: {
console.log('saving layout to ' + selectedFile); console.log('saving layout to ' + selectedFile);
if (selectedFile) { if (selectedFile) {
let status = Folio.FolioSettings.saveLayoutToFile(selectedFile); let status = folio.FolioSettings.saveLayoutToFile(selectedFile);
if (status) { if (status) {
exportedSuccessfullyPrompt.open(); exportedSuccessfullyPrompt.open();
} else { } else {
@ -335,7 +338,7 @@ Window {
title: i18n("Confirm Import") title: i18n("Confirm Import")
subtitle: i18n("This will overwrite your existing homescreen layout!") subtitle: i18n("This will overwrite your existing homescreen layout!")
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: Folio.FolioSettings.loadLayoutFromFile(importFileDialog.selectedFile); onAccepted: folio.FolioSettings.loadLayoutFromFile(importFileDialog.selectedFile);
} }
} }
} }

View file

@ -7,14 +7,9 @@
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
PageListModel *PageListModel::self() PageListModel::PageListModel(HomeScreen *parent)
{
static PageListModel *model = new PageListModel;
return model;
}
PageListModel::PageListModel(QObject *parent)
: QAbstractListModel{parent} : QAbstractListModel{parent}
, m_homeScreen{parent}
{ {
} }
@ -77,7 +72,7 @@ Q_INVOKABLE void PageListModel::addPageAtEnd()
{ {
beginInsertRows(QModelIndex(), m_pages.size(), m_pages.size()); beginInsertRows(QModelIndex(), m_pages.size(), m_pages.size());
PageModel *page = new PageModel{{}, this}; PageModel *page = new PageModel{{}, this, m_homeScreen};
connect(page, &PageModel::saveRequested, this, &PageListModel::save); connect(page, &PageModel::saveRequested, this, &PageListModel::save);
m_pages.append(page); m_pages.append(page);
@ -96,9 +91,11 @@ bool PageListModel::isLastPageEmpty()
void PageListModel::deleteEmptyPagesAtEnd() void PageListModel::deleteEmptyPagesAtEnd()
{ {
auto pageListModel = m_homeScreen->pageListModel();
// delete empty pages at the end if they exist // delete empty pages at the end if they exist
while (PageListModel::self()->isLastPageEmpty() && PageListModel::self()->rowCount() > 1) { while (pageListModel->isLastPageEmpty() && pageListModel->rowCount() > 1) {
PageListModel::self()->removePage(PageListModel::self()->rowCount() - 1); pageListModel->removePage(pageListModel->rowCount() - 1);
} }
} }
@ -113,24 +110,24 @@ QJsonArray PageListModel::exportToJson()
void PageListModel::save() void PageListModel::save()
{ {
if (!m_containment) { if (!m_homeScreen) {
return; return;
} }
QJsonArray arr = exportToJson(); QJsonArray arr = exportToJson();
QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact); QByteArray data = QJsonDocument(arr).toJson(QJsonDocument::Compact);
m_containment->config().writeEntry("Pages", QString::fromStdString(data.toStdString())); m_homeScreen->config().writeEntry("Pages", QString::fromStdString(data.toStdString()));
Q_EMIT m_containment->configNeedsSaving(); Q_EMIT m_homeScreen->configNeedsSaving();
} }
void PageListModel::load() void PageListModel::load()
{ {
if (!m_containment) { if (!m_homeScreen) {
return; return;
} }
QJsonDocument doc = QJsonDocument::fromJson(m_containment->config().readEntry("Pages", "{}").toUtf8()); QJsonDocument doc = QJsonDocument::fromJson(m_homeScreen->config().readEntry("Pages", "{}").toUtf8());
loadFromJson(doc.array()); loadFromJson(doc.array());
} }
@ -143,7 +140,7 @@ void PageListModel::loadFromJson(QJsonArray arr)
for (QJsonValueRef r : arr) { for (QJsonValueRef r : arr) {
QJsonArray obj = r.toArray(); QJsonArray obj = r.toArray();
PageModel *page = PageModel::fromJson(obj, this); PageModel *page = PageModel::fromJson(obj, this, m_homeScreen);
if (page) { if (page) {
connect(page, &PageModel::saveRequested, this, &PageListModel::save); connect(page, &PageModel::saveRequested, this, &PageListModel::save);
m_pages.append(page); m_pages.append(page);
@ -159,8 +156,3 @@ void PageListModel::loadFromJson(QJsonArray arr)
addPageAtEnd(); addPageAtEnd();
} }
} }
void PageListModel::setContainment(Plasma::Containment *containment)
{
m_containment = containment;
}

View file

@ -3,6 +3,7 @@
#pragma once #pragma once
#include "homescreen.h"
#include "pagemodel.h" #include "pagemodel.h"
#include <QAbstractListModel> #include <QAbstractListModel>
@ -10,6 +11,9 @@
#include <Plasma/Containment> #include <Plasma/Containment>
class HomeScreen;
class PageModel;
class PageListModel : public QAbstractListModel class PageListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
@ -18,9 +22,7 @@ class PageListModel : public QAbstractListModel
public: public:
enum Roles { PageRole = Qt::UserRole + 1 }; enum Roles { PageRole = Qt::UserRole + 1 };
PageListModel(QObject *parent = nullptr); PageListModel(HomeScreen *parent = nullptr);
static PageListModel *self();
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@ -40,13 +42,11 @@ public:
Q_INVOKABLE void load(); Q_INVOKABLE void load();
void loadFromJson(QJsonArray arr); void loadFromJson(QJsonArray arr);
void setContainment(Plasma::Containment *containment);
Q_SIGNALS: Q_SIGNALS:
void lengthChanged(); void lengthChanged();
private: private:
QList<PageModel *> m_pages; HomeScreen *m_homeScreen{nullptr};
Plasma::Containment *m_containment{nullptr}; QList<PageModel *> m_pages;
}; };

View file

@ -6,268 +6,12 @@
#include "homescreenstate.h" #include "homescreenstate.h"
#include "widgetsmanager.h" #include "widgetsmanager.h"
FolioPageDelegate::FolioPageDelegate(int row, int column, QObject *parent) PageModel::PageModel(QList<FolioPageDelegate *> delegates, QObject *parent, HomeScreen *homeScreen)
: FolioDelegate{parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplication *application, QObject *parent)
: FolioDelegate{application, parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplicationFolder *folder, QObject *parent)
: FolioDelegate{folder, parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioWidget *widget, QObject *parent)
: FolioDelegate{widget, parent}
, m_row{row}
, m_column{column}
{
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioDelegate *delegate, QObject *parent)
: FolioDelegate{parent}
, m_row{row}
, m_column{column}
{
m_type = delegate->type();
m_application = delegate->application();
m_folder = delegate->folder();
m_widget = delegate->widget();
init();
}
void FolioPageDelegate::init()
{
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realRow = m_row;
m_realColumn = m_column;
break;
case HomeScreenState::RotateClockwise:
m_realRow = HomeScreenState::self()->pageColumns() - m_column - 1;
m_realColumn = m_row;
if (m_widget) {
// since top-left in cw is bottom-left in portrait
m_realRow -= m_widget->realGridHeight() - 1;
}
break;
case HomeScreenState::RotateCounterClockwise:
m_realRow = m_column;
m_realColumn = HomeScreenState::self()->pageRows() - m_row - 1;
if (m_widget) {
// since top-left in ccw is top-right in portrait
m_realColumn -= m_widget->realGridWidth() - 1;
}
break;
case HomeScreenState::RotateUpsideDown:
m_realRow = HomeScreenState::self()->pageRows() - m_row - 1;
m_realColumn = HomeScreenState::self()->pageColumns() - m_column - 1;
if (m_widget) {
// since top-left in upside-down is bottom-right in portrait
m_realRow -= m_widget->realGridHeight() - 1;
m_realColumn -= m_widget->realGridWidth() - 1;
}
break;
}
if (m_widget) {
connect(m_widget, &FolioWidget::realTopLeftPositionChanged, this, [this](int rowOffset, int columnOffset) {
m_realRow += rowOffset;
m_realColumn += columnOffset;
});
}
connect(HomeScreenState::self(), &HomeScreenState::pageOrientationChanged, this, [this]() {
setRowOnly(getTranslatedTopLeftRow(m_realRow, m_realColumn, this));
setColumnOnly(getTranslatedTopLeftColumn(m_realRow, m_realColumn, this));
});
}
FolioPageDelegate *FolioPageDelegate::fromJson(QJsonObject &obj, QObject *parent)
{
FolioDelegate *fd = FolioDelegate::fromJson(obj, parent);
if (!fd) {
return nullptr;
}
int realRow = obj[QStringLiteral("row")].toInt();
int realColumn = obj[QStringLiteral("column")].toInt();
int row = getTranslatedTopLeftRow(realRow, realColumn, fd);
int column = getTranslatedTopLeftColumn(realRow, realColumn, fd);
FolioPageDelegate *delegate = new FolioPageDelegate{row, column, fd, parent};
fd->deleteLater();
return delegate;
}
int FolioPageDelegate::getTranslatedTopLeftRow(int realRow, int realColumn, FolioDelegate *fd)
{
int row = getTranslatedRow(realRow, realColumn);
int column = getTranslatedColumn(realRow, realColumn);
// special logic to return "top left" for widgets, since they take more than one tile
if (fd->type() == FolioDelegate::Widget) {
return fd->widget()->topLeftCorner(row, column).row;
} else {
return row;
}
}
int FolioPageDelegate::getTranslatedTopLeftColumn(int realRow, int realColumn, FolioDelegate *fd)
{
int row = getTranslatedRow(realRow, realColumn);
int column = getTranslatedColumn(realRow, realColumn);
// special logic to return "top left" for widgets, since they take more than one tile
if (fd->type() == FolioDelegate::Widget) {
return fd->widget()->topLeftCorner(row, column).column;
} else {
return column;
}
}
int FolioPageDelegate::getTranslatedRow(int realRow, int realColumn)
{
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
return realRow;
case HomeScreenState::RotateClockwise:
return realColumn;
case HomeScreenState::RotateCounterClockwise:
return FolioSettings::self()->homeScreenColumns() - realColumn - 1;
case HomeScreenState::RotateUpsideDown:
return FolioSettings::self()->homeScreenRows() - realRow - 1;
}
return realRow;
}
int FolioPageDelegate::getTranslatedColumn(int realRow, int realColumn)
{
// we have to use the "real" rows and columns, so fetch them from FolioSettings instead of HomeScreenState
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
return realColumn;
case HomeScreenState::RotateClockwise:
return FolioSettings::self()->homeScreenRows() - realRow - 1;
case HomeScreenState::RotateCounterClockwise:
return realRow;
case HomeScreenState::RotateUpsideDown:
return FolioSettings::self()->homeScreenColumns() - realColumn - 1;
}
return realRow;
}
QJsonObject FolioPageDelegate::toJson() const
{
QJsonObject o = FolioDelegate::toJson();
o[QStringLiteral("row")] = m_realRow;
o[QStringLiteral("column")] = m_realColumn;
return o;
}
int FolioPageDelegate::row()
{
return m_row;
}
void FolioPageDelegate::setRow(int row)
{
if (m_row != row) {
// adjust stored data too
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realRow = row;
break;
case HomeScreenState::RotateClockwise:
m_realColumn += row - m_row;
break;
case HomeScreenState::RotateCounterClockwise:
m_realColumn += m_row - row;
break;
case HomeScreenState::RotateUpsideDown:
m_realRow += m_row - row;
break;
}
setRowOnly(row);
}
}
void FolioPageDelegate::setRowOnly(int row)
{
if (m_row != row) {
m_row = row;
Q_EMIT rowChanged();
}
}
int FolioPageDelegate::column()
{
return m_column;
}
void FolioPageDelegate::setColumn(int column)
{
if (m_column != column) {
// adjust stored data too
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
m_realColumn = column;
break;
case HomeScreenState::RotateClockwise:
m_realRow += m_column - column;
break;
case HomeScreenState::RotateCounterClockwise:
m_realRow += column - m_column;
break;
case HomeScreenState::RotateUpsideDown:
m_realColumn += m_column - column;
break;
}
setColumnOnly(column);
}
}
void FolioPageDelegate::setColumnOnly(int column)
{
if (m_column != column) {
m_column = column;
Q_EMIT columnChanged();
}
}
PageModel::PageModel(QList<FolioPageDelegate *> delegates, QObject *parent)
: QAbstractListModel{parent} : QAbstractListModel{parent}
, m_homeScreen{homeScreen}
, m_delegates{delegates} , m_delegates{delegates}
{ {
connect(WidgetsManager::self(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) { connect(homeScreen->widgetsManager(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) {
if (applet) { if (applet) {
// delete any instance of this widget // delete any instance of this widget
for (int i = 0; i < m_delegates.size(); i++) { for (int i = 0; i < m_delegates.size(); i++) {
@ -283,20 +27,20 @@ PageModel::PageModel(QList<FolioPageDelegate *> delegates, QObject *parent)
PageModel::~PageModel() = default; PageModel::~PageModel() = default;
PageModel *PageModel::fromJson(QJsonArray &arr, QObject *parent) PageModel *PageModel::fromJson(QJsonArray &arr, QObject *parent, HomeScreen *homeScreen)
{ {
QList<FolioPageDelegate *> delegates; QList<FolioPageDelegate *> delegates;
for (QJsonValueRef r : arr) { for (QJsonValueRef r : arr) {
QJsonObject obj = r.toObject(); QJsonObject obj = r.toObject();
FolioPageDelegate *delegate = FolioPageDelegate::fromJson(obj, parent); FolioPageDelegate *delegate = FolioPageDelegate::fromJson(obj, homeScreen);
if (delegate) { if (delegate) {
delegates.append(delegate); delegates.append(delegate);
} }
} }
PageModel *model = new PageModel{delegates, parent}; PageModel *model = new PageModel{delegates, parent, homeScreen};
// ensure delegates can request saves // ensure delegates can request saves
for (auto *delegate : delegates) { for (auto *delegate : delegates) {
@ -372,7 +116,9 @@ void PageModel::removeDelegate(int index)
bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate) bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate)
{ {
if (row < 0 || row >= HomeScreenState::self()->pageRows() || column < 0 || column >= HomeScreenState::self()->pageColumns()) { HomeScreenState *homeScreenState = m_homeScreen->homeScreenState();
if (row < 0 || row >= homeScreenState->pageRows() || column < 0 || column >= homeScreenState->pageColumns()) {
return false; return false;
} }
@ -384,8 +130,8 @@ bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate)
int maxColumn = column + delegate->widget()->gridWidth() - 1; int maxColumn = column + delegate->widget()->gridWidth() - 1;
// check bounds // check bounds
if ((row < 0 || row >= HomeScreenState::self()->pageRows()) || (maxRow < 0 || maxRow >= HomeScreenState::self()->pageRows()) if ((row < 0 || row >= homeScreenState->pageRows()) || (maxRow < 0 || maxRow >= homeScreenState->pageRows())
|| (column < 0 || column >= HomeScreenState::self()->pageColumns()) || (maxColumn < 0 || maxColumn >= HomeScreenState::self()->pageColumns())) { || (column < 0 || column >= homeScreenState->pageColumns()) || (maxColumn < 0 || maxColumn >= homeScreenState->pageColumns())) {
return false; return false;
} }
@ -462,11 +208,11 @@ void PageModel::moveAndResizeWidgetDelegate(FolioPageDelegate *delegate, int new
} }
// test if we can add the delegate with new size and position // test if we can add the delegate with new size and position
FolioWidget *testWidget = new FolioWidget(this, 0, 0, 0); FolioWidget *testWidget = new FolioWidget(m_homeScreen, 0, 0, 0);
// we have to use setGridWidth and setGridHeight since it takes into account the page orientation // we have to use setGridWidth and setGridHeight since it takes into account the page orientation
testWidget->setGridWidth(newGridWidth); testWidget->setGridWidth(newGridWidth);
testWidget->setGridHeight(newGridHeight); testWidget->setGridHeight(newGridHeight);
FolioDelegate *testDelegate = new FolioDelegate(testWidget, this); FolioDelegate *testDelegate = new FolioDelegate(testWidget, m_homeScreen);
// NOT THREAD SAFE! // NOT THREAD SAFE!
// which is fine, because the GUI isn't multithreaded // which is fine, because the GUI isn't multithreaded

View file

@ -6,6 +6,7 @@
#include "folioapplication.h" #include "folioapplication.h"
#include "folioapplicationfolder.h" #include "folioapplicationfolder.h"
#include "foliodelegate.h" #include "foliodelegate.h"
#include "homescreen.h"
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QJsonArray> #include <QJsonArray>
@ -13,51 +14,13 @@
#include <Plasma/Applet> #include <Plasma/Applet>
class FolioPageDelegate : public FolioDelegate class HomeScreen;
{ class FolioPageDelegate;
Q_OBJECT
Q_PROPERTY(int row READ row NOTIFY rowChanged)
Q_PROPERTY(int column READ column NOTIFY columnChanged)
public:
FolioPageDelegate(int row = 0, int column = 0, QObject *parent = nullptr);
FolioPageDelegate(int row, int column, FolioApplication *application, QObject *parent);
FolioPageDelegate(int row, int column, FolioApplicationFolder *folder, QObject *parent);
FolioPageDelegate(int row, int column, FolioWidget *widget, QObject *parent);
FolioPageDelegate(int row, int column, FolioDelegate *delegate, QObject *parent);
static FolioPageDelegate *fromJson(QJsonObject &obj, QObject *parent);
static int getTranslatedTopLeftRow(int realRow, int realColumn, FolioDelegate *fd);
static int getTranslatedTopLeftColumn(int realRow, int realColumn, FolioDelegate *fd);
static int getTranslatedRow(int realRow, int realColumn);
static int getTranslatedColumn(int realRow, int realColumn);
virtual QJsonObject toJson() const override;
int row();
void setRow(int row);
int column();
void setColumn(int column);
Q_SIGNALS:
void rowChanged();
void columnChanged();
private:
void setRowOnly(int row);
void setColumnOnly(int column);
void init();
int m_realRow;
int m_realColumn;
int m_row;
int m_column;
};
class PageModel : public QAbstractListModel class PageModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
public: public:
enum Roles { enum Roles {
DelegateRole = Qt::UserRole + 1, DelegateRole = Qt::UserRole + 1,
@ -66,10 +29,10 @@ public:
ShownRole, ShownRole,
}; };
PageModel(QList<FolioPageDelegate *> delegates = QList<FolioPageDelegate *>{}, QObject *parent = nullptr); PageModel(QList<FolioPageDelegate *> delegates = QList<FolioPageDelegate *>{}, QObject *parent = nullptr, HomeScreen *m_homeScreen = nullptr);
~PageModel(); ~PageModel();
static PageModel *fromJson(QJsonArray &arr, QObject *parent); static PageModel *fromJson(QJsonArray &arr, QObject *parent, HomeScreen *homeScreen);
QJsonArray toJson() const; QJsonArray toJson() const;
@ -95,5 +58,7 @@ Q_SIGNALS:
private: private:
void connectSaveRequests(FolioDelegate *delegate); void connectSaveRequests(FolioDelegate *delegate);
HomeScreen *m_homeScreen{nullptr};
QList<FolioPageDelegate *> m_delegates; QList<FolioPageDelegate *> m_delegates;
}; };

View file

@ -8,12 +8,6 @@ WidgetsManager::WidgetsManager(QObject *parent)
{ {
} }
WidgetsManager *WidgetsManager::self()
{
static WidgetsManager *manager = new WidgetsManager{nullptr};
return manager;
}
Plasma::Applet *WidgetsManager::getWidget(int id) Plasma::Applet *WidgetsManager::getWidget(int id)
{ {
for (auto *widget : m_widgets) { for (auto *widget : m_widgets) {

View file

@ -3,6 +3,8 @@
#pragma once #pragma once
#include "homescreen.h"
#include <QObject> #include <QObject>
#include <Plasma/Applet> #include <Plasma/Applet>
@ -15,8 +17,6 @@ class WidgetsManager : public QObject
public: public:
WidgetsManager(QObject *parent = nullptr); WidgetsManager(QObject *parent = nullptr);
static WidgetsManager *self();
Plasma::Applet *getWidget(int id); Plasma::Applet *getWidget(int id);
void addWidget(Plasma::Applet *applet); void addWidget(Plasma::Applet *applet);