Show webfinger if displayName is unknown for an author.
[larjonas-pumpa.git] / src / aswidget.cpp
blobf418848c89d10173fbc422dedcad44ccb55c46ca
1 /*
2 Copyright 2013-2015 Mats Sjöberg
4 This file is part of the Pumpa programme.
6 Pumpa is free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 Pumpa is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pumpa. If not, see <http://www.gnu.org/licenses/>.
20 #include "aswidget.h"
21 #include "activitywidget.h"
22 #include <QScrollBar>
23 #include <QDebug>
25 //------------------------------------------------------------------------------
27 ASWidget::ASWidget(QWidget* parent, int widgetLimit, int purgeWait) :
28 QScrollArea(parent),
29 m_firstTime(true),
30 m_list(NULL),
31 m_asMode(QAS_NULL),
32 m_purgeWait(purgeWait),
33 m_purgeCounter(purgeWait),
34 m_widgetLimit(widgetLimit)
36 m_reuseWidgets = (m_widgetLimit > 0);
38 m_itemLayout = new QVBoxLayout;
39 m_itemLayout->setSpacing(10);
41 m_listContainer = new QWidget;
42 m_listContainer->setLayout(m_itemLayout);
43 m_listContainer->setSizePolicy(QSizePolicy::Ignored,
44 QSizePolicy::Ignored);
46 setWidget(m_listContainer);
47 setWidgetResizable(true);
50 //------------------------------------------------------------------------------
52 void ASWidget::clear() {
53 QLayoutItem* item;
54 while ((item = m_itemLayout->takeAt(0)) != 0) {
55 if (dynamic_cast<QWidgetItem*>(item)) {
56 QWidget* w = item->widget();
57 delete w;
59 delete item;
62 m_firstTime = true;
63 m_itemLayout->addStretch();
66 //------------------------------------------------------------------------------
68 void ASWidget::setEndpoint(QString endpoint, QObject* parent, int asMode) {
69 clear();
70 m_list = initList(endpoint, parent);
72 if (asMode != -1)
73 m_asMode |= asMode;
75 connect(m_list, SIGNAL(changed()),
76 this, SLOT(update()), Qt::UniqueConnection);
77 // connect(m_list, SIGNAL(request(QString, int)),
78 // this, SIGNAL(request(QString, int)), Qt::UniqueConnection);
81 //------------------------------------------------------------------------------
83 void ASWidget::refresh() {
84 int c = count();
85 if (c > 200) c = 200; // Count must be between 0 and 200
87 emit request(QString("%1?count=%2").arg(m_list->url()).arg(c),
88 m_asMode | QAS_UPDATE_ONLY);
91 //------------------------------------------------------------------------------
93 void ASWidget::fetchNewer() {
94 emit request(m_list->prevLink(), m_asMode | QAS_NEWER);
97 //------------------------------------------------------------------------------
99 void ASWidget::fetchOlder(int count) {
100 m_purgeCounter = m_purgeWait;
101 QString nextLink = m_list->nextLink();
102 if (!nextLink.isEmpty()) {
103 if (count != -1)
104 nextLink += QString("&count=%1").arg(count);
105 emit request(nextLink, m_asMode | QAS_OLDER);
109 //------------------------------------------------------------------------------
111 void ASWidget::refreshTimeLabels() {
112 for (int i=0; i<m_itemLayout->count(); i++) {
113 ObjectWidgetWithSignals* ow = widgetAt(i);
114 if (ow)
115 ow->refreshTimeLabels();
117 if (m_purgeCounter > 0) {
118 m_purgeCounter--;
119 #ifdef DEBUG_WIDGETS
120 qDebug() << "purgeCounter" << m_purgeCounter <<
121 (m_list ? m_list->url() : "NULL");
122 #endif
126 //------------------------------------------------------------------------------
128 void ASWidget::keyPressEvent(QKeyEvent* event) {
129 int key = event->key();
131 if (key == Qt::Key_Home || key == Qt::Key_End) {
132 bool home = key==Qt::Key_Home;
133 QScrollBar* sb = verticalScrollBar();
134 sb->setValue(home ? sb->minimum() : sb->maximum());
135 } else {
136 QScrollArea::keyPressEvent(event);
140 //------------------------------------------------------------------------------
142 ObjectWidgetWithSignals* ASWidget::widgetAt(int idx) {
143 QLayoutItem* item = m_itemLayout->itemAt(idx);
145 if (dynamic_cast<QWidgetItem*>(item))
146 return qobject_cast<ObjectWidgetWithSignals*>(item->widget());
148 return NULL;
151 //------------------------------------------------------------------------------
153 QASAbstractObject* ASWidget::objectAt(int idx) {
154 ObjectWidgetWithSignals* ows = widgetAt(idx);
155 if (!ows)
156 return NULL;
158 ActivityWidget* aw = qobject_cast<ActivityWidget*>(ows);
159 if (aw)
160 return aw->activity();
162 ObjectWidget* ow = qobject_cast<ObjectWidget*>(ows);
163 if (ow)
164 return ow->object();
166 return NULL;
169 //------------------------------------------------------------------------------
171 void ASWidget::update() {
173 We assume m_list contains all objects, but new ones might have
174 been added either (or both) to the top or end. Go through from
175 top (newest) to bottom. If the object doesn't exist add it, if it
176 does increment the counter (go further down both in the
177 collection and widget list).
180 int li = 0;
181 int newCount = 0;
182 bool older = false;
183 m_newObjects.clear();
185 for (size_t i=0; i<m_list->size(); i++) {
186 QASAbstractObject* cObj = m_list->at(i);
188 if (cObj->isDeleted())
189 continue;
191 #ifdef DEBUG_TIMELINE
192 qDebug() << "UPDATE: m_list" << i << cObj->apiLink();
193 #endif
195 QASAbstractObject* wObj = objectAt(li);
196 if (wObj == cObj) {
197 li++;
198 older = true;
199 #ifdef DEBUG_TIMELINE
200 qDebug() << "UPDATE EXISTS1";
201 #endif
202 continue;
205 if (m_object_set.contains(cObj)) {
206 #ifdef DEBUG_TIMELINE
207 qDebug() << "UPDATE EXISTS2";
208 #endif
209 continue;
211 m_object_set.insert(cObj);
213 bool doCountAsNew = false;
215 bool doReuse = !older && m_reuseWidgets && (count() > m_widgetLimit) &&
216 m_purgeCounter == 0;
218 if (doReuse) {
219 ObjectWidgetWithSignals* ow = NULL;
220 int idx = m_itemLayout->count();
221 while (!ow && --idx > 0)
222 ow = widgetAt(idx);
224 #ifdef DEBUG_WIDGETS
225 qDebug() << "Reused widget" << idx << li << cObj->apiLink()
226 << m_list->url();
227 #endif
229 QASAbstractObject* obj = ow->asObject();
230 m_itemLayout->removeWidget(ow);
232 m_object_set.remove(obj);
233 m_list->removeObject(obj);
235 #ifdef DEBUG_TIMELINE
236 qDebug() << "UPDATE INSERTED AT" << li << "REUSE";
237 #endif
238 changeWidgetObject(ow, cObj);
239 m_itemLayout->insertWidget(li++, ow);
241 doCountAsNew = countAsNew(cObj);
242 } else {
243 ObjectWidgetWithSignals* ow = createWidget(cObj);
244 doCountAsNew = countAsNew(cObj);
245 ObjectWidgetWithSignals::connectSignals(ow, this);
247 #ifdef DEBUG_TIMELINE
248 qDebug() << "UPDATE INSERTED AT" << li << "NEW";
249 #endif
250 m_itemLayout->insertWidget(li++, ow);
252 #ifdef DEBUG_WIDGETS
253 qDebug() << "Created widget" << cObj->apiLink() << m_list->url();
254 #endif
257 if (!m_firstTime && doCountAsNew && !older) {
258 newCount++;
259 m_newObjects.push_back(cObj);
263 if (newCount && !m_firstTime)
264 emit hasNewObjects();
266 if (newCount && !isVisible() && !m_firstTime)
267 emit highlightMe();
268 m_firstTime = false;
271 //------------------------------------------------------------------------------
273 void ASWidget::changeWidgetObject(ObjectWidgetWithSignals* ow,
274 QASAbstractObject* obj) {
275 ow->changeObject(obj);
278 //------------------------------------------------------------------------------
280 ObjectWidgetWithSignals* ASWidget::createWidget(QASAbstractObject*) {
281 return NULL;
284 //------------------------------------------------------------------------------
286 QASAbstractObjectList* ASWidget::initList(QString, QObject*) {
287 return NULL;
290 //------------------------------------------------------------------------------
292 void ASWidget::refreshObject(QASAbstractObject* obj) {
293 if (!obj)
294 return;
296 QDateTime now = QDateTime::currentDateTime();
297 QDateTime lr = obj->lastRefreshed();
299 if (lr.isNull() || lr.secsTo(now) > 10) {
300 obj->lastRefreshed(now);
301 emit request(obj->apiLink(), obj->asType());