summaryrefslogtreecommitdiff
path: root/src/atomchannel.h
blob: 87727d27c9a2befbed22118605aa65f91022b9a4 (plain)
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
#pragma once

#include <optional>

#include <QDateTime>
#include <QDebug>
#include <QDomDocument>
#include <QList>
#include <QString>
#include <QUrl>

#include "atomchannelimage.h"
#include "atomitem.h"

class QXmlStreamReader;

// TODO: mark items as read in all user channels

#define GADGET_PROPERTY(type, name) \
protected: \
    Q_PROPERTY(const type name READ get_##name WRITE set_##name) \
public: \
    const type &get_##name() const \
    { \
        return m_##name; \
    } \
    void set_##name(const type &name) \
    { \
        m_##name = name; \
    } \
\
protected: \
    type m_##name

class DbItem
{
    Q_GADGET

    GADGET_PROPERTY(std::optional<qlonglong>, id);

    static constexpr auto dateFormat = Qt::DateFormat::RFC2822Date;

public:
    explicit DbItem(const QDomNode &node);

public:
    void init(const QMetaObject &mo, const QDomNode &node);
};

class Channel : public DbItem
{
    Q_GADGET

    GADGET_PROPERTY(QString, title);
    GADGET_PROPERTY(QUrl, link);

public:
    explicit Channel(const QDomNode &node);

public:
    bool isValid() const;
};

// TODO: <image>

class Item : public DbItem
{
    Q_GADGET

    GADGET_PROPERTY(QString, title);
    GADGET_PROPERTY(QUrl, link);
    GADGET_PROPERTY(QStringList, categories);
    GADGET_PROPERTY(QString, guid);
    GADGET_PROPERTY(QDateTime, pubDate);
    GADGET_PROPERTY(QString, description);
    GADGET_PROPERTY(QString, content);

public:
    explicit Item(const QDomNode &node);

public:
    bool isValid() const;
};

class AtomChannel
{
public:
    // TODO: move to interface
    static inline const QString xmlTag{"channel"};

public:
    explicit AtomChannel(QXmlStreamReader *xmlReader);

public:
    // TODO: update db data if differs. here and everywhere (item, user, etc)
    /*!
     * \brief getDbId - check if channel with corresponding `link` exists in db
     * and return db id if any
     * \return id on success, 0 otherwise
     */
    std::optional<int> getDbId();

    /*!
     * \brief createInDb - create channel in db
     * \return new channel id on success, 0 otherwise
     */
    std::optional<int> createInDb();

    /*!
     * \brief getOrInsertDbId - get existing channel id or try to create a new
     * channel and get its id
     * \return existing or new channel id on success, 0 otherwise
     */
    std::optional<int> getOrInsertDbId();

    /*!
     * \brief syncDbItems - create items in db if not exist
     * \return list of new items ids
     */
    QList<int> syncDbItems();

public:
    /*!
     * \brief m_id - cache db m_id
     */
    std::optional<int> m_id{0};

    QString title;
    /*!
     * \brief link - field called `link` in atom xml. Points to feed itself
     */
    QUrl link;
    QString description;
    QDateTime lastBuildDate;
    QLocale::Language language;
    // ...
    // TODO: shared_ptr
    AtomChannelImage image;
    QList<AtomItem> items;
};

QDebug operator<<(QDebug debug, const AtomChannel &channel);
QDebug operator<<(QDebug debug, const Channel &channel);
QDebug operator<<(QDebug debug, const Item &item);