File indexing completed on 2024-12-01 12:40:34
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2021 Julius Künzel <jk.kdedev@smartlab.uber.space> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "kaboutapplicationcomponentlistdelegate_p.h" 0009 0010 #include "kaboutapplicationcomponentmodel_p.h" 0011 #include "kaboutapplicationlistview_p.h" 0012 #include "klicensedialog_p.h" 0013 #include "ktoolbar.h" 0014 0015 #include <KLocalizedString> 0016 0017 #include <QAction> 0018 #include <QApplication> 0019 #include <QDesktopServices> 0020 #include <QLabel> 0021 #include <QPainter> 0022 #include <QStandardPaths> 0023 #include <QUrl> 0024 0025 namespace KDEPrivate 0026 { 0027 0028 KAboutApplicationComponentListDelegate::KAboutApplicationComponentListDelegate(QAbstractItemView *itemView, QObject *parent) 0029 : KWidgetItemDelegate(itemView, parent) 0030 { 0031 } 0032 0033 QList<QWidget *> KAboutApplicationComponentListDelegate::createItemWidgets(const QModelIndex &index) const 0034 { 0035 Q_UNUSED(index); 0036 QList<QWidget *> list; 0037 0038 QLabel *textLabel = new QLabel(itemView()); 0039 list.append(textLabel); 0040 0041 KAboutApplicationComponentProfile profile = index.data().value<KAboutApplicationComponentProfile>(); 0042 textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0043 QObject::connect(textLabel, &QLabel::linkActivated, itemView(), [this, profile]() { 0044 auto *dialog = new KLicenseDialog(profile.license(), itemView()); 0045 dialog->show(); 0046 }); 0047 0048 KToolBar *mainLinks = new KToolBar(itemView(), false, false); 0049 0050 QAction *homepageAction = new QAction(QIcon::fromTheme(QStringLiteral("internet-services")), // 0051 i18n("Visit component's homepage"), 0052 mainLinks); 0053 homepageAction->setVisible(false); 0054 mainLinks->addAction(homepageAction); 0055 QAction *visitProfileAction = new QAction(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff")), QString(), mainLinks); 0056 visitProfileAction->setVisible(false); 0057 mainLinks->addAction(visitProfileAction); 0058 0059 list.append(mainLinks); 0060 0061 connect(mainLinks, &QToolBar::actionTriggered, this, &KAboutApplicationComponentListDelegate::launchUrl); 0062 0063 return list; 0064 } 0065 0066 void KAboutApplicationComponentListDelegate::updateItemWidgets(const QList<QWidget *> widgets, 0067 const QStyleOptionViewItem &option, 0068 const QPersistentModelIndex &index) const 0069 { 0070 const int margin = option.fontMetrics.height() / 2; 0071 0072 KAboutApplicationComponentProfile profile = index.data().value<KAboutApplicationComponentProfile>(); 0073 0074 QRect wRect = widgetsRect(option, index); 0075 0076 // Let's fill in the text first... 0077 QLabel *label = qobject_cast<QLabel *>(widgets.at(TextLabel)); 0078 label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0079 0080 QString text = buildTextForProfile(profile); 0081 0082 label->move(wRect.left(), wRect.top()); 0083 label->resize(wRect.width(), heightForString(text, wRect.width() - margin, option) + margin); 0084 label->setWordWrap(true); 0085 label->setContentsMargins(0, 0, 0, 0); 0086 label->setAlignment(Qt::AlignBottom | Qt::AlignLeft); 0087 label->setForegroundRole(QPalette::WindowText); 0088 0089 label->setText(text); 0090 0091 // And now we fill in the main links (email + homepage + OCS profile)... 0092 KToolBar *mainLinks = qobject_cast<KToolBar *>(widgets.at(MainLinks)); 0093 mainLinks->setIconSize(QSize(22, 22)); 0094 mainLinks->setContentsMargins(0, 0, 0, 0); 0095 mainLinks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0096 QAction *action; 0097 if (!profile.webAdress().isEmpty()) { 0098 action = mainLinks->actions().at(HomepageAction); 0099 action->setToolTip(i18nc("@info:tooltip", "Visit components's homepage\n%1", profile.webAdress())); 0100 action->setData(profile.webAdress()); 0101 action->setVisible(true); 0102 } 0103 mainLinks->resize(QSize(mainLinks->sizeHint().width(), LINK_HEIGHT)); 0104 mainLinks->move(wRect.left(), wRect.top() + label->height()); 0105 itemView()->reset(); 0106 } 0107 0108 QSize KAboutApplicationComponentListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0109 { 0110 int height = widgetsRect(option, index).height(); 0111 0112 QSize metrics(option.fontMetrics.height() * 7, height); 0113 return metrics; 0114 } 0115 0116 void KAboutApplicationComponentListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &) const 0117 { 0118 QStyle *style = QApplication::style(); 0119 style->drawPrimitive(QStyle::PE_Widget, &option, painter, nullptr); 0120 } 0121 0122 void KAboutApplicationComponentListDelegate::launchUrl(QAction *action) const 0123 { 0124 QString url = action->data().toString(); 0125 if (!url.isEmpty()) { 0126 QDesktopServices::openUrl(QUrl(url)); 0127 } 0128 } 0129 0130 int KAboutApplicationComponentListDelegate::heightForString(const QString &string, int lineWidth, const QStyleOptionViewItem &option) const 0131 { 0132 QFontMetrics fm = option.fontMetrics; 0133 constexpr auto opts = Qt::AlignLeft | Qt::AlignBottom | Qt::TextWordWrap; 0134 QRect boundingRect = fm.boundingRect(0, 0, lineWidth, 9999, opts, string); 0135 return boundingRect.height(); 0136 } 0137 0138 QString KAboutApplicationComponentListDelegate::buildTextForProfile(const KAboutApplicationComponentProfile &profile) const 0139 { 0140 QString text = QLatin1String("<b>") + i18nc("@item Component name in about dialog.", "%1", profile.name()) + QLatin1String("</b>"); 0141 0142 if (!profile.version().isEmpty()) { 0143 text += QStringLiteral("\n<br><i>%1</i>").arg(i18n("Version %1", profile.version())); 0144 } 0145 0146 if (!profile.description().isEmpty()) { 0147 text += QLatin1String("\n<br>") + profile.description(); 0148 } 0149 0150 if (profile.license().key() != KAboutLicense::Unknown) { 0151 text += QLatin1String("\n<br>"); 0152 text += QStringLiteral("<a href=\"#\">%2</a>").arg(i18n("License: %1", profile.license().name(KAboutLicense::FullName))); 0153 } 0154 0155 return text; 0156 } 0157 0158 QRect KAboutApplicationComponentListDelegate::widgetsRect(const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const 0159 { 0160 KAboutApplicationComponentProfile profile = index.data().value<KAboutApplicationComponentProfile>(); 0161 int margin = option.fontMetrics.height() / 2; 0162 0163 QRect widgetsRect = QRect(option.rect.left() + margin, // 0164 margin / 2, // 0165 option.rect.width() - 2 * margin, // 0166 0); 0167 0168 int textHeight = heightForString(buildTextForProfile(profile), widgetsRect.width() - margin, option); 0169 widgetsRect.setHeight(textHeight + LINK_HEIGHT + 1.5 * margin); 0170 0171 return widgetsRect; 0172 } 0173 0174 } // namespace KDEPrivate 0175 0176 #include "moc_kaboutapplicationcomponentlistdelegate_p.cpp"