File indexing completed on 2024-10-13 03:41:37
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer at kde.org> 0004 SPDX-FileCopyrightText: 2008, 2019 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 SPDX-FileCopyrightText: 2010 Teo Mrnjavac <teo@kde.org> 0006 0007 Parts of this class have been take from the KAboutApplication class, which was 0008 SPDX-FileCopyrightText: 2000 Waldo Bastian <bastian@kde.org> 0009 SPDX-FileCopyrightText: 2000 Espen Sand <espen@kde.org> 0010 0011 SPDX-License-Identifier: LGPL-2.0-only 0012 */ 0013 0014 #include "kabstractaboutdialog_p.h" 0015 0016 #include "kaboutapplicationcomponentlistdelegate_p.h" 0017 #include "kaboutapplicationcomponentmodel_p.h" 0018 #include "kaboutapplicationlistview_p.h" 0019 #include "kaboutapplicationpersonlistdelegate_p.h" 0020 #include "kaboutapplicationpersonmodel_p.h" 0021 #include "klicensedialog_p.h" 0022 #include <kxmlgui_version.h> 0023 // KF 0024 #include <KLocalizedString> 0025 #include <KTitleWidget> 0026 // Qt 0027 #include <QApplication> 0028 #include <QCheckBox> 0029 #include <QDialogButtonBox> 0030 #include <QIcon> 0031 #include <QLabel> 0032 #include <QVBoxLayout> 0033 0034 QWidget *KAbstractAboutDialogPrivate::createTitleWidget(const QIcon &icon, const QString &displayName, const QString &version, QWidget *parent) 0035 { 0036 KTitleWidget *titleWidget = new KTitleWidget(parent); 0037 0038 titleWidget->setIconSize(QSize(48, 48)); 0039 titleWidget->setIcon(icon, KTitleWidget::ImageLeft); 0040 titleWidget->setText( 0041 QLatin1String("<html><font size=\"5\">%1</font><br />%2</html>").arg(displayName, i18nc("Version version-number", "Version %1", version))); 0042 return titleWidget; 0043 } 0044 0045 QWidget *KAbstractAboutDialogPrivate::createAboutWidget(const QString &shortDescription, 0046 const QString &otherText, 0047 const QString ©rightStatement, 0048 const QString &homepage, 0049 const QList<KAboutLicense> &licenses, 0050 QWidget *parent) 0051 { 0052 QWidget *aboutWidget = new QWidget(parent); 0053 QVBoxLayout *aboutLayout = new QVBoxLayout(aboutWidget); 0054 0055 QString aboutPageText = shortDescription + QLatin1Char('\n'); 0056 0057 if (!otherText.isEmpty()) { 0058 aboutPageText += QLatin1Char('\n') + otherText + QLatin1Char('\n'); 0059 } 0060 0061 if (!copyrightStatement.isEmpty()) { 0062 aboutPageText += QLatin1Char('\n') + copyrightStatement + QLatin1Char('\n'); 0063 } 0064 0065 if (!homepage.isEmpty()) { 0066 aboutPageText += QLatin1Char('\n') + QStringLiteral("<a href=\"%1\">%1</a>").arg(homepage) + QLatin1Char('\n'); 0067 } 0068 aboutPageText = aboutPageText.trimmed(); 0069 0070 QLabel *aboutLabel = new QLabel; 0071 aboutLabel->setWordWrap(true); 0072 aboutLabel->setOpenExternalLinks(true); 0073 aboutLabel->setText(aboutPageText.replace(QLatin1Char('\n'), QStringLiteral("<br />"))); 0074 aboutLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0075 0076 aboutLayout->addStretch(); 0077 aboutLayout->addWidget(aboutLabel); 0078 0079 const int licenseCount = licenses.count(); 0080 for (int i = 0; i < licenseCount; ++i) { 0081 const KAboutLicense &license = licenses.at(i); 0082 0083 QLabel *showLicenseLabel = new QLabel; 0084 showLicenseLabel->setText(QStringLiteral("<a href=\"%1\">%2</a>").arg(QString::number(i), i18n("License: %1", license.name(KAboutLicense::FullName)))); 0085 showLicenseLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0086 QObject::connect(showLicenseLabel, &QLabel::linkActivated, parent, [license, parent]() { 0087 auto *dialog = new KLicenseDialog(license, parent); 0088 dialog->show(); 0089 }); 0090 0091 aboutLayout->addWidget(showLicenseLabel); 0092 } 0093 0094 aboutLayout->addStretch(); 0095 0096 return aboutWidget; 0097 } 0098 0099 QWidget *KAbstractAboutDialogPrivate::createComponentWidget(const QList<KAboutComponent> &components, QWidget *parent) 0100 { 0101 QWidget *componentWidget = new QWidget(parent); 0102 QVBoxLayout *componentLayout = new QVBoxLayout(componentWidget); 0103 componentLayout->setContentsMargins(0, 0, 0, 0); 0104 0105 QList<KAboutComponent> allComponents = components; 0106 allComponents.prepend(KAboutComponent(i18n("The <em>%1</em> windowing system", QGuiApplication::platformName()))); 0107 allComponents.prepend(KAboutComponent(i18n("Qt"), 0108 QString(), 0109 i18n("%1 (built against %2)", QString::fromLocal8Bit(qVersion()), QStringLiteral(QT_VERSION_STR)), 0110 QStringLiteral("https://www.qt.io/"))); 0111 allComponents.prepend(KAboutComponent(i18n("KDE Frameworks"), 0112 QString(), 0113 QStringLiteral(KXMLGUI_VERSION_STRING), 0114 QStringLiteral("https://develop.kde.org/products/frameworks/"))); 0115 0116 KDEPrivate::KAboutApplicationComponentModel *componentModel = new KDEPrivate::KAboutApplicationComponentModel(allComponents, componentWidget); 0117 0118 KDEPrivate::KAboutApplicationListView *componentView = new KDEPrivate::KAboutApplicationListView(componentWidget); 0119 0120 KDEPrivate::KAboutApplicationComponentListDelegate *componentDelegate = 0121 new KDEPrivate::KAboutApplicationComponentListDelegate(componentView, componentView); 0122 0123 componentView->setModel(componentModel); 0124 componentView->setItemDelegate(componentDelegate); 0125 componentView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0126 componentLayout->addWidget(componentView); 0127 0128 return componentWidget; 0129 } 0130 0131 static QWidget *createAvatarCheck(QWidget *parent, KDEPrivate::KAboutApplicationPersonModel *model) 0132 { 0133 // Add in a checkbox to allow people to switch the avatar fetch 0134 // (off-by-default to avoid unwarned online activity) 0135 QCheckBox *avatarsCheck = new QCheckBox(parent); 0136 avatarsCheck->setText(i18n("Show author photos")); 0137 avatarsCheck->setToolTip(i18n("Enabling this will fetch images from an online location")); 0138 avatarsCheck->setVisible(model->hasAnyAvatars()); 0139 QObject::connect(model, &KDEPrivate::KAboutApplicationPersonModel::hasAnyAvatarsChanged, parent, [avatarsCheck, model]() { 0140 avatarsCheck->setVisible(model->hasAnyAvatars()); 0141 }); 0142 QObject::connect(avatarsCheck, &QCheckBox::stateChanged, parent, [model](int state) { 0143 switch (state) { 0144 case Qt::Checked: 0145 case Qt::PartiallyChecked: 0146 // tell model to use avatars 0147 model->setShowRemoteAvatars(true); 0148 break; 0149 case Qt::Unchecked: 0150 default: 0151 // tell model not to use avatars 0152 model->setShowRemoteAvatars(false); 0153 break; 0154 } 0155 }); 0156 return avatarsCheck; 0157 } 0158 0159 QWidget *KAbstractAboutDialogPrivate::createAuthorsWidget(const QList<KAboutPerson> &authors, 0160 bool customAuthorTextEnabled, 0161 const QString &customAuthorRichText, 0162 const QString &bugAddress, 0163 QWidget *parent) 0164 { 0165 QWidget *authorWidget = new QWidget(parent); 0166 QVBoxLayout *authorLayout = new QVBoxLayout(authorWidget); 0167 authorLayout->setContentsMargins(0, 0, 0, 0); 0168 0169 if (!customAuthorTextEnabled || !customAuthorRichText.isEmpty()) { 0170 QLabel *bugsLabel = new QLabel(authorWidget); 0171 bugsLabel->setContentsMargins(4, 2, 0, 4); 0172 bugsLabel->setOpenExternalLinks(true); 0173 if (!customAuthorTextEnabled) { 0174 if (bugAddress.isEmpty() || bugAddress == QLatin1String("submit@bugs.kde.org")) { 0175 bugsLabel->setText(i18nc("Reference to website", 0176 "Please use %1 to report bugs.\n", 0177 QLatin1String("<a href=\"https://bugs.kde.org\">https://bugs.kde.org</a>"))); 0178 } else { 0179 QUrl bugUrl(bugAddress); 0180 if (bugUrl.scheme().isEmpty()) { 0181 bugUrl.setScheme(QStringLiteral("mailto")); 0182 } 0183 bugsLabel->setText(i18nc("Reference to email address", 0184 "Please report bugs to %1.\n", 0185 QLatin1String("<a href=\"%1\">%2</a>").arg(bugUrl.toString(), bugAddress))); 0186 } 0187 } else { 0188 bugsLabel->setText(customAuthorRichText); 0189 } 0190 bugsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); 0191 authorLayout->addWidget(bugsLabel); 0192 } 0193 0194 KDEPrivate::KAboutApplicationPersonModel *authorModel = new KDEPrivate::KAboutApplicationPersonModel(authors, authorWidget); 0195 0196 KDEPrivate::KAboutApplicationListView *authorView = new KDEPrivate::KAboutApplicationListView(authorWidget); 0197 0198 KDEPrivate::KAboutApplicationPersonListDelegate *authorDelegate = new KDEPrivate::KAboutApplicationPersonListDelegate(authorView, authorView); 0199 0200 authorView->setModel(authorModel); 0201 authorView->setItemDelegate(authorDelegate); 0202 authorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0203 authorLayout->addWidget(createAvatarCheck(parent, authorModel)); 0204 authorLayout->addWidget(authorView); 0205 0206 return authorWidget; 0207 } 0208 0209 QWidget *KAbstractAboutDialogPrivate::createCreditWidget(const QList<KAboutPerson> &credits, QWidget *parent) 0210 { 0211 QWidget *creditWidget = new QWidget(parent); 0212 QVBoxLayout *creditLayout = new QVBoxLayout(creditWidget); 0213 creditLayout->setContentsMargins(0, 0, 0, 0); 0214 0215 KDEPrivate::KAboutApplicationPersonModel *creditModel = new KDEPrivate::KAboutApplicationPersonModel(credits, creditWidget); 0216 0217 KDEPrivate::KAboutApplicationListView *creditView = new KDEPrivate::KAboutApplicationListView(creditWidget); 0218 0219 KDEPrivate::KAboutApplicationPersonListDelegate *creditDelegate = new KDEPrivate::KAboutApplicationPersonListDelegate(creditView, creditView); 0220 0221 creditView->setModel(creditModel); 0222 creditView->setItemDelegate(creditDelegate); 0223 creditView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0224 creditLayout->addWidget(createAvatarCheck(parent, creditModel)); 0225 creditLayout->addWidget(creditView); 0226 0227 return creditWidget; 0228 } 0229 0230 QWidget *KAbstractAboutDialogPrivate::createTranslatorsWidget(const QList<KAboutPerson> &translators, QWidget *parent) 0231 { 0232 QWidget *translatorWidget = new QWidget(parent); 0233 QVBoxLayout *translatorLayout = new QVBoxLayout(translatorWidget); 0234 translatorLayout->setContentsMargins(0, 0, 0, 0); 0235 0236 KDEPrivate::KAboutApplicationPersonModel *translatorModel = new KDEPrivate::KAboutApplicationPersonModel(translators, translatorWidget); 0237 0238 KDEPrivate::KAboutApplicationListView *translatorView = new KDEPrivate::KAboutApplicationListView(translatorWidget); 0239 0240 KDEPrivate::KAboutApplicationPersonListDelegate *translatorDelegate = new KDEPrivate::KAboutApplicationPersonListDelegate(translatorView, translatorView); 0241 0242 translatorView->setModel(translatorModel); 0243 translatorView->setItemDelegate(translatorDelegate); 0244 translatorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0245 translatorLayout->addWidget(createAvatarCheck(parent, translatorModel)); 0246 translatorLayout->addWidget(translatorView); 0247 0248 QString aboutTranslationTeam = KAboutData::aboutTranslationTeam(); 0249 if (!aboutTranslationTeam.isEmpty()) { 0250 QLabel *translationTeamLabel = new QLabel(translatorWidget); 0251 translationTeamLabel->setContentsMargins(4, 2, 4, 4); 0252 translationTeamLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); 0253 translationTeamLabel->setWordWrap(true); 0254 translationTeamLabel->setText(aboutTranslationTeam); 0255 translationTeamLabel->setOpenExternalLinks(true); 0256 translatorLayout->addWidget(translationTeamLabel); 0257 // TODO: this could be displayed as a view item to save space 0258 } 0259 0260 return translatorWidget; 0261 } 0262 0263 void KAbstractAboutDialogPrivate::createForm(QWidget *titleWidget, QWidget *tabWidget, QDialog *dialog) 0264 { 0265 QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); 0266 buttonBox->setStandardButtons(QDialogButtonBox::Close); 0267 QObject::connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); 0268 QObject::connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); 0269 0270 // And we jam everything together in a layout... 0271 QVBoxLayout *mainLayout = new QVBoxLayout(dialog); 0272 mainLayout->addWidget(titleWidget); 0273 mainLayout->addWidget(tabWidget); 0274 mainLayout->addWidget(buttonBox); 0275 }