KNewStuff

entrydetailsdialog.cpp
1 /*
2  Copyright (C) 2009 Frederik Gladhorn <[email protected]>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "entrydetailsdialog_p.h"
19 
20 #include <QMenu>
21 #include <knewstuff_debug.h>
22 #include <KLocalizedString>
23 
24 #include "core/engine.h"
25 #include "core/imageloader_p.h"
26 #include <attica/provider.h>
27 
28 using namespace KNS3;
29 
30 EntryDetails::EntryDetails(KNSCore::Engine *engine, Ui::DownloadWidget *widget)
31  : QObject(widget->m_listView), m_engine(engine), ui(widget)
32 {
33  init();
34 }
35 
36 EntryDetails::~EntryDetails()
37 {
38 }
39 
40 void EntryDetails::init()
41 {
42  connect(ui->preview1, &ImagePreviewWidget::clicked, this, &EntryDetails::preview1Selected);
43  connect(ui->preview2, &ImagePreviewWidget::clicked, this, &EntryDetails::preview2Selected);
44  connect(ui->preview3, &ImagePreviewWidget::clicked, this, &EntryDetails::preview3Selected);
45 
46  ui->ratingWidget->setMaxRating(10);
47  ui->ratingWidget->setHalfStepsEnabled(true);
48 
49  updateButtons();
50  connect(ui->installButton, &QAbstractButton::clicked, this, &EntryDetails::install);
51  connect(ui->uninstallButton, &QAbstractButton::clicked, this, &EntryDetails::uninstall);
52  // updating is the same as installing
53  connect(ui->updateButton, &QAbstractButton::clicked, this, &EntryDetails::install);
54  connect(ui->becomeFanButton, &QAbstractButton::clicked, this, &EntryDetails::becomeFan);
55 
56  ui->installButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok")));
57  ui->updateButton->setIcon(QIcon::fromTheme(QStringLiteral("system-software-update")));
58  ui->uninstallButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
59 
60  connect(m_engine, &KNSCore::Engine::signalEntryDetailsLoaded,
61  this, &EntryDetails::entryChanged);
62  connect(m_engine, &KNSCore::Engine::signalEntryChanged,
63  this, &EntryDetails::entryStatusChanged);
64  connect(m_engine, &KNSCore::Engine::signalEntryPreviewLoaded,
65  this, &EntryDetails::slotEntryPreviewLoaded);
66 }
67 
68 void EntryDetails::setEntry(const KNSCore::EntryInternal &entry)
69 {
70  m_entry = entry;
71  // immediately show something
72  entryChanged(m_entry);
73  // fetch more preview images
74  m_engine->loadDetails(m_entry);
75 }
76 
77 void EntryDetails::entryChanged(const KNSCore::EntryInternal &entry)
78 {
79  if (ui->detailsStack->currentIndex() == 0) {
80  return;
81  }
82  m_entry = entry;
83 
84  // FIXME
85  //ui->ratingWidget->setEditable(m_engine->userCanVote(m_entry));
86 
87  if (!m_engine->userCanBecomeFan(m_entry)) {
88  ui->becomeFanButton->setEnabled(false);
89  }
90 
91  ui->m_titleWidget->setText(i18n("Details for %1", m_entry.name()));
92  if (!m_entry.author().homepage().isEmpty()) {
93  ui->authorLabel->setText(QLatin1String("<a href=\"") + m_entry.author().homepage() + QLatin1String("\">") + m_entry.author().name() + QLatin1String("</a>"));
94  } else if (!m_entry.author().email().isEmpty()) {
95  ui->authorLabel->setText(QLatin1String("<a href=\"mailto:") + m_entry.author().email() + QLatin1String("\">") + m_entry.author().name() + QLatin1String("</a>"));
96  } else {
97  ui->authorLabel->setText(m_entry.author().name());
98  }
99 
100  QString summary = KNSCore::replaceBBCode(m_entry.summary()).replace(QLatin1Char('\n'), QLatin1String("<br/>"));
101  QString changelog = KNSCore::replaceBBCode(m_entry.changelog()).replace(QLatin1Char('\n'), QLatin1String("<br/>"));
102 
103  QString description = QLatin1String("<html><body>") + summary;
104  if (!changelog.isEmpty()) {
105  description += QLatin1String("<br/><p><b>") + i18n("Changelog:") + QLatin1String("</b><br/>") + changelog + QLatin1String("</p>");
106  }
107  description += QLatin1String("</body></html>");
108  ui->descriptionLabel->setText(description);
109 
110  QString homepageText(QLatin1String("<a href=\"") + m_entry.homepage().url() + QLatin1String("\">") +
111  i18nc("A link to the description of this Get Hot New Stuff item", "Homepage") + QStringLiteral("</a>"));
112 
113  if (!m_entry.donationLink().isEmpty()) {
114  homepageText += QLatin1String("<br><a href=\"") + m_entry.donationLink() + QLatin1String("\">") + i18nc("A link to make a donation for a Get Hot New Stuff item (opens a web browser)", "Make a donation") + QLatin1String("</a>");
115  }
116  if (!m_entry.knowledgebaseLink().isEmpty()) {
117  homepageText += QLatin1String("<br><a href=\"") + m_entry.knowledgebaseLink() + QLatin1String("\">")
118  + i18ncp("A link to the knowledgebase (like a forum) (opens a web browser)", "Knowledgebase (no entries)", "Knowledgebase (%1 entries)", m_entry.numberKnowledgebaseEntries()) + QStringLiteral("</a>");
119  }
120  ui->homepageLabel->setText(homepageText);
121  ui->homepageLabel->setToolTip(i18nc("Tooltip for a link in a dialog", "Opens in a browser window"));
122 
123  if (m_entry.rating() > 0) {
124  ui->ratingWidget->setVisible(true);
125  disconnect(ui->ratingWidget, static_cast<void(KRatingWidget::*)(uint)>(&KRatingWidget::ratingChanged),
126  this, &EntryDetails::ratingChanged);
127  // Most of the voting is 20 - 80, so rate 20 as 0 stars and 80 as 5 stars
128  int rating = qMax(0, qMin(10, (m_entry.rating() - 20) / 6));
129  ui->ratingWidget->setRating(rating);
130  connect(ui->ratingWidget, static_cast<void(KRatingWidget::*)(uint)>(&KRatingWidget::ratingChanged),
131  this, &EntryDetails::ratingChanged);
132  } else {
133  ui->ratingWidget->setVisible(false);
134  }
135 
136  bool hideSmallPreviews = m_entry.previewUrl(KNSCore::EntryInternal::PreviewSmall2).isEmpty()
137  && m_entry.previewUrl(KNSCore::EntryInternal::PreviewSmall3).isEmpty();
138 
139  ui->preview1->setVisible(!hideSmallPreviews);
140  ui->preview2->setVisible(!hideSmallPreviews);
141  ui->preview3->setVisible(!hideSmallPreviews);
142 
143  // in static xml we often only get a small preview, use that in details
144  if (m_entry.previewUrl(KNSCore::EntryInternal::PreviewBig1).isEmpty() && !m_entry.previewUrl(KNSCore::EntryInternal::PreviewSmall1).isEmpty()) {
145  m_entry.setPreviewUrl(m_entry.previewUrl(KNSCore::EntryInternal::PreviewSmall1), KNSCore::EntryInternal::PreviewBig1);
146  m_entry.setPreviewImage(m_entry.previewImage(KNSCore::EntryInternal::PreviewSmall1), KNSCore::EntryInternal::PreviewBig1);
147  }
148 
149  for (int type = KNSCore::EntryInternal::PreviewSmall1; type <= KNSCore::EntryInternal::PreviewBig3; ++type) {
150  if (m_entry.previewUrl(KNSCore::EntryInternal::PreviewSmall1).isEmpty()) {
151  ui->previewBig->setVisible(false);
152  } else
153 
154  if (!m_entry.previewUrl((KNSCore::EntryInternal::PreviewType)type).isEmpty()) {
155  qCDebug(KNEWSTUFF) << "type: " << type << m_entry.previewUrl((KNSCore::EntryInternal::PreviewType)type);
156  if (m_entry.previewImage((KNSCore::EntryInternal::PreviewType)type).isNull()) {
157  m_engine->loadPreview(m_entry, (KNSCore::EntryInternal::PreviewType)type);
158  } else {
159  slotEntryPreviewLoaded(m_entry, (KNSCore::EntryInternal::PreviewType)type);
160  }
161  }
162  }
163 
164  updateButtons();
165 }
166 
167 void EntryDetails::entryStatusChanged(const KNSCore::EntryInternal &entry)
168 {
169  Q_UNUSED(entry);
170  updateButtons();
171 }
172 
173 void EntryDetails::updateButtons()
174 {
175  if (ui->detailsStack->currentIndex() == 0) {
176  return;
177  }
178  qCDebug(KNEWSTUFF) << "update buttons: " << m_entry.status();
179  ui->installButton->setVisible(false);
180  ui->uninstallButton->setVisible(false);
181  ui->updateButton->setVisible(false);
182 
183  switch (m_entry.status()) {
184  case Entry::Installed:
185  ui->uninstallButton->setVisible(true);
186  ui->uninstallButton->setEnabled(true);
187  break;
188  case Entry::Updateable:
189  ui->updateButton->setVisible(true);
190  ui->updateButton->setEnabled(true);
191  ui->uninstallButton->setVisible(true);
192  ui->uninstallButton->setEnabled(true);
193  break;
194 
195  case Entry::Invalid:
196  case Entry::Downloadable:
197  ui->installButton->setVisible(true);
198  ui->installButton->setEnabled(true);
199  break;
200 
201  case Entry::Installing:
202  ui->installButton->setVisible(true);
203  ui->installButton->setEnabled(false);
204  break;
205  case Entry::Updating:
206  ui->updateButton->setVisible(true);
207  ui->updateButton->setEnabled(false);
208  ui->uninstallButton->setVisible(true);
209  ui->uninstallButton->setEnabled(false);
210  break;
211  case Entry::Deleted:
212  ui->installButton->setVisible(true);
213  ui->installButton->setEnabled(true);
214  break;
215  }
216 
217  if (QMenu *buttonMenu = ui->installButton->menu()) {
218  buttonMenu->clear();
219  ui->installButton->setMenu(nullptr);
220  buttonMenu->deleteLater();
221  }
222  if (ui->installButton->isVisible() && m_entry.downloadLinkCount() > 1) {
223  QMenu *installMenu = new QMenu(ui->installButton);
224  const auto lst = m_entry.downloadLinkInformationList();
225  for (const KNSCore::EntryInternal::DownloadLinkInformation &info : lst) {
226  QString text = info.name;
227  if (!info.distributionType.trimmed().isEmpty()) {
228  text + QStringLiteral(" (") + info.distributionType.trimmed() + QLatin1Char(')');
229  }
230  QAction *installMenuAction = installMenu->addAction(QIcon::fromTheme(QStringLiteral("dialog-ok")), text);
231  installMenuAction->setData(info.id);
232  connect(installMenuAction, &QAction::triggered, this, [this, installMenuAction](){
233  Q_EMIT installAction(installMenuAction);
234  });
235  }
236  qCDebug(KNEWSTUFF) << "links: " << m_entry.downloadLinkInformationList().size();
237  ui->installButton->setMenu(installMenu);
238  }
239 }
240 
241 void EntryDetails::install()
242 {
243  m_engine->install(m_entry);
244 }
245 
246 void EntryDetails::uninstall()
247 {
248  m_engine->uninstall(m_entry);
249 }
250 
251 void EntryDetails::slotEntryPreviewLoaded(const KNSCore::EntryInternal &entry, KNSCore::EntryInternal::PreviewType type)
252 {
253  if (!(entry == m_entry)) {
254  return;
255  }
256 
257  switch (type) {
258  case KNSCore::EntryInternal::PreviewSmall1:
259  ui->preview1->setImage(entry.previewImage(KNSCore::EntryInternal::PreviewSmall1));
260  break;
261  case KNSCore::EntryInternal::PreviewSmall2:
262  ui->preview2->setImage(entry.previewImage(KNSCore::EntryInternal::PreviewSmall2));
263  break;
264  case KNSCore::EntryInternal::PreviewSmall3:
265  ui->preview3->setImage(entry.previewImage(KNSCore::EntryInternal::PreviewSmall3));
266  break;
267  case KNSCore::EntryInternal::PreviewBig1:
268  m_currentPreview = entry.previewImage(KNSCore::EntryInternal::PreviewBig1);
269  ui->previewBig->setImage(m_currentPreview);
270  break;
271  default:
272  break;
273  }
274 }
275 
276 void EntryDetails::preview1Selected()
277 {
278  previewSelected(0);
279 }
280 
281 void EntryDetails::preview2Selected()
282 {
283  previewSelected(1);
284 }
285 
286 void EntryDetails::preview3Selected()
287 {
288  previewSelected(2);
289 }
290 
291 void EntryDetails::previewSelected(int current)
292 {
293  KNSCore::EntryInternal::PreviewType type = static_cast<KNSCore::EntryInternal::PreviewType>(KNSCore::EntryInternal::PreviewBig1 + current);
294  m_currentPreview = m_entry.previewImage(type);
295  ui->previewBig->setImage(m_currentPreview);
296 }
297 
298 void EntryDetails::ratingChanged(uint rating)
299 {
300  // engine expects values from 0..100
301  qCDebug(KNEWSTUFF) << "rating: " << rating << " -> " << rating*10;
302  m_engine->vote(m_entry, rating * 10);
303 }
304 
305 void EntryDetails::becomeFan()
306 {
307  m_engine->becomeFan(m_entry);
308 }
309 
310 void EntryDetails::installAction(QAction *action)
311 {
312  m_engine->install(m_entry, action->data().toInt());
313 }
314 
void triggered(bool checked)
QVariant data() const const
KNEWSTUFFCORE_EXPORT QString replaceBBCode(const QString &unformattedText)
function to remove bb code formatting that opendesktop sends
QImage previewImage(PreviewType type=PreviewSmall1) const
This will not be loaded automatically, instead use Engine to load the actual images.
QAction * addAction(const QString &text)
int toInt(bool *ok) const const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
QString trimmed() const const
void clicked(bool checked)
void ratingChanged(unsigned int rating)
const QList< QKeySequence > & replace()
void setData(const QVariant &userData)
QString i18ncp(const char *context, const char *singular, const char *plural, const TYPE &arg...)
QCA_EXPORT void init()
QString i18n(const char *text, const TYPE &arg...)
KNewStuff data entry container.
Definition: entryinternal.h:60
KNewStuff engine.
Definition: engine.h:70
QIcon fromTheme(const QString &name)
Definition: button.cpp:29
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Aug 9 2020 22:43:40 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.