folio: Use smart pointers to manage delegate lifetimes

Currently delegates do not get deleted when removed from models. Due to
the complexity of drag state and other objects, we can't simply delete
the delegate when removed from the model because they might still be
involved in animations or other state at the time of removal. Use smart
pointers to have the delegate objects deleted instead.

QML unfortunately doesn't support QSharedPointer, so we need to expose raw pointers to it.
This commit is contained in:
Devin Lin 2025-02-21 18:06:24 +00:00
parent c8d215f2a3
commit 3550caa580
18 changed files with 250 additions and 193 deletions

View file

@ -80,17 +80,17 @@ void ApplicationListModel::load()
m_delegates.clear();
QList<FolioDelegate *> unorderedList;
QList<FolioDelegate::Ptr> unorderedList;
const KService::List apps = KApplicationTrader::query(filter);
for (const KService::Ptr &service : apps) {
FolioApplication *app = new FolioApplication{m_homeScreen, service};
FolioDelegate *delegate = new FolioDelegate{app, m_homeScreen};
FolioApplication::Ptr app = std::make_shared<FolioApplication>(m_homeScreen, service);
FolioDelegate::Ptr delegate = std::make_shared<FolioDelegate>(app, m_homeScreen);
unorderedList << delegate;
}
std::sort(unorderedList.begin(), unorderedList.end(), [](FolioDelegate *a1, FolioDelegate *a2) {
std::sort(unorderedList.begin(), unorderedList.end(), [](FolioDelegate::Ptr &a1, FolioDelegate::Ptr &a2) {
return a1->application()->name().compare(a2->application()->name(), Qt::CaseInsensitive) < 0;
});
@ -105,12 +105,12 @@ QVariant ApplicationListModel::data(const QModelIndex &index, int role) const
return QVariant();
}
FolioDelegate *delegate = m_delegates.at(index.row());
FolioDelegate::Ptr delegate = m_delegates.at(index.row());
switch (role) {
case Qt::DisplayRole:
case DelegateRole:
return QVariant::fromValue(delegate);
return QVariant::fromValue(delegate.get());
case NameRole:
if (!delegate->application()) {
return QVariant();

View file

@ -43,8 +43,8 @@ public Q_SLOTS:
protected:
HomeScreen *m_homeScreen{nullptr};
QList<FolioDelegate *> m_delegates;
QList<std::shared_ptr<FolioDelegate>> m_delegates;
QTimer *m_reloadAppsTimer{nullptr};
};

View file

@ -109,12 +109,17 @@ void DelegateDragPosition::setFolderPosition(int folderPosition)
}
}
FolioApplicationFolder *DelegateDragPosition::folder() const
FolioApplicationFolder::Ptr DelegateDragPosition::folder() const
{
return m_folder;
}
void DelegateDragPosition::setFolder(FolioApplicationFolder *folder)
FolioApplicationFolder *DelegateDragPosition::folderRaw() const
{
return m_folder.get();
}
void DelegateDragPosition::setFolder(FolioApplicationFolder::Ptr folder)
{
if (m_folder != folder) {
m_folder = folder;
@ -197,12 +202,17 @@ DelegateDragPosition *DragState::startPosition() const
return m_startPosition;
}
FolioDelegate *DragState::dropDelegate() const
FolioDelegate::Ptr DragState::dropDelegate() const
{
return m_dropDelegate;
}
void DragState::setDropDelegate(FolioDelegate *dropDelegate)
FolioDelegate *DragState::dropDelegateRaw() const
{
return m_dropDelegate.get();
}
void DragState::setDropDelegate(FolioDelegate::Ptr dropDelegate)
{
m_dropDelegate = dropDelegate;
Q_EMIT dropDelegateChanged();
@ -266,7 +276,7 @@ void DragState::onDelegateDragPositionOverFolderViewChanged()
qreal x = getPointerX();
qreal y = getPointerY();
auto *folder = m_state->currentFolder();
FolioApplicationFolder::Ptr folder = m_state->currentFolder();
if (!folder) {
return;
}
@ -370,7 +380,7 @@ void DragState::onDelegateDragPositionOverFavouritesChanged()
// start folder open timer if hovering over a folder
// get delegate being hovered over
FolioDelegate *delegate = favouritesModel->getEntryAt(dropIndex);
FolioDelegate::Ptr delegate = favouritesModel->getEntryAt(dropIndex);
// 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) {
@ -430,7 +440,7 @@ void DragState::onDelegateDragPositionOverPageViewChanged()
PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
if (pageModel) {
// get delegate being hovered over
FolioDelegate *delegate = pageModel->getDelegate(row, column);
FolioDelegate::Ptr delegate = pageModel->getDelegate(row, column);
// 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) {
@ -495,8 +505,8 @@ void DragState::onDelegateDragFromAppDrawerStarted(QString storageId)
{
// fetch delegate at start position
if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
FolioApplication *app = new FolioApplication{m_homeScreen, service};
setDropDelegate(new FolioDelegate{app, m_homeScreen});
FolioApplication::Ptr app = std::make_shared<FolioApplication>(m_homeScreen, service);
setDropDelegate(std::make_shared<FolioDelegate>(app, m_homeScreen));
} else {
setDropDelegate(nullptr);
}
@ -511,7 +521,7 @@ void DragState::onDelegateDragFromFolderStarted(FolioApplicationFolder *folder,
setDropDelegate(folder->applications()->getDelegate(position));
// set start location
m_startPosition->setFolder(folder);
m_startPosition->setFolder(folder->shared_from_this());
m_startPosition->setFolderPosition(position);
m_startPosition->setLocation(DelegateDragPosition::Folder);
}
@ -520,8 +530,8 @@ void DragState::onDelegateDragFromWidgetListStarted(QString appletPluginId)
{
// default widget has dimensions of 1x1, and id of -1
m_createdAppletPluginId = appletPluginId;
FolioWidget *widget = new FolioWidget{m_homeScreen, -1, 1, 1};
setDropDelegate(new FolioDelegate{widget, m_homeScreen});
FolioWidget::Ptr widget = std::make_shared<FolioWidget>(m_homeScreen, -1, 1, 1);
setDropDelegate(std::make_shared<FolioDelegate>(widget, m_homeScreen));
// set start location
m_startPosition->setLocation(DelegateDragPosition::WidgetList);
@ -619,7 +629,7 @@ void DragState::onOpenFolderTimerFinished()
return;
}
FolioApplicationFolder *folder = nullptr;
FolioApplicationFolder::Ptr folder = nullptr;
QPointF screenPosition;
switch (m_candidateDropPosition->location()) {
@ -631,7 +641,7 @@ void DragState::onOpenFolderTimerFinished()
}
// get delegate being hovered over
FolioDelegate *delegate = page->getDelegate(m_candidateDropPosition->pageRow(), m_candidateDropPosition->pageColumn());
FolioDelegate::Ptr delegate = page->getDelegate(m_candidateDropPosition->pageRow(), m_candidateDropPosition->pageColumn());
if (!delegate || delegate->type() != FolioDelegate::Folder) {
return;
}
@ -643,7 +653,7 @@ void DragState::onOpenFolderTimerFinished()
}
case DelegateDragPosition::Favourites: {
// get delegate being hovered over in favourites bar
FolioDelegate *delegate = m_homeScreen->favouritesModel()->getEntryAt(m_candidateDropPosition->favouritesPosition());
FolioDelegate::Ptr delegate = m_homeScreen->favouritesModel()->getEntryAt(m_candidateDropPosition->favouritesPosition());
if (!delegate || delegate->type() != FolioDelegate::Folder) {
return;
}
@ -657,7 +667,7 @@ void DragState::onOpenFolderTimerFinished()
}
// open the folder
m_state->openFolder(screenPosition.x(), screenPosition.y(), folder);
m_state->openFolder(screenPosition.x(), screenPosition.y(), folder.get());
}
void DragState::onLeaveFolderTimerFinished()
@ -678,7 +688,7 @@ void DragState::onChangeFolderPageTimerFinished()
return;
}
auto *folder = m_state->currentFolder();
FolioApplicationFolder::Ptr folder = m_state->currentFolder();
qreal x = getPointerX();
qreal y = getPointerY();
@ -714,7 +724,7 @@ void DragState::onFolderInsertBetweenTimerFinished()
return;
}
auto *folder = m_state->currentFolder();
FolioApplicationFolder::Ptr folder = m_state->currentFolder();
// update the candidate drop position
m_candidateDropPosition->setFolder(folder);
@ -782,10 +792,10 @@ bool DragState::createDropPositionDelegate()
int column = m_candidateDropPosition->pageColumn();
// delegate to add
FolioPageDelegate *delegate = new FolioPageDelegate{row, column, m_dropDelegate, m_homeScreen};
FolioPageDelegate::Ptr delegate = std::make_shared<FolioPageDelegate>(row, column, m_dropDelegate, m_homeScreen);
// delegate that exists at the drop position
FolioPageDelegate *existingDelegate = page->getDelegate(row, column);
FolioPageDelegate::Ptr existingDelegate = page->getDelegate(row, column);
// if a delegate already exists at the spot, check if we can insert/create a folder
if (existingDelegate) {
@ -801,10 +811,10 @@ bool DragState::createDropPositionDelegate()
} else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) {
// create a folder from the two apps
FolioApplicationFolder *folder = new FolioApplicationFolder(m_homeScreen, DEFAULT_FOLDER_NAME);
FolioApplicationFolder::Ptr folder = std::make_shared<FolioApplicationFolder>(m_homeScreen, DEFAULT_FOLDER_NAME);
folder->addDelegate(delegate, 0);
folder->addDelegate(existingDelegate, 0);
FolioPageDelegate *folderDelegate = new FolioPageDelegate{row, column, folder, m_homeScreen};
FolioPageDelegate::Ptr folderDelegate = std::make_shared<FolioPageDelegate>(row, column, folder, m_homeScreen);
page->removeDelegate(row, column);
page->addDelegate(folderDelegate);
@ -828,7 +838,7 @@ bool DragState::createDropPositionDelegate()
}
case DelegateDragPosition::Favourites: {
// delegate that exists at the drop position
FolioDelegate *existingDelegate = m_homeScreen->favouritesModel()->getEntryAt(m_candidateDropPosition->favouritesPosition());
FolioDelegate::Ptr 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 (existingDelegate) {
@ -844,10 +854,10 @@ bool DragState::createDropPositionDelegate()
} else if (existingDelegate->type() == FolioDelegate::Application && !isStartPositionEqualDropPosition()) {
// create a folder from the two apps
FolioApplicationFolder *folder = new FolioApplicationFolder(m_homeScreen, DEFAULT_FOLDER_NAME);
FolioApplicationFolder::Ptr folder = std::make_shared<FolioApplicationFolder>(m_homeScreen, DEFAULT_FOLDER_NAME);
folder->addDelegate(m_dropDelegate, 0);
folder->addDelegate(existingDelegate, 0);
FolioDelegate *folderDelegate = new FolioDelegate{folder, m_homeScreen};
FolioDelegate::Ptr folderDelegate = std::make_shared<FolioDelegate>(folder, m_homeScreen);
m_homeScreen->favouritesModel()->removeEntry(m_candidateDropPosition->favouritesPosition());
m_homeScreen->favouritesModel()->addEntry(m_candidateDropPosition->favouritesPosition(), folderDelegate);
@ -878,7 +888,7 @@ bool DragState::createDropPositionDelegate()
break;
}
case DelegateDragPosition::Folder: {
auto *folder = m_candidateDropPosition->folder();
FolioApplicationFolder::Ptr folder = m_candidateDropPosition->folder();
if (!folder) {
break;
}

View file

@ -23,7 +23,7 @@ class DelegateDragPosition : public QObject
Q_PROPERTY(int pageColumn READ pageColumn NOTIFY pageColumnChanged)
Q_PROPERTY(int favouritesPosition READ favouritesPosition NOTIFY favouritesPositionChanged)
Q_PROPERTY(int folderPosition READ folderPosition NOTIFY folderPositionChanged)
Q_PROPERTY(FolioApplicationFolder *folder READ folder NOTIFY folderChanged)
Q_PROPERTY(FolioApplicationFolder *folder READ folderRaw NOTIFY folderChanged)
public:
enum Location { Pages, Favourites, AppDrawer, Folder, WidgetList };
@ -53,8 +53,9 @@ public:
void setFolderPosition(int folderPosition);
// TODO: what if the folder becomes invalid? we need to clear it
FolioApplicationFolder *folder() const;
void setFolder(FolioApplicationFolder *folder);
std::shared_ptr<FolioApplicationFolder> folder() const;
FolioApplicationFolder *folderRaw() const;
void setFolder(std::shared_ptr<FolioApplicationFolder> folder);
Q_SIGNALS:
void locationChanged();
@ -72,7 +73,7 @@ private:
int m_pageColumn{0};
int m_favouritesPosition{0};
int m_folderPosition{0};
FolioApplicationFolder *m_folder{nullptr};
std::shared_ptr<FolioApplicationFolder> m_folder{nullptr};
};
Q_DECLARE_METATYPE(DelegateDragPosition);
@ -82,15 +83,17 @@ class DragState : public QObject
Q_OBJECT
Q_PROPERTY(DelegateDragPosition *candidateDropPosition READ candidateDropPosition CONSTANT)
Q_PROPERTY(DelegateDragPosition *startPosition READ startPosition CONSTANT)
Q_PROPERTY(FolioDelegate *dropDelegate READ dropDelegate NOTIFY dropDelegateChanged)
Q_PROPERTY(FolioDelegate *dropDelegate READ dropDelegateRaw NOTIFY dropDelegateChanged)
public:
DragState(HomeScreenState *state = nullptr, HomeScreen *parent = nullptr);
DelegateDragPosition *candidateDropPosition() const;
DelegateDragPosition *startPosition() const;
FolioDelegate *dropDelegate() const;
void setDropDelegate(FolioDelegate *dropDelegate);
std::shared_ptr<FolioDelegate> dropDelegate() const;
FolioDelegate *dropDelegateRaw() const;
void setDropDelegate(std::shared_ptr<FolioDelegate> dropDelegate);
Q_SIGNALS:
void dropDelegateChanged();
@ -157,7 +160,7 @@ private:
int m_favouritesInsertBetweenIndex{0};
// the delegate that is being dropped
FolioDelegate *m_dropDelegate{nullptr};
std::shared_ptr<FolioDelegate> m_dropDelegate{nullptr};
// where we are hovering over, potentially to drop the delegate
DelegateDragPosition *const m_candidateDropPosition{nullptr};

View file

@ -40,7 +40,7 @@ QVariant FavouritesModel::data(const QModelIndex &index, int role) const
switch (role) {
case DelegateRole:
return QVariant::fromValue(m_delegates.at(index.row()).delegate);
return QVariant::fromValue(m_delegates.at(index.row()).delegate.get());
}
return QVariant();
@ -90,7 +90,7 @@ void FavouritesModel::moveEntry(int fromRow, int toRow)
save();
}
bool FavouritesModel::canAddEntry(int row, FolioDelegate *delegate)
bool FavouritesModel::canAddEntry(int row, FolioDelegate::Ptr delegate)
{
if (!delegate) {
return false;
@ -103,7 +103,7 @@ bool FavouritesModel::canAddEntry(int row, FolioDelegate *delegate)
return true;
}
bool FavouritesModel::addEntry(int row, FolioDelegate *delegate)
bool FavouritesModel::addEntry(int row, FolioDelegate::Ptr delegate)
{
if (!canAddEntry(row, delegate)) {
return false;
@ -129,7 +129,7 @@ bool FavouritesModel::addEntry(int row, FolioDelegate *delegate)
return true;
}
FolioDelegate *FavouritesModel::getEntryAt(int row)
FolioDelegate::Ptr FavouritesModel::getEntryAt(int row)
{
if (row < 0 || row >= m_delegates.size()) {
return nullptr;
@ -186,12 +186,12 @@ void FavouritesModel::setGhostEntry(int row)
// if it doesn't, add a new empty delegate
if (!found) {
FolioDelegate *ghost = new FolioDelegate{m_homeScreen};
FolioDelegate::Ptr ghost = std::make_shared<FolioDelegate>(m_homeScreen);
addEntry(row, ghost);
}
}
void FavouritesModel::replaceGhostEntry(FolioDelegate *delegate)
void FavouritesModel::replaceGhostEntry(FolioDelegate::Ptr delegate)
{
for (int i = 0; i < m_delegates.size(); i++) {
if (m_delegates[i].delegate->type() == FolioDelegate::None) {
@ -221,7 +221,7 @@ QJsonArray FavouritesModel::exportToJson()
{
QJsonArray arr;
for (int i = 0; i < m_delegates.size(); i++) {
FolioDelegate *delegate = m_delegates[i].delegate;
FolioDelegate::Ptr delegate = m_delegates[i].delegate;
// if this delegate is empty, ignore it
if (!delegate || delegate->type() == FolioDelegate::None) {
@ -264,7 +264,7 @@ void FavouritesModel::loadFromJson(QJsonArray arr)
for (QJsonValueRef r : arr) {
QJsonObject obj = r.toObject();
FolioDelegate *delegate = FolioDelegate::fromJson(obj, m_homeScreen);
FolioDelegate::Ptr delegate = FolioDelegate::fromJson(obj, m_homeScreen);
if (delegate) {
connectSaveRequests(delegate);
@ -275,10 +275,10 @@ void FavouritesModel::loadFromJson(QJsonArray arr)
endResetModel();
}
void FavouritesModel::connectSaveRequests(FolioDelegate *delegate)
void FavouritesModel::connectSaveRequests(FolioDelegate::Ptr delegate)
{
if (delegate->type() == FolioDelegate::Folder && delegate->folder()) {
connect(delegate->folder(), &FolioApplicationFolder::saveRequested, this, &FavouritesModel::save);
connect(delegate->folder().get(), &FolioApplicationFolder::saveRequested, this, &FavouritesModel::save);
}
}

View file

@ -20,7 +20,7 @@ class HomeScreen;
class FolioDelegate;
struct FavouritesDelegate {
FolioDelegate *delegate;
std::shared_ptr<FolioDelegate> delegate;
qreal xPosition;
};
@ -41,9 +41,9 @@ public:
Q_INVOKABLE void removeEntry(int row);
void moveEntry(int fromRow, int toRow);
bool canAddEntry(int row, FolioDelegate *delegate);
bool addEntry(int row, FolioDelegate *delegate);
FolioDelegate *getEntryAt(int row);
bool canAddEntry(int row, std::shared_ptr<FolioDelegate> delegate);
bool addEntry(int row, std::shared_ptr<FolioDelegate> delegate);
std::shared_ptr<FolioDelegate> getEntryAt(int row);
// whether the dock is full, we can't add any more items
bool isFull() const;
@ -53,7 +53,7 @@ public:
// invisible - existing delegate looks like it doesn't exist
int getGhostEntryPosition();
void setGhostEntry(int row);
void replaceGhostEntry(FolioDelegate *delegate);
void replaceGhostEntry(std::shared_ptr<FolioDelegate> delegate);
void deleteGhostEntry();
// whether the position given is in between 2 delegates, or at the edge.
@ -71,7 +71,7 @@ public:
void loadFromJson(QJsonArray arr);
private:
void connectSaveRequests(FolioDelegate *delegate);
void connectSaveRequests(std::shared_ptr<FolioDelegate> delegate);
// get the x (or y) position where delegates start being placed
qreal getDelegateRowStartPos() const;

View file

@ -35,11 +35,11 @@ FolioApplication::FolioApplication(HomeScreen *parent, KService::Ptr service)
});
}
FolioApplication *FolioApplication::fromJson(QJsonObject &obj, HomeScreen *parent)
FolioApplication::Ptr FolioApplication::fromJson(QJsonObject &obj, HomeScreen *parent)
{
QString storageId = obj[QStringLiteral("storageId")].toString();
if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
return new FolioApplication(parent, service);
return std::make_shared<FolioApplication>(parent, service);
}
return nullptr;
}

View file

@ -23,7 +23,7 @@ class HomeScreen;
/**
* @short Object that represents an application.
*/
class FolioApplication : public QObject
class FolioApplication : public QObject, public std::enable_shared_from_this<FolioApplication>
{
Q_OBJECT
Q_PROPERTY(bool running READ running NOTIFY windowChanged)
@ -32,9 +32,11 @@ class FolioApplication : public QObject
Q_PROPERTY(QString storageId READ storageId NOTIFY storageIdChanged)
public:
typedef std::shared_ptr<FolioApplication> Ptr;
FolioApplication(HomeScreen *parent = nullptr, KService::Ptr service = QExplicitlySharedDataPointer<KService>{nullptr});
static FolioApplication *fromJson(QJsonObject &obj, HomeScreen *parent); // may return nullptr
static FolioApplication::Ptr fromJson(QJsonObject &obj, HomeScreen *parent); // may return nullptr
QJsonObject toJson() const;
bool running() const;

View file

@ -15,17 +15,17 @@ FolioApplicationFolder::FolioApplicationFolder(HomeScreen *parent, QString name)
{
}
FolioApplicationFolder *FolioApplicationFolder::fromJson(QJsonObject &obj, HomeScreen *parent)
FolioApplicationFolder::Ptr FolioApplicationFolder::fromJson(QJsonObject &obj, HomeScreen *parent)
{
QString name = obj[QStringLiteral("name")].toString();
QList<FolioApplication *> apps;
QList<FolioApplication::Ptr> apps;
for (auto storageId : obj[QStringLiteral("apps")].toArray()) {
if (KService::Ptr service = KService::serviceByStorageId(storageId.toString())) {
apps.append(new FolioApplication(parent, service));
apps.append(std::make_shared<FolioApplication>(parent, service));
}
}
FolioApplicationFolder *folder = new FolioApplicationFolder(parent, name);
FolioApplicationFolder::Ptr folder = std::make_shared<FolioApplicationFolder>(parent, name);
folder->setApplications(apps);
return folder;
}
@ -69,7 +69,7 @@ QList<FolioApplication *> FolioApplicationFolder::appPreviews()
if (!m_delegates[i].delegate->application()) {
continue;
}
previews.push_back(m_delegates[i].delegate->application());
previews.push_back(m_delegates[i].delegate->application().get());
}
return previews;
}
@ -79,15 +79,15 @@ ApplicationFolderModel *FolioApplicationFolder::applications()
return m_applicationFolderModel;
}
void FolioApplicationFolder::setApplications(QList<FolioApplication *> applications)
void FolioApplicationFolder::setApplications(QList<FolioApplication::Ptr> applications)
{
if (m_applicationFolderModel) {
m_applicationFolderModel->deleteLater();
}
m_delegates.clear();
for (auto *app : applications) {
m_delegates.append({new FolioDelegate{app, m_homeScreen}, 0, 0});
for (FolioApplication::Ptr app : applications) {
m_delegates.append({FolioDelegate::Ptr{new FolioDelegate{app, m_homeScreen}}, 0, 0, 0});
}
m_applicationFolderModel = new ApplicationFolderModel{this};
m_applicationFolderModel->evaluateDelegateIndexes();
@ -102,7 +102,7 @@ void FolioApplicationFolder::moveEntry(int fromRow, int toRow)
m_applicationFolderModel->moveEntry(fromRow, toRow);
}
bool FolioApplicationFolder::addDelegate(FolioDelegate *delegate, int row)
bool FolioApplicationFolder::addDelegate(FolioDelegate::Ptr delegate, int row)
{
return m_applicationFolderModel->addDelegate(delegate, row);
}
@ -122,11 +122,11 @@ bool FolioApplicationFolder::isDropPositionOutside(qreal x, qreal y)
return m_applicationFolderModel->isDropPositionOutside(x, y);
}
ApplicationFolderModel::ApplicationFolderModel(FolioApplicationFolder *folder)
: QAbstractListModel{folder}
, m_folder{folder}
ApplicationFolderModel::ApplicationFolderModel(FolioApplicationFolder *parent)
: QAbstractListModel{parent}
, m_folder{parent}
{
HomeScreenState *homeScreenState = folder->m_homeScreen->homeScreenState();
HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
connect(homeScreenState, &HomeScreenState::folderPageWidthChanged, this, [this]() {
evaluateDelegateIndexes();
});
@ -166,7 +166,7 @@ QVariant ApplicationFolderModel::data(const QModelIndex &index, int role) const
switch (role) {
case DelegateRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).delegate);
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).delegate.get());
case columnIndexRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).columnIndex);
case rowIndexRole:
@ -183,7 +183,7 @@ QHash<int, QByteArray> ApplicationFolderModel::roleNames() const
return {{DelegateRole, "delegate"}, {columnIndexRole, "columnIndex"}, {rowIndexRole, "rowIndex"}, {pageIndexRole, "pageIndex"}};
}
FolioDelegate *ApplicationFolderModel::getDelegate(int index)
FolioDelegate::Ptr ApplicationFolderModel::getDelegate(int index)
{
if (index < 0 || index >= m_folder->m_delegates.size()) {
return nullptr;
@ -217,7 +217,7 @@ void ApplicationFolderModel::moveEntry(int fromRow, int toRow)
Q_EMIT m_folder->saveRequested();
}
bool ApplicationFolderModel::canAddDelegate(FolioDelegate *delegate, int index)
bool ApplicationFolderModel::canAddDelegate(FolioDelegate::Ptr delegate, int index)
{
if (index < 0 || index > m_folder->m_delegates.size()) {
return false;
@ -230,7 +230,7 @@ bool ApplicationFolderModel::canAddDelegate(FolioDelegate *delegate, int index)
return true;
}
bool ApplicationFolderModel::addDelegate(FolioDelegate *delegate, int index)
bool ApplicationFolderModel::addDelegate(FolioDelegate::Ptr delegate, int index)
{
if (!canAddDelegate(delegate, index)) {
return false;
@ -238,14 +238,14 @@ bool ApplicationFolderModel::addDelegate(FolioDelegate *delegate, int index)
if (index == m_folder->m_delegates.size()) {
beginInsertRows(QModelIndex(), index, index);
m_folder->m_delegates.append({delegate, 0, 0});
m_folder->m_delegates.append({delegate, 0, 0, 0});
evaluateDelegateIndexes(false);
endInsertRows();
} else if (m_folder->m_delegates[index].delegate->type() == FolioDelegate::None) {
replaceGhostEntry(delegate);
} else {
beginInsertRows(QModelIndex(), index, index);
m_folder->m_delegates.insert(index, {delegate, 0, 0});
m_folder->m_delegates.insert(index, {delegate, 0, 0, 0});
evaluateDelegateIndexes(false);
endInsertRows();
}
@ -309,7 +309,7 @@ int ApplicationFolderModel::getGhostEntryPosition()
void ApplicationFolderModel::setGhostEntry(int index)
{
FolioDelegate *ghost = nullptr;
FolioDelegate::Ptr ghost = nullptr;
// check if a ghost entry already exists
for (int i = 0; i < m_folder->m_delegates.size(); i++) {
@ -328,14 +328,14 @@ void ApplicationFolderModel::setGhostEntry(int index)
}
if (!ghost) {
ghost = new FolioDelegate{m_folder->m_homeScreen};
ghost = std::make_shared<FolioDelegate>(m_folder->m_homeScreen);
}
// add empty delegate at new position
addDelegate(ghost, index);
}
void ApplicationFolderModel::replaceGhostEntry(FolioDelegate *delegate)
void ApplicationFolderModel::replaceGhostEntry(FolioDelegate::Ptr delegate)
{
for (int i = 0; i < m_folder->m_delegates.size(); i++) {
if (m_folder->m_delegates[i].delegate->type() == FolioDelegate::None) {

View file

@ -28,7 +28,7 @@ class FolioApplication;
* @short Object that represents an application folder.
*/
class FolioApplicationFolder : public QObject
class FolioApplicationFolder : public QObject, public std::enable_shared_from_this<FolioApplicationFolder>
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
@ -36,9 +36,11 @@ class FolioApplicationFolder : public QObject
Q_PROPERTY(ApplicationFolderModel *applications READ applications NOTIFY applicationsReset)
public:
typedef std::shared_ptr<FolioApplicationFolder> Ptr;
FolioApplicationFolder(HomeScreen *parent = nullptr, QString name = QString{});
static FolioApplicationFolder *fromJson(QJsonObject &obj, HomeScreen *parent);
static std::shared_ptr<FolioApplicationFolder> fromJson(QJsonObject &obj, HomeScreen *parent);
QJsonObject toJson() const;
QString name() const;
@ -47,10 +49,10 @@ public:
QList<FolioApplication *> appPreviews();
ApplicationFolderModel *applications();
void setApplications(QList<FolioApplication *> applications);
void setApplications(QList<std::shared_ptr<FolioApplication>> applications);
void moveEntry(int fromRow, int toRow);
bool addDelegate(FolioDelegate *delegate, int row);
bool addDelegate(std::shared_ptr<FolioDelegate> delegate, int row);
Q_INVOKABLE void removeDelegate(int row);
int dropInsertPosition(int page, qreal x, qreal y);
@ -73,7 +75,7 @@ private:
};
struct ApplicationDelegate {
FolioDelegate *delegate;
std::shared_ptr<FolioDelegate> delegate;
int columnIndex;
int rowIndex;
int pageIndex;
@ -91,16 +93,16 @@ public:
rowIndexRole,
pageIndexRole,
};
ApplicationFolderModel(FolioApplicationFolder *folder);
ApplicationFolderModel(FolioApplicationFolder *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
FolioDelegate *getDelegate(int index);
std::shared_ptr<FolioDelegate> getDelegate(int index);
void moveEntry(int fromRow, int toRow);
bool canAddDelegate(FolioDelegate *delegate, int index);
bool addDelegate(FolioDelegate *delegate, int index);
bool canAddDelegate(std::shared_ptr<FolioDelegate> delegate, int index);
bool addDelegate(std::shared_ptr<FolioDelegate> delegate, int index);
void removeDelegate(int index);
QPointF getDelegatePosition(int index);
@ -109,7 +111,7 @@ public:
// invisible - existing delegate looks like it doesn't exist
int getGhostEntryPosition();
void setGhostEntry(int index);
void replaceGhostEntry(FolioDelegate *delegate);
void replaceGhostEntry(std::shared_ptr<FolioDelegate> delegate);
void deleteGhostEntry();
// the index that dropping at the position given would place the delegate at.

View file

@ -13,7 +13,7 @@ FolioDelegate::FolioDelegate(HomeScreen *parent)
{
}
FolioDelegate::FolioDelegate(FolioApplication *application, HomeScreen *parent)
FolioDelegate::FolioDelegate(FolioApplication::Ptr application, HomeScreen *parent)
: QObject{parent}
, m_type{FolioDelegate::Application}
, m_application{application}
@ -22,7 +22,7 @@ FolioDelegate::FolioDelegate(FolioApplication *application, HomeScreen *parent)
{
}
FolioDelegate::FolioDelegate(FolioApplicationFolder *folder, HomeScreen *parent)
FolioDelegate::FolioDelegate(FolioApplicationFolder::Ptr folder, HomeScreen *parent)
: QObject{parent}
, m_type{FolioDelegate::Folder}
, m_application{nullptr}
@ -31,7 +31,7 @@ FolioDelegate::FolioDelegate(FolioApplicationFolder *folder, HomeScreen *parent)
{
}
FolioDelegate::FolioDelegate(FolioWidget *widget, HomeScreen *parent)
FolioDelegate::FolioDelegate(FolioWidget::Ptr widget, HomeScreen *parent)
: QObject{parent}
, m_type{FolioDelegate::Widget}
, m_application{nullptr}
@ -40,34 +40,34 @@ FolioDelegate::FolioDelegate(FolioWidget *widget, HomeScreen *parent)
{
}
FolioDelegate *FolioDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
FolioDelegate::Ptr FolioDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
{
const QString type = obj[QStringLiteral("type")].toString();
if (type == "application") {
// read application
FolioApplication *app = FolioApplication::fromJson(obj, parent);
FolioApplication::Ptr app = FolioApplication::fromJson(obj, parent);
if (app) {
return new FolioDelegate{app, parent};
return std::make_shared<FolioDelegate>(app, parent);
}
} else if (type == "folder") {
// read folder
FolioApplicationFolder *folder = FolioApplicationFolder::fromJson(obj, parent);
FolioApplicationFolder::Ptr folder = FolioApplicationFolder::fromJson(obj, parent);
if (folder) {
return new FolioDelegate{folder, parent};
return std::make_shared<FolioDelegate>(folder, parent);
}
} else if (type == "widget") {
// read widget
FolioWidget *widget = FolioWidget::fromJson(obj, parent);
FolioWidget::Ptr widget = FolioWidget::fromJson(obj, parent);
if (widget) {
return new FolioDelegate{widget, parent};
return std::make_shared<FolioDelegate>(widget, parent);
}
} else if (type == "none") {
return new FolioDelegate{parent};
return std::make_shared<FolioDelegate>(parent);
}
return nullptr;
@ -93,26 +93,41 @@ QJsonObject FolioDelegate::toJson() const
return QJsonObject{};
}
FolioDelegate::Type FolioDelegate::type()
FolioDelegate::Type FolioDelegate::type() const
{
return m_type;
}
FolioApplication *FolioDelegate::application()
FolioApplication::Ptr FolioDelegate::application()
{
return m_application;
}
FolioApplicationFolder *FolioDelegate::folder()
FolioApplication *FolioDelegate::applicationRaw()
{
return m_application.get();
}
FolioApplicationFolder::Ptr FolioDelegate::folder()
{
return m_folder;
}
FolioWidget *FolioDelegate::widget()
FolioApplicationFolder *FolioDelegate::folderRaw()
{
return m_folder.get();
}
FolioWidget::Ptr FolioDelegate::widget()
{
return m_widget;
}
FolioWidget *FolioDelegate::widgetRaw()
{
return m_widget.get();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, HomeScreen *parent)
: FolioDelegate{parent}
, m_homeScreen{parent}
@ -122,7 +137,7 @@ FolioPageDelegate::FolioPageDelegate(int row, int column, HomeScreen *parent)
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplication *application, HomeScreen *parent)
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplication::Ptr application, HomeScreen *parent)
: FolioDelegate{application, parent}
, m_homeScreen{parent}
, m_row{row}
@ -131,7 +146,7 @@ FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplication *appl
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplicationFolder *folder, HomeScreen *parent)
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplicationFolder::Ptr folder, HomeScreen *parent)
: FolioDelegate{folder, parent}
, m_homeScreen{parent}
, m_row{row}
@ -140,7 +155,7 @@ FolioPageDelegate::FolioPageDelegate(int row, int column, FolioApplicationFolder
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioWidget *widget, HomeScreen *parent)
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioWidget::Ptr widget, HomeScreen *parent)
: FolioDelegate{widget, parent}
, m_homeScreen{parent}
, m_row{row}
@ -149,7 +164,7 @@ FolioPageDelegate::FolioPageDelegate(int row, int column, FolioWidget *widget, H
init();
}
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioDelegate *delegate, HomeScreen *parent)
FolioPageDelegate::FolioPageDelegate(int row, int column, FolioDelegate::Ptr delegate, HomeScreen *parent)
: FolioDelegate{parent}
, m_homeScreen{parent}
, m_row{row}
@ -207,21 +222,21 @@ void FolioPageDelegate::init()
}
if (m_widget) {
connect(m_widget, &FolioWidget::realTopLeftPositionChanged, this, [this](int rowOffset, int columnOffset) {
connect(m_widget.get(), &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));
setRowOnly(getTranslatedTopLeftRow(m_homeScreen, m_realRow, m_realColumn, this->shared_from_this()));
setColumnOnly(getTranslatedTopLeftColumn(m_homeScreen, m_realRow, m_realColumn, this->shared_from_this()));
});
}
FolioPageDelegate *FolioPageDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
FolioPageDelegate::Ptr FolioPageDelegate::fromJson(QJsonObject &obj, HomeScreen *parent)
{
FolioDelegate *fd = FolioDelegate::fromJson(obj, parent);
FolioDelegate::Ptr fd = FolioDelegate::fromJson(obj, parent);
if (!fd) {
return nullptr;
@ -233,13 +248,13 @@ FolioPageDelegate *FolioPageDelegate::fromJson(QJsonObject &obj, HomeScreen *par
int row = getTranslatedTopLeftRow(parent, realRow, realColumn, fd);
int column = getTranslatedTopLeftColumn(parent, realRow, realColumn, fd);
FolioPageDelegate *delegate = new FolioPageDelegate{row, column, fd, parent};
FolioPageDelegate::Ptr delegate = std::make_shared<FolioPageDelegate>(row, column, fd, parent);
fd->deleteLater();
return delegate;
}
int FolioPageDelegate::getTranslatedTopLeftRow(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd)
int FolioPageDelegate::getTranslatedTopLeftRow(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate::Ptr fd)
{
int row = getTranslatedRow(homeScreen, realRow, realColumn);
int column = getTranslatedColumn(homeScreen, realRow, realColumn);
@ -252,7 +267,7 @@ int FolioPageDelegate::getTranslatedTopLeftRow(HomeScreen *homeScreen, int realR
}
}
int FolioPageDelegate::getTranslatedTopLeftColumn(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate *fd)
int FolioPageDelegate::getTranslatedTopLeftColumn(HomeScreen *homeScreen, int realRow, int realColumn, FolioDelegate::Ptr fd)
{
int row = getTranslatedRow(homeScreen, realRow, realColumn);
int column = getTranslatedColumn(homeScreen, realRow, realColumn);
@ -386,3 +401,8 @@ void FolioPageDelegate::setColumnOnly(int column)
Q_EMIT columnChanged();
}
}
std::shared_ptr<FolioPageDelegate> FolioPageDelegate::sharedPageDelegate()
{
return static_pointer_cast<FolioPageDelegate>(shared_from_this());
}

View file

@ -15,15 +15,17 @@ class FolioApplication;
class FolioApplicationFolder;
class FolioWidget;
class FolioDelegate : public QObject
class FolioDelegate : public QObject, public std::enable_shared_from_this<FolioDelegate>
{
Q_OBJECT
Q_PROPERTY(FolioDelegate::Type type READ type CONSTANT)
Q_PROPERTY(FolioApplication *application READ application CONSTANT)
Q_PROPERTY(FolioApplicationFolder *folder READ folder CONSTANT)
Q_PROPERTY(FolioWidget *widget READ widget CONSTANT)
Q_PROPERTY(FolioApplication *application READ applicationRaw CONSTANT)
Q_PROPERTY(FolioApplicationFolder *folder READ folderRaw CONSTANT)
Q_PROPERTY(FolioWidget *widget READ widgetRaw CONSTANT)
public:
typedef std::shared_ptr<FolioDelegate> Ptr;
enum Type {
None,
Application,
@ -32,25 +34,31 @@ public:
};
Q_ENUM(Type)
FolioDelegate(HomeScreen *parent = nullptr);
FolioDelegate(FolioApplication *application, HomeScreen *parent);
FolioDelegate(FolioApplicationFolder *folder, HomeScreen *parent);
FolioDelegate(FolioWidget *widget, HomeScreen *parent);
FolioDelegate(HomeScreen *parent);
FolioDelegate(std::shared_ptr<FolioApplication> application, HomeScreen *parent);
FolioDelegate(std::shared_ptr<FolioApplicationFolder> folder, HomeScreen *parent);
FolioDelegate(std::shared_ptr<FolioWidget> widget, HomeScreen *parent);
static FolioDelegate *fromJson(QJsonObject &obj, HomeScreen *parent);
static std::shared_ptr<FolioDelegate> fromJson(QJsonObject &obj, HomeScreen *parent);
virtual QJsonObject toJson() const;
FolioDelegate::Type type();
FolioApplication *application();
FolioApplicationFolder *folder();
FolioWidget *widget();
FolioDelegate::Type type() const;
std::shared_ptr<FolioApplication> application();
FolioApplication *applicationRaw();
std::shared_ptr<FolioApplicationFolder> folder();
FolioApplicationFolder *folderRaw();
std::shared_ptr<FolioWidget> widget();
FolioWidget *widgetRaw();
protected:
FolioDelegate::Type m_type;
FolioApplication *m_application{nullptr};
FolioApplicationFolder *m_folder{nullptr};
FolioWidget *m_widget{nullptr};
std::shared_ptr<FolioApplication> m_application{nullptr};
std::shared_ptr<FolioApplicationFolder> m_folder{nullptr};
std::shared_ptr<FolioWidget> m_widget{nullptr};
};
class FolioPageDelegate : public FolioDelegate
@ -61,15 +69,17 @@ class FolioPageDelegate : public FolioDelegate
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);
typedef std::shared_ptr<FolioPageDelegate> Ptr;
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);
FolioPageDelegate(int row = 0, int column = 0, HomeScreen *parent = nullptr);
FolioPageDelegate(int row, int column, std::shared_ptr<FolioApplication> application, HomeScreen *parent);
FolioPageDelegate(int row, int column, std::shared_ptr<FolioApplicationFolder> folder, HomeScreen *parent);
FolioPageDelegate(int row, int column, std::shared_ptr<FolioWidget> widget, HomeScreen *parent);
FolioPageDelegate(int row, int column, std::shared_ptr<FolioDelegate> delegate, HomeScreen *parent);
static std::shared_ptr<FolioPageDelegate> fromJson(QJsonObject &obj, HomeScreen *parent);
static int getTranslatedTopLeftRow(HomeScreen *homeScreen, int realRow, int realColumn, std::shared_ptr<FolioDelegate> fd);
static int getTranslatedTopLeftColumn(HomeScreen *homeScreen, int realRow, int realColumn, std::shared_ptr<FolioDelegate> fd);
static int getTranslatedRow(HomeScreen *homeScreen, int realRow, int realColumn);
static int getTranslatedColumn(HomeScreen *homeScreen, int realRow, int realColumn);
@ -81,6 +91,8 @@ public:
int column();
void setColumn(int column);
std::shared_ptr<FolioPageDelegate> sharedPageDelegate();
Q_SIGNALS:
void rowChanged();
void columnChanged();

