aboutsummaryrefslogtreecommitdiff
path: root/src/favouritecollection.hpp
blob: abc40b10ad9f807466c700b4d41f5170aef6ad14 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#ifndef FAVOURITECOLLECTION_HPP
#define FAVOURITECOLLECTION_HPP

#include <QAbstractItemModel>
#include <QUrl>
#include <QString>
#include <memory>
#include <QSettings>

struct Favourite
{
    QString title;
    QUrl destination;

    bool isValid() const {
        return destination.isValid();
    }

    QString getTitle() const {
        if(title.isEmpty())
            return destination.toString(QUrl::FullyEncoded);
        else
            return title;
    }
};

class FavouriteCollection : public QAbstractItemModel
{
    Q_OBJECT
    struct Node  {
        enum Type { Root, Group, Favourite };
        Node * parent = nullptr;
        int index = 0;
        std::vector<std::unique_ptr<Node>> children;
        Type type;
        explicit Node(Type t) : type(t) { }
        Node(Node const &) = delete;
        Node(Node &&) = delete;
        virtual ~Node() = default;

        template<typename T>
        T & as() { return *static_cast<T*>(this); }

        template<typename T>
        T const & as() const { return *static_cast<T const*>(this); }
    };

    struct FavouriteNode : Node {
        ::Favourite favourite;
        FavouriteNode() : Node(Favourite) { }
        FavouriteNode(FavouriteNode const &) = delete;
        FavouriteNode(FavouriteNode &&) = delete;
        ~FavouriteNode() override = default;
    };

    struct GroupNode : Node {
        QString title;
        GroupNode() : Node(Group) { }
        GroupNode(GroupNode const &) = delete;
        GroupNode(GroupNode &&) = delete;
        ~GroupNode() override = default;
    };

    struct RootNode : Node {
        RootNode() : Node(Root) { }
        RootNode(RootNode const &) = delete;
        RootNode(RootNode &&) = delete;
        ~RootNode() override = default;
    };

public:
    explicit FavouriteCollection(QObject *parent = nullptr);

    FavouriteCollection(FavouriteCollection const & other);

    FavouriteCollection(FavouriteCollection && other);

    ~FavouriteCollection();

    FavouriteCollection & operator=(FavouriteCollection const &);
    FavouriteCollection & operator=(FavouriteCollection &&);

public:
    void load(QSettings & settings);

    void save(QSettings & settings) const;

    bool addGroup(QString const & group);

    bool renameGroup(QString const & old_name, QString const & new_name);

    bool addFavourite(QString const & group, Favourite const & fav);

    void editFavouriteTitle(const QModelIndex &index, const QString &title);
    bool editFavouriteTitle(const QUrl &url, const QString &new_title);

    void editFavouriteDest(const QModelIndex & index, const QUrl & url);

    bool editFavouriteGroup(const QUrl &url, const QString &group_name);

    Favourite getFavourite(const QUrl &url) const;

    Favourite getFavourite(QModelIndex const & index) const;

    Favourite * getMutableFavourite(QModelIndex const & index);

    QString groupForFavourite(QUrl const & url) const;

    QStringList groups() const;

    //! Returns the group name of the index.
    QString group(QModelIndex const & index) const;

    bool destroyFavourite(QModelIndex const & index);

    bool canDeleteGroup(QString const & group_name);
    bool deleteGroup(QString const & group_name);
    bool deleteGroupRecursive(QString const & group_name);

    //! Returns a list of non-mutable references to all contained favourites.
    //! Note that the group will change in-order, so all favourites for group a
    //! will be listed, then all for group b, no intermixing is done.
    QVector<QPair<QString, Favourite const *>> allFavourites() const;

    bool containsUrl(QUrl const & url) const;

    bool addUnsorted(QUrl const & url, QString const & title);

    bool removeUrl(QUrl const & url);

public:
    // Header:
    // QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

    // Basic functionality:
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &index) const override;

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;

    // Drag'n'Drop

    Qt::ItemFlags flags(const QModelIndex &index) const override;

    QStringList mimeTypes() const override;
    QMimeData *mimeData(const QModelIndexList &indexes) const override;
    bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
    Qt::DropActions supportedDropActions() const override;

    Qt::DropActions supportedDragActions() const override;

    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;


private:
    void relayout();

    bool internalAddGroup(QString const & group_name, GroupNode * & out_group);

private:
    RootNode root;
};

#endif // FAVOURITECOLLECTION_HPP