KNewStuff

downloadwidget.cpp
1 /*
2  knewstuff3/ui/downloaddialog.cpp.
3  SPDX-FileCopyrightText: 2005 Enrico Ros <[email protected]>
4  SPDX-FileCopyrightText: 2005-2007 Josef Spillner <[email protected]>
5  SPDX-FileCopyrightText: 2007 Dirk Mueller <[email protected]>
6  SPDX-FileCopyrightText: 2007-2009 Jeremy Whiting <[email protected]>
7  SPDX-FileCopyrightText: 2009-2010 Frederik Gladhorn <[email protected]>
8  SPDX-FileCopyrightText: 2010 Reza Fatahilah Shah <[email protected]>
9 
10  SPDX-License-Identifier: LGPL-2.1-or-later
11 */
12 
13 #include "downloadwidget.h"
14 #include "downloadwidget_p.h"
15 
16 #include <QTimer>
17 #include <QScrollBar>
18 #include <QCoreApplication>
19 
20 #include <KMessageBox>
21 #include <KLocalizedString>
22 #include <knewstuff_debug.h>
23 
24 #include "core/itemsmodel.h"
25 
26 #include "ui/itemsviewdelegate_p.h"
27 #include "ui/itemsgridviewdelegate_p.h"
28 #include "ui/widgetquestionlistener.h"
29 
30 #include "entry_p.h"
31 
32 using namespace KNS3;
33 
35  : QWidget(parent)
36  , d(new DownloadWidgetPrivate(this))
37 {
39  init(name + QStringLiteral(".knsrc"));
40 }
41 
43  : QWidget(parent)
44  , d(new DownloadWidgetPrivate(this))
45 {
46  init(configFile);
47 }
48 
49 void DownloadWidget::init(const QString &configFile)
50 {
51  d->init(configFile);
52  WidgetQuestionListener::instance();
53 }
54 
56 {
57  delete d;
58 }
59 
61 {
62  d->ui.m_titleWidget->setText(title);
63 }
64 
66 {
67  return d->ui.m_titleWidget->text();
68 }
69 
71 {
72  return d->engine;
73 }
74 
76 {
77  Entry::List entries;
78  entries.reserve(d->changedEntries.count());
79  for (const KNSCore::EntryInternal &e : qAsConst(d->changedEntries)) {
80  entries.append(EntryPrivate::fromInternal(&e));
81  }
82  return entries;
83 }
84 
86 {
87  Entry::List entries;
88  for (const KNSCore::EntryInternal &e : qAsConst(d->changedEntries)) {
89  if (e.status() == Entry::Installed) {
90  entries.append(EntryPrivate::fromInternal(&e));
91  }
92  }
93  return entries;
94 }
95 
96 DownloadWidgetPrivate::DownloadWidgetPrivate(DownloadWidget *q)
97  : q(q)
98  , engine(new KNSCore::Engine)
99  , model(new KNSCore::ItemsModel(engine))
100  , messageTimer(nullptr)
101  , dialogMode(false)
102 {
103 }
104 
105 DownloadWidgetPrivate::~DownloadWidgetPrivate()
106 {
107  delete messageTimer;
108  delete delegate;
109  delete model;
110  delete engine;
111 }
112 
113 void DownloadWidgetPrivate::slotResetMessage() // SLOT
114 {
115  ui.m_titleWidget->setComment(QString());
116 }
117 
118 void DownloadWidgetPrivate::slotNetworkTimeout() // SLOT
119 {
120  displayMessage(i18n("Timeout. Check Internet connection."), KTitleWidget::ErrorMessage);
121 }
122 
123 void DownloadWidgetPrivate::sortingChanged()
124 {
125  KNSCore::Provider::SortMode sortMode = KNSCore::Provider::Downloads;
126  KNSCore::Provider::Filter filter = KNSCore::Provider::None;
127  if (ui.ratingRadio->isChecked()) {
128  sortMode = KNSCore::Provider::Rating;
129  } else if (ui.newestRadio->isChecked()) {
130  sortMode = KNSCore::Provider::Newest;
131  } else if (ui.mostDownloadsRadio->isChecked()) {
132  sortMode = KNSCore::Provider::Downloads;
133  } else if (ui.installedRadio->isChecked()) {
134  filter = KNSCore::Provider::Installed;
135  }
136 
137  model->clearEntries();
138  if (filter == KNSCore::Provider::Installed) {
139  ui.m_searchEdit->clear();
140  }
141  ui.m_searchEdit->setEnabled(filter != KNSCore::Provider::Installed);
142 
143  engine->setSortMode(sortMode);
144  engine->setFilter(filter);
145 }
146 
147 void DownloadWidgetPrivate::slotUpdateSearch()
148 {
149  if (searchTerm == ui.m_searchEdit->text().trimmed()) {
150  return;
151  }
152  searchTerm = ui.m_searchEdit->text().trimmed();
153 }
154 
155 void DownloadWidgetPrivate::slotSearchTextChanged()
156 {
157  if (searchTerm == ui.m_searchEdit->text().trimmed()) {
158  return;
159  }
160  searchTerm = ui.m_searchEdit->text().trimmed();
161  engine->setSearchTerm(searchTerm);
162 }
163 
164 void DownloadWidgetPrivate::slotCategoryChanged(int idx)
165 {
166  if (idx == 0) {
167  // All Categories item selected, reset filter
169 
170  } else {
171  const QString category = ui.m_categoryCombo->currentData().toString();
172 
173  if (!category.isEmpty()) {
174  QStringList filter(category);
175  engine->setCategoriesFilter(filter);
176  }
177  }
178 }
179 
180 void DownloadWidgetPrivate::slotInfo(QString provider, QString server, QString version)
181 {
182  QString link = QStringLiteral("<a href=\"%1\">%1</a>").arg(server);
183  QString infostring = i18n("Server: %1", link);
184  infostring += i18n("<br />Provider: %1", provider);
185  infostring += i18n("<br />Version: %1", version);
186 
187  KMessageBox::information(nullptr,
188  infostring,
189  i18n("Provider information"));
190 }
191 
192 void DownloadWidgetPrivate::slotEntryChanged(const KNSCore::EntryInternal &entry)
193 {
194  changedEntries.insert(entry);
195  model->slotEntryChanged(entry);
196 }
197 
198 void DownloadWidgetPrivate::slotPayloadFailed(const KNSCore::EntryInternal &entry)
199 {
200  KMessageBox::error(nullptr, i18n("Could not install %1", entry.name()),
201  i18n("Get Hot New Stuff!"));
202 }
203 
204 void DownloadWidgetPrivate::slotPayloadLoaded(QUrl url)
205 {
206  Q_UNUSED(url)
207 }
208 
209 void DownloadWidgetPrivate::slotError(const QString &message)
210 {
211  KMessageBox::error(nullptr, message, i18n("Get Hot New Stuff"));
212 }
213 
214 void DownloadWidgetPrivate::scrollbarValueChanged(int value)
215 {
216  if (static_cast<double>(value) / ui.m_listView->verticalScrollBar()->maximum() > 0.9) {
217  engine->requestMoreData();
218  }
219 }
220 
221 void DownloadWidgetPrivate::init(const QString &configFile)
222 {
223  m_configFile = configFile;
224  ui.setupUi(q);
225  ui.m_titleWidget->setVisible(false);
226  ui.closeButton->setVisible(dialogMode);
227  ui.backButton->setVisible(false);
228  KStandardGuiItem::assign(ui.backButton, KStandardGuiItem::Back);
229  q->connect(ui.backButton, &QPushButton::clicked, this, &DownloadWidgetPrivate::slotShowOverview);
230 
231  q->connect(engine, &KNSCore::Engine::signalMessage, this, &DownloadWidgetPrivate::slotShowMessage);
232 
233  q->connect(engine, &KNSCore::Engine::signalBusy, ui.progressIndicator, &ProgressIndicator::busy);
234  q->connect(engine, &KNSCore::Engine::signalErrorCode, ui.progressIndicator, &ProgressIndicator::error);
235  q->connect(engine, &KNSCore::Engine::signalIdle, ui.progressIndicator, &ProgressIndicator::idle);
236 
237  q->connect(engine, &KNSCore::Engine::signalProvidersLoaded, this, &DownloadWidgetPrivate::slotProvidersLoaded);
238  // Entries have been fetched and should be shown:
239  q->connect(engine, &KNSCore::Engine::signalEntriesLoaded, this, &DownloadWidgetPrivate::slotEntriesLoaded);
240 
241  // An entry has changes - eg because it was installed
242  q->connect(engine, &KNSCore::Engine::signalEntryChanged, this, &DownloadWidgetPrivate::slotEntryChanged);
243 
244  q->connect(engine, &KNSCore::Engine::signalResetView, model, &KNSCore::ItemsModel::clearEntries);
245  q->connect(engine, &KNSCore::Engine::signalEntryPreviewLoaded,
246  model, &KNSCore::ItemsModel::slotEntryPreviewLoaded);
247 
248  engine->init(configFile);
249  engine->setSortMode(KNSCore::Provider::Downloads);
250 
251  delegate = new ItemsViewDelegate(ui.m_listView, engine, q);
252  ui.m_listView->setItemDelegate(delegate);
253  ui.m_listView->setModel(model);
254 
255  ui.iconViewButton->setIcon(QIcon::fromTheme(QStringLiteral("view-list-icons")));
256  ui.iconViewButton->setToolTip(i18n("Icons view mode"));
257  ui.listViewButton->setIcon(QIcon::fromTheme(QStringLiteral("view-list-details")));
258  ui.listViewButton->setToolTip(i18n("Details view mode"));
259 
260  q->connect(ui.listViewButton, &QPushButton::clicked, this, &DownloadWidgetPrivate::slotListViewListMode);
261  q->connect(ui.iconViewButton, &QPushButton::clicked, this, &DownloadWidgetPrivate::slotListViewIconMode);
262 
263  q->connect(ui.newestRadio, &QRadioButton::clicked, this, &DownloadWidgetPrivate::sortingChanged);
264  q->connect(ui.ratingRadio, &QRadioButton::clicked, this, &DownloadWidgetPrivate::sortingChanged);
265  q->connect(ui.mostDownloadsRadio, &QRadioButton::clicked, this, &DownloadWidgetPrivate::sortingChanged);
266  q->connect(ui.installedRadio, &QRadioButton::clicked, this, &DownloadWidgetPrivate::sortingChanged);
267 
268  q->connect(ui.m_searchEdit, &KLineEdit::textChanged, this, &DownloadWidgetPrivate::slotSearchTextChanged);
269  q->connect(ui.m_searchEdit, &KLineEdit::editingFinished, this, &DownloadWidgetPrivate::slotUpdateSearch);
270 
271  ui.m_providerLabel->setVisible(false);
272  ui.m_providerCombo->setVisible(false);
273  ui.m_providerCombo->addItem(i18n("All Providers"));
274 
275  QStringList categories = engine->categories();
276  if (categories.size() < 2) {
277  ui.m_categoryLabel->setVisible(false);
278  ui.m_categoryCombo->setVisible(false);
279  } else {
280  ui.m_categoryCombo->addItem(i18n("All Categories"));
281  //NOTE: categories will be populated when we will get metadata from the server
282  }
283 
284  connect(engine, &KNSCore::Engine::signalCategoriesMetadataLoded,
285  this, [this](const QList<KNSCore::Provider::CategoryMetadata> &categories) {
286  for (const auto &data : categories) {
287  if (!data.displayName.isEmpty()) {
288  ui.m_categoryCombo->addItem(data.displayName, data.name);
289  } else {
290  ui.m_categoryCombo->addItem(data.name, data.name);
291  }
292  }
293  });
294  ui.detailsStack->widget(0)->layout()->setContentsMargins(0, 0, 0, 0);
295  ui.detailsStack->widget(1)->layout()->setContentsMargins(0, 0, 0, 0);
296 
297  q->connect(ui.m_categoryCombo, static_cast<void(KComboBox::*)(int)>(&KComboBox::activated),
298  this, &DownloadWidgetPrivate::slotCategoryChanged);
299 
300  // let the search line edit trap the enter key, otherwise it closes the dialog
301  ui.m_searchEdit->setTrapReturnKey(true);
302 
303  q->connect(ui.m_listView->verticalScrollBar(), &QScrollBar::valueChanged, this, &DownloadWidgetPrivate::scrollbarValueChanged);
304  q->connect(ui.m_listView, SIGNAL(doubleClicked(QModelIndex)), delegate, SLOT(slotDetailsClicked(QModelIndex)));
305 
306  details = new EntryDetails(engine, &ui);
307  q->connect(delegate, &KNS3::ItemsViewBaseDelegate::signalShowDetails, this, &DownloadWidgetPrivate::slotShowDetails);
308 
309  slotShowOverview();
310 }
311 
312 void DownloadWidgetPrivate::slotListViewListMode()
313 {
314  ui.listViewButton->setChecked(true);
315  ui.iconViewButton->setChecked(false);
316  setListViewMode(QListView::ListMode);
317 }
318 
319 void DownloadWidgetPrivate::slotListViewIconMode()
320 {
321  ui.listViewButton->setChecked(false);
322  ui.iconViewButton->setChecked(true);
323  setListViewMode(QListView::IconMode);
324 }
325 
326 void DownloadWidgetPrivate::setListViewMode(QListView::ViewMode mode)
327 {
328  if (ui.m_listView->viewMode() == mode) {
329  return;
330  }
331 
332  ItemsViewBaseDelegate *oldDelegate = delegate;
333  if (mode == QListView::ListMode) {
334  delegate = new ItemsViewDelegate(ui.m_listView, engine, q);
335  ui.m_listView->setViewMode(QListView::ListMode);
336  ui.m_listView->setResizeMode(QListView::Fixed);
337  } else {
338  delegate = new ItemsGridViewDelegate(ui.m_listView, engine, q);
339  ui.m_listView->setViewMode(QListView::IconMode);
340  ui.m_listView->setResizeMode(QListView::Adjust);
341  }
342  ui.m_listView->setItemDelegate(delegate);
343  delete oldDelegate;
344  q->connect(ui.m_listView, SIGNAL(doubleClicked(QModelIndex)), delegate, SLOT(slotDetailsClicked(QModelIndex)));
345  q->connect(delegate, &KNS3::ItemsViewBaseDelegate::signalShowDetails, this, &DownloadWidgetPrivate::slotShowDetails);
346 }
347 
348 void DownloadWidgetPrivate::slotProvidersLoaded()
349 {
350  qCDebug(KNEWSTUFF) << "providers loaded";
351  engine->reloadEntries();
352 }
353 
354 void DownloadWidgetPrivate::slotEntriesLoaded(const KNSCore::EntryInternal::List &entries)
355 {
356  for (const KNSCore::EntryInternal &entry : entries) {
357  if (!categories.contains(entry.category())) {
358  qCDebug(KNEWSTUFF) << "Found category: " << entry.category();
359  categories.insert(entry.category());
360  }
361  }
362  model->slotEntriesLoaded(entries);
363 }
364 
365 void DownloadWidgetPrivate::slotShowMessage(const QString& msg)
366 {
367  displayMessage(msg, KTitleWidget::InfoMessage);
368 }
369 
370 void DownloadWidgetPrivate::displayMessage(const QString &msg, KTitleWidget::MessageType type, int timeOutMs)
371 {
372  if (!messageTimer) {
373  messageTimer = new QTimer;
374  messageTimer->setSingleShot(true);
375  q->connect(messageTimer, &QTimer::timeout, this, &DownloadWidgetPrivate::slotResetMessage);
376  }
377  // stop the pending timer if present
378  messageTimer->stop();
379 
380  // set text to messageLabel
381  ui.m_titleWidget->setComment(msg, type);
382 
383  // single shot the resetColors timer (and create it if null)
384  if (timeOutMs > 0) {
385  qCDebug(KNEWSTUFF) << "starting the message timer for " << timeOutMs;
386  messageTimer->start(timeOutMs);
387  }
388 }
389 
390 void DownloadWidgetPrivate::slotShowDetails(const KNSCore::EntryInternal &entry)
391 {
392  if (!entry.isValid()) {
393  qCDebug(KNEWSTUFF) << "invalid entry";
394  return;
395  }
396  titleText = ui.m_titleWidget->text();
397 
398  ui.backButton->setVisible(true);
399  ui.detailsStack->setCurrentIndex(1);
400  ui.descriptionScrollArea->verticalScrollBar()->setValue(0);
401  ui.preview1->setImage(QImage());
402  ui.preview2->setImage(QImage());
403  ui.preview3->setImage(QImage());
404  ui.previewBig->setImage(QImage());
405  details->setEntry(entry);
406 }
407 
408 void DownloadWidgetPrivate::slotShowOverview()
409 {
410  ui.backButton->setVisible(false);
411 
412  ui.updateButton->setVisible(false);
413  ui.installButton->setVisible(false);
414  ui.becomeFanButton->setVisible(false);
415  ui.uninstallButton->setVisible(false);
416 
417  ui.detailsStack->setCurrentIndex(0);
418  ui.m_titleWidget->setText(titleText);
419 }
420 
421 #include "moc_downloadwidget.cpp"
KNSCore::Engine * engine()
~DownloadWidget()
destructor
void reserve(int alloc)
KNS3::Entry::List changedEntries()
The list of entries with changed status (installed/uninstalled)
KNS3::Entry::List installedEntries()
The list of entries that have been newly installed.
QStringList categories() const
The list of the server-side names of the categories handled by this engine instance.
Definition: engine.cpp:201
void setSearchTerm(const QString &searchString)
Sets a string search term.
Definition: engine.cpp:454
void setTitle(const QString &title)
Set the title for display purposes in the widget&#39;s title.
void textChanged(const QString &text)
QString title() const
Get the current title.
int size() const const
KNewStuff download widget.
void timeout()
void append(const T &value)
QString & insert(int position, QChar ch)
void setCategoriesFilter(const QStringList &categories)
Set the categories that will be included in searches.
Definition: engine.cpp:406
bool isEmpty() const const
void clicked(bool checked)
void activated(int index)
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
QString category() const
Retrieve the category of the data object.
bool init(const QString &configfile)
Initializes the engine.
Definition: engine.cpp:104
void signalMessage(const QString &message)
Indicates a message to be added to the ui&#39;s log, or sent to a messagebox.
void setFilter(Provider::Filter filter)
Set a filter for results (defaults to none), which will allow you to show only installed entries...
Definition: engine.cpp:426
void setSortMode(Provider::SortMode mode)
Set the order the search results are returned in.
Definition: engine.cpp:412
QString i18n(const char *text, const TYPE &arg...)
DownloadWidget(QWidget *parent=nullptr)
Create a download widget that lets the user install, update and uninstall contents.
KNewStuff data entry container.
Definition: entryinternal.h:49
void insert(int i, const T &value)
KNewStuff engine.
Definition: engine.h:59
void valueChanged(int value)
void editingFinished()
QIcon fromTheme(const QString &name)
void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
Definition: button.cpp:18
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString name() const
Retrieve the name of the data object.
QObject * parent() const const
void signalErrorCode(const KNSCore::ErrorCode &errorCode, const QString &message, const QVariant &metadata)
Fires in the case of any critical or serious errors, such as network or API problems.
QString applicationName()
void setSingleShot(bool singleShot)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Aug 11 2020 22:43:23 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.