View file

@ -51,12 +51,12 @@ void FolioWidget::init()
});
}
FolioWidget *FolioWidget::fromJson(QJsonObject &obj, HomeScreen *parent)
FolioWidget::Ptr FolioWidget::fromJson(QJsonObject &obj, HomeScreen *parent)
{
int id = obj[QStringLiteral("id")].toInt();
int gridWidth = obj[QStringLiteral("gridWidth")].toInt();
int gridHeight = obj[QStringLiteral("gridHeight")].toInt();
return new FolioWidget(parent, id, gridWidth, gridHeight);
return std::make_shared<FolioWidget>(parent, id, gridWidth, gridHeight);
}
QJsonObject FolioWidget::toJson() const
@ -208,7 +208,7 @@ bool FolioWidget::isInBounds(int widgetRow, int widgetColumn, int row, int colum
return (row >= widgetRow) && (row <= widgetRow + gridHeight() - 1) && (column >= widgetColumn) && (column <= widgetColumn + gridWidth() - 1);
}
bool FolioWidget::overlapsWidget(int widgetRow, int widgetColumn, FolioWidget *otherWidget, int otherWidgetRow, int otherWidgetColumn)
bool FolioWidget::overlapsWidget(int widgetRow, int widgetColumn, FolioWidget::Ptr otherWidget, int otherWidgetRow, int otherWidgetColumn)
{
if (!otherWidget) {
return false;

View file

@ -22,7 +22,7 @@ public:
/**
* @short Object that represents a widget on the homescreen.
*/
class FolioWidget : public QObject
class FolioWidget : public QObject, public std::enable_shared_from_this<FolioWidget>
{
Q_OBJECT
Q_PROPERTY(int id READ id NOTIFY idChanged)
@ -32,10 +32,12 @@ class FolioWidget : public QObject
Q_PROPERTY(PlasmaQuick::AppletQuickItem *visualApplet READ visualApplet NOTIFY visualAppletChanged)
public:
typedef std::shared_ptr<FolioWidget> Ptr;
FolioWidget(HomeScreen *parent = nullptr, int id = -1, int gridWidth = 0, int gridHeight = 0);
FolioWidget(HomeScreen *parent, Plasma::Applet *applet, int gridWidth, int gridHeight);
static FolioWidget *fromJson(QJsonObject &obj, HomeScreen *parent);
static std::shared_ptr<FolioWidget> fromJson(QJsonObject &obj, HomeScreen *parent);
QJsonObject toJson() const;
int id() const;
@ -59,7 +61,7 @@ public:
// query whether (row, column) is inside this widget, if it was at position (widgetRow, widgetColumn)
bool isInBounds(int widgetRow, int widgetColumn, int row, int column);
bool overlapsWidget(int widgetRow, int widgetColumn, FolioWidget *otherWidget, int otherWidgetRow, int otherWidgetColumn);
bool overlapsWidget(int widgetRow, int widgetColumn, std::shared_ptr<FolioWidget> otherWidget, int otherWidgetRow, int otherWidgetColumn);
Plasma::Applet *applet() const;
void setApplet(Plasma::Applet *applet);

View file

@ -517,12 +517,17 @@ void HomeScreenState::setFolderOpenProgress(qreal folderOpenProgress)
}
}
FolioApplicationFolder *HomeScreenState::currentFolder() const
FolioApplicationFolder::Ptr HomeScreenState::currentFolder() const
{
return m_currentFolder;
}
void HomeScreenState::setCurrentFolder(FolioApplicationFolder *folder)
FolioApplicationFolder *HomeScreenState::currentFolderRaw() const
{
return m_currentFolder.get();
}
void HomeScreenState::setCurrentFolder(FolioApplicationFolder::Ptr folder)
{
if (m_currentFolder != folder) {
m_currentFolder = folder;
@ -662,17 +667,17 @@ FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
return nullptr;
}
FolioDelegate *delegate = pageModel->getDelegate(row, column);
FolioDelegate::Ptr delegate = pageModel->getDelegate(row, column);
if (!delegate) {
return nullptr;
}
return delegate;
return delegate.get();
}
FolioDelegate *HomeScreenState::getFavouritesDelegateAt(int position)
{
return m_homeScreen->favouritesModel()->getEntryAt(position);
return m_homeScreen->favouritesModel()->getEntryAt(position).get();
}
FolioDelegate *HomeScreenState::getFolderDelegateAt(int position)
@ -681,7 +686,7 @@ FolioDelegate *HomeScreenState::getFolderDelegateAt(int position)
return nullptr;
}
return m_currentFolder->applications()->getDelegate(position);
return m_currentFolder->applications()->getDelegate(position).get();
}
QPointF HomeScreenState::getPageDelegateScreenPosition(int page, int row, int column)
@ -799,7 +804,7 @@ void HomeScreenState::goToFolderPage(int page, bool snap)
void HomeScreenState::openFolder(qreal delegateX, qreal delegateY, FolioApplicationFolder *folder)
{
setCurrentFolder(folder);
setCurrentFolder(folder->shared_from_this());
m_openFolderAnim->stop();
m_closeFolderAnim->stop();

View file

@ -60,7 +60,7 @@ class HomeScreenState : public QObject
Q_PROPERTY(qreal folderPageContentWidth READ folderPageContentWidth WRITE setFolderPageContentWidth NOTIFY folderPageContentWidthChanged)
Q_PROPERTY(qreal folderPageContentHeight READ folderPageContentHeight WRITE setFolderPageContentHeight NOTIFY folderPageContentHeightChanged)
Q_PROPERTY(qreal folderOpenProgress READ folderOpenProgress WRITE setFolderOpenProgress NOTIFY folderOpenProgressChanged)
Q_PROPERTY(FolioApplicationFolder *currentFolder READ currentFolder NOTIFY currentFolderChanged)
Q_PROPERTY(FolioApplicationFolder *currentFolder READ currentFolderRaw NOTIFY currentFolderChanged)
Q_PROPERTY(qreal folderGridLength READ folderGridLength NOTIFY folderGridLengthChanged)
Q_PROPERTY(qreal settingsOpenProgress READ settingsOpenProgress WRITE setSettingsOpenProgress NOTIFY settingsOpenProgressChanged)
@ -208,8 +208,9 @@ public:
int folderGridLength() const;
void calculateFolderGridLength();
FolioApplicationFolder *currentFolder() const;
void setCurrentFolder(FolioApplicationFolder *folder);
std::shared_ptr<FolioApplicationFolder> currentFolder() const;
FolioApplicationFolder *currentFolderRaw() const;
void setCurrentFolder(std::shared_ptr<FolioApplicationFolder> folder);
// the progress for the opening of the settings view
qreal settingsOpenProgress();
@ -389,7 +390,7 @@ private:
qreal m_folderPageContentWidth{0};
qreal m_folderPageContentHeight{0};
qreal m_folderOpenProgress{0};
FolioApplicationFolder *m_currentFolder{nullptr};
std::shared_ptr<FolioApplicationFolder> m_currentFolder{nullptr};
int m_folderGridLength{0};
qreal m_settingsOpenProgress{0};

View file

@ -6,7 +6,7 @@
#include "homescreenstate.h"
#include "widgetsmanager.h"
PageModel::PageModel(QList<FolioPageDelegate *> delegates, QObject *parent, HomeScreen *homeScreen)
PageModel::PageModel(QList<FolioPageDelegate::Ptr> delegates, QObject *parent, HomeScreen *homeScreen)
: QAbstractListModel{parent}
, m_homeScreen{homeScreen}
, m_delegates{delegates}
@ -15,7 +15,7 @@ PageModel::PageModel(QList<FolioPageDelegate *> delegates, QObject *parent, Home
if (applet) {
// delete any instance of this widget
for (int i = 0; i < m_delegates.size(); i++) {
auto *delegate = m_delegates[i];
FolioPageDelegate::Ptr delegate = m_delegates[i];
if (delegate->type() == FolioDelegate::Widget && delegate->widget()->applet() == applet) {
removeDelegate(i);
break;
@ -29,12 +29,12 @@ PageModel::~PageModel() = default;
PageModel *PageModel::fromJson(QJsonArray &arr, QObject *parent, HomeScreen *homeScreen)
{
QList<FolioPageDelegate *> delegates;
QList<FolioPageDelegate::Ptr> delegates;
for (QJsonValueRef r : arr) {
QJsonObject obj = r.toObject();
FolioPageDelegate *delegate = FolioPageDelegate::fromJson(obj, homeScreen);
FolioPageDelegate::Ptr delegate = FolioPageDelegate::fromJson(obj, homeScreen);
if (delegate) {
delegates.append(delegate);
}
@ -43,7 +43,7 @@ PageModel *PageModel::fromJson(QJsonArray &arr, QObject *parent, HomeScreen *hom
PageModel *model = new PageModel{delegates, parent, homeScreen};
// ensure delegates can request saves
for (auto *delegate : delegates) {
for (FolioPageDelegate::Ptr delegate : delegates) {
model->connectSaveRequests(delegate);
}
@ -54,7 +54,7 @@ QJsonArray PageModel::toJson() const
{
QJsonArray arr;
for (FolioPageDelegate *delegate : m_delegates) {
for (FolioPageDelegate::Ptr delegate : m_delegates) {
if (!delegate) {
continue;
}
@ -79,7 +79,7 @@ QVariant PageModel::data(const QModelIndex &index, int role) const
switch (role) {
case DelegateRole:
return QVariant::fromValue(m_delegates.at(index.row()));
return QVariant::fromValue(m_delegates.at(index.row()).get());
}
return QVariant();
@ -136,7 +136,7 @@ bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate)
}
// check if any delegate exists at any of the spots where the widget is being added
for (FolioPageDelegate *d : m_delegates) {
for (FolioPageDelegate::Ptr d : m_delegates) {
if (delegate->widget()->isInBounds(row, column, d->row(), d->column())) {
return false;
} else if (d->type() == FolioDelegate::Widget) {
@ -151,7 +151,7 @@ bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate)
// inserting app or folder...
// check if there already exists a delegate in this space
for (FolioPageDelegate *d : m_delegates) {
for (FolioPageDelegate::Ptr d : m_delegates) {
if (d->row() == row && d->column() == column) {
return false;
} else if (d->type() == FolioDelegate::Widget && d->widget()->isInBounds(d->row(), d->column(), row, column)) {
@ -163,9 +163,9 @@ bool PageModel::canAddDelegate(int row, int column, FolioDelegate *delegate)
return true;
}
bool PageModel::addDelegate(FolioPageDelegate *delegate)
bool PageModel::addDelegate(FolioPageDelegate::Ptr delegate)
{
if (!canAddDelegate(delegate->row(), delegate->column(), delegate)) {
if (!canAddDelegate(delegate->row(), delegate->column(), delegate.get())) {
return false;
}
@ -180,9 +180,9 @@ bool PageModel::addDelegate(FolioPageDelegate *delegate)
return true;
}
FolioPageDelegate *PageModel::getDelegate(int row, int col)
FolioPageDelegate::Ptr PageModel::getDelegate(int row, int col)
{
for (FolioPageDelegate *d : m_delegates) {
for (FolioPageDelegate::Ptr d : m_delegates) {
if (d->row() == row && d->column() == col) {
return d;
}
@ -207,23 +207,21 @@ void PageModel::moveAndResizeWidgetDelegate(FolioPageDelegate *delegate, int new
return;
}
// test if we can add the delegate with new size and position
FolioWidget *testWidget = new FolioWidget(m_homeScreen, 0, 0, 0);
// we have to use setGridWidth and setGridHeight since it takes into account the page orientation
// Test if we can add the delegate with new size and position
FolioWidget::Ptr testWidget = std::make_shared<FolioWidget>(m_homeScreen, 0, 0, 0);
// We have to use setGridWidth and setGridHeight since it takes into account the page orientation
testWidget->setGridWidth(newGridWidth);
testWidget->setGridHeight(newGridHeight);
FolioDelegate *testDelegate = new FolioDelegate(testWidget, m_homeScreen);
FolioDelegate::Ptr testDelegate = std::make_shared<FolioDelegate>(testWidget, m_homeScreen);
// testWidget and testDelegate will get cleaned up automatically since are smart pointers
// NOT THREAD SAFE!
// which is fine, because the GUI isn't multithreaded
int index = m_delegates.indexOf(delegate);
int index = m_delegates.indexOf(delegate->sharedPageDelegate());
m_delegates.remove(index); // remove the delegate temporarily, since we don't want it to check overlapping of itself
bool canAdd = canAddDelegate(newRow, newColumn, testDelegate);
m_delegates.insert(index, delegate); // add it back
// cleanup test delegate
testDelegate->deleteLater();
testWidget->deleteLater();
bool canAdd = canAddDelegate(newRow, newColumn, testDelegate.get());
m_delegates.insert(index, delegate->sharedPageDelegate()); // add it back
if (!canAdd) {
return;
@ -240,12 +238,12 @@ bool PageModel::isPageEmpty()
return m_delegates.size() == 0;
}
void PageModel::connectSaveRequests(FolioDelegate *delegate)
void PageModel::connectSaveRequests(FolioDelegate::Ptr delegate)
{
if (delegate->type() == FolioDelegate::Folder && delegate->folder()) {
connect(delegate->folder(), &FolioApplicationFolder::saveRequested, this, &PageModel::save);
connect(delegate->folder().get(), &FolioApplicationFolder::saveRequested, this, &PageModel::save);
} else if (delegate->type() == FolioDelegate::Widget && delegate->widget()) {
connect(delegate->widget(), &FolioWidget::saveRequested, this, &PageModel::save);
connect(delegate->widget().get(), &FolioWidget::saveRequested, this, &PageModel::save);
}
}

View file

@ -29,7 +29,9 @@ public:
ShownRole,
};
PageModel(QList<FolioPageDelegate *> delegates = QList<FolioPageDelegate *>{}, QObject *parent = nullptr, HomeScreen *m_homeScreen = nullptr);
PageModel(QList<std::shared_ptr<FolioPageDelegate>> delegates = QList<std::shared_ptr<FolioPageDelegate>>{},
QObject *parent = nullptr,
HomeScreen *m_homeScreen = nullptr);
~PageModel();
static PageModel *fromJson(QJsonArray &arr, QObject *parent, HomeScreen *homeScreen);
@ -43,8 +45,8 @@ public:
Q_INVOKABLE void removeDelegate(int row, int col);
Q_INVOKABLE void removeDelegate(int index);
Q_INVOKABLE bool canAddDelegate(int row, int column, FolioDelegate *delegate);
bool addDelegate(FolioPageDelegate *delegate);
FolioPageDelegate *getDelegate(int row, int col);
bool addDelegate(std::shared_ptr<FolioPageDelegate> delegate);
std::shared_ptr<FolioPageDelegate> getDelegate(int row, int col);
Q_INVOKABLE void moveAndResizeWidgetDelegate(FolioPageDelegate *delegate, int newRow, int newColumn, int newGridWidth, int newGridHeight);
@ -57,8 +59,8 @@ Q_SIGNALS:
void saveRequested();
private:
void connectSaveRequests(FolioDelegate *delegate);
void connectSaveRequests(std::shared_ptr<FolioDelegate> delegate);
HomeScreen *m_homeScreen{nullptr};
QList<FolioPageDelegate *> m_delegates;
QList<std::shared_ptr<FolioPageDelegate>> m_delegates;
};