File indexing completed on 2024-12-29 05:06:03

0001 // SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 #pragma once
0005 
0006 #include <QObject>
0007 
0008 #include <QAbstractListModel>
0009 #include <QList>
0010 #include <QObject>
0011 #include <QQuickItem>
0012 #include <QSet>
0013 
0014 #include <Plasma/Containment>
0015 
0016 #include "foliodelegate.h"
0017 
0018 struct FavouritesDelegate {
0019     FolioDelegate *delegate;
0020     qreal xPosition;
0021 };
0022 
0023 class FavouritesModel : public QAbstractListModel
0024 {
0025     Q_OBJECT
0026 
0027 public:
0028     enum Roles {
0029         DelegateRole = Qt::UserRole + 1,
0030         XPositionRole,
0031     };
0032 
0033     FavouritesModel(QObject *parent = nullptr);
0034     static FavouritesModel *self();
0035 
0036     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0037     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0038     QHash<int, QByteArray> roleNames() const override;
0039 
0040     Q_INVOKABLE void removeEntry(int row);
0041     void moveEntry(int fromRow, int toRow);
0042     bool canAddEntry(int row, FolioDelegate *delegate);
0043     bool addEntry(int row, FolioDelegate *delegate);
0044     FolioDelegate *getEntryAt(int row);
0045 
0046     // for use with drag and drop, as the delegate is dragged around
0047     // ghost - fake delegate exists at an index, so a gap is created
0048     // invisible - existing delegate looks like it doesn't exist
0049     int getGhostEntryPosition();
0050     void setGhostEntry(int row);
0051     void replaceGhostEntry(FolioDelegate *delegate);
0052     void deleteGhostEntry();
0053 
0054     // whether the position given is in between 2 delegates, or at the edge.
0055     // this would return false if dropping should place the delegate into a folder/create a folder.
0056     bool dropPositionIsEdge(qreal x, qreal y) const;
0057 
0058     // the index that dropping at the position given would place the delegate at.
0059     int dropInsertPosition(qreal x, qreal y) const;
0060 
0061     QPointF getDelegateScreenPosition(int position) const;
0062 
0063     QJsonArray exportToJson();
0064     void save();
0065     Q_INVOKABLE void load();
0066     void loadFromJson(QJsonArray arr);
0067 
0068     void setContainment(Plasma::Containment *containment);
0069 
0070 private:
0071     void connectSaveRequests(FolioDelegate *delegate);
0072     void evaluateDelegatePositions(bool emitSignal = true);
0073 
0074     // get the x (or y) position where delegates start being placed
0075     qreal getDelegateRowStartPos() const;
0076 
0077     // adjusts the index in relation to the page orientation
0078     // this is so that we only have to calculate positions assuming one orientation
0079     int adjustIndex(int index) const;
0080 
0081     QList<FavouritesDelegate> m_delegates;
0082 
0083     Plasma::Containment *m_containment{nullptr};
0084 };