diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,8 @@ kaboutapplicationpersonlistview_p.cpp kaboutapplicationpersonmodel_p.cpp kaboutkdedialog_p.cpp + kaboutplugindialog.cpp + kabstractaboutdialog_p.cpp kactioncategory.cpp kactioncollection.cpp kactionconflictdetector.cpp @@ -32,6 +34,7 @@ kgesturemap.cpp khelpmenu.cpp kkeysequencewidget.cpp + klicensedialog_p.cpp kmainwindow.cpp kmenumenuhandler_p.cpp kshortcuteditwidget.cpp @@ -117,6 +120,7 @@ ecm_generate_headers(KXmlGui_HEADERS HEADER_NAMES KAboutApplicationDialog + KAboutPluginDialog KActionCategory KActionCollection KBugReport diff --git a/src/kaboutapplicationdialog.h b/src/kaboutapplicationdialog.h --- a/src/kaboutapplicationdialog.h +++ b/src/kaboutapplicationdialog.h @@ -96,8 +96,6 @@ class Private; Private *const d; - Q_PRIVATE_SLOT(d, void _k_showLicense(const QString &)) - Q_DISABLE_COPY(KAboutApplicationDialog) }; diff --git a/src/kaboutapplicationdialog.cpp b/src/kaboutapplicationdialog.cpp --- a/src/kaboutapplicationdialog.cpp +++ b/src/kaboutapplicationdialog.cpp @@ -23,129 +23,80 @@ #include "kaboutapplicationdialog.h" -#include "kaboutapplicationpersonmodel_p.h" -#include "kaboutapplicationpersonlistview_p.h" -#include "kaboutapplicationpersonlistdelegate_p.h" +#include "kabstractaboutdialog_p.h" #include "../kxmlgui_version.h" #include #include -#include +#include #include -#include #include -#include -#include -#include #include -#include -#include #include -class Q_DECL_HIDDEN KAboutApplicationDialog::Private + +class Q_DECL_HIDDEN KAboutApplicationDialog::Private : public KAbstractAboutDialogPrivate { public: - Private(KAboutApplicationDialog *parent) - : q(parent), - aboutData(KAboutData::applicationData()) + Private(const KAboutData &aboutData, KAboutApplicationDialog *parent) + : q(parent) + , aboutData(aboutData) {} - void init(const KAboutData &aboutData, Options opt); - - void _k_showLicense(const QString &number); + void init(Options opt); - KAboutApplicationDialog *q; +private: + KAboutApplicationDialog * const q; - KAboutData aboutData; + const KAboutData aboutData; }; KAboutApplicationDialog::KAboutApplicationDialog(const KAboutData &aboutData, QWidget *parent) : QDialog(parent), - d(new Private(this)) + d(new Private(aboutData, this)) { - d->init(aboutData, NoOptions); + d->init(NoOptions); } KAboutApplicationDialog::KAboutApplicationDialog(const KAboutData &aboutData, Options opt, QWidget *parent) : QDialog(parent), - d(new Private(this)) + d(new Private(aboutData, this)) { - d->init(aboutData, opt); + d->init(opt); } -void KAboutApplicationDialog::Private::init(const KAboutData &ad, Options opt) +void KAboutApplicationDialog::Private::init(Options opt) { - aboutData = ad; - q->setWindowTitle(i18n("About %1", aboutData.displayName())); q->setModal(false); //Set up the title widget... - KTitleWidget *titleWidget = new KTitleWidget(q); - - QIcon windowIcon = qApp->windowIcon(); - if (windowIcon.isNull() && !aboutData.programIconName().isEmpty()) { - windowIcon = QIcon::fromTheme(aboutData.programIconName()); - } - titleWidget->setPixmap(windowIcon.pixmap(48, 48), KTitleWidget::ImageLeft); + QPixmap titlePixmap; if (aboutData.programLogo().canConvert()) { - titleWidget->setPixmap(aboutData.programLogo().value(), KTitleWidget::ImageLeft); + titlePixmap = aboutData.programLogo().value(); } else if (aboutData.programLogo().canConvert()) { - titleWidget->setPixmap(QPixmap::fromImage(aboutData.programLogo().value()), KTitleWidget::ImageLeft); + titlePixmap = QPixmap::fromImage(aboutData.programLogo().value()); + } else { + QIcon windowIcon = qApp->windowIcon(); + if (windowIcon.isNull() && !aboutData.programIconName().isEmpty()) { + windowIcon = QIcon::fromTheme(aboutData.programIconName()); + } + titlePixmap = windowIcon.pixmap(48, 48); } - titleWidget->setText(i18n("%1
Version %2", aboutData.displayName(), aboutData.version())); + QWidget *titleWidget = createTitleWidget(titlePixmap, aboutData.displayName(), aboutData.version(), q); //Then the tab bar... QTabWidget *tabWidget = new QTabWidget; tabWidget->setUsesScrollButtons(false); //Set up the first page... - QString aboutPageText = aboutData.shortDescription() + QLatin1Char('\n'); - - if (!aboutData.otherText().isEmpty()) { - aboutPageText += QLatin1Char('\n') + aboutData.otherText() + QLatin1Char('\n'); - } - - if (!aboutData.copyrightStatement().isEmpty()) { - aboutPageText += QLatin1Char('\n') + aboutData.copyrightStatement() + QLatin1Char('\n'); - } - - if (!aboutData.homepage().isEmpty()) { - aboutPageText += QLatin1Char('\n') + QStringLiteral("%1").arg(aboutData.homepage()) + QLatin1Char('\n'); - } - aboutPageText = aboutPageText.trimmed(); - - QLabel *aboutLabel = new QLabel; - aboutLabel->setWordWrap(true); - aboutLabel->setOpenExternalLinks(true); - aboutLabel->setText(aboutPageText.replace(QLatin1Char('\n'), QStringLiteral("
"))); - aboutLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + QWidget *aboutWidget = createAboutWidget(aboutData.shortDescription(), aboutData.otherText(), + aboutData.copyrightStatement(), aboutData.homepage(), + aboutData.licenses(), q); - QVBoxLayout *aboutLayout = new QVBoxLayout; - aboutLayout->addStretch(); - aboutLayout->addWidget(aboutLabel); - - const int licenseCount = aboutData.licenses().count(); - for (int i = 0; i < licenseCount; ++i) { - const KAboutLicense &license = aboutData.licenses().at(i); - - QLabel *showLicenseLabel = new QLabel; - showLicenseLabel->setText(QStringLiteral("%2").arg(QString::number(i), - i18n("License: %1", license.name(KAboutLicense::FullName)))); - showLicenseLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - connect(showLicenseLabel, SIGNAL(linkActivated(QString)), q, SLOT(_k_showLicense(QString))); - - aboutLayout->addWidget(showLicenseLabel); - } - - aboutLayout->addStretch(); - - QWidget *aboutWidget = new QWidget(q); - aboutWidget->setLayout(aboutLayout); - - tabWidget->addTab(aboutWidget, i18n("&About")); + tabWidget->addTab(aboutWidget, i18n("About")); // Version QWidget *versionWidget = new QWidget(q); @@ -162,140 +113,34 @@ } versionLayout->addStretch(); versionWidget->setLayout(versionLayout); - tabWidget->addTab(versionWidget, i18n("&Libraries")); - - //Palette needed at least for translators... - QPalette transparentBackgroundPalette; - transparentBackgroundPalette.setColor(QPalette::Base, Qt::transparent); - transparentBackgroundPalette.setColor(QPalette::Text, transparentBackgroundPalette.color(QPalette::WindowText)); + tabWidget->addTab(versionWidget, i18n("Libraries")); //And here we go, authors page... const int authorCount = aboutData.authors().count(); if (authorCount) { - QWidget *authorWidget = new QWidget(q); - QVBoxLayout *authorLayout = new QVBoxLayout(authorWidget); - authorLayout->setContentsMargins(0, 0, 0, 0); - - if (!aboutData.customAuthorTextEnabled() || !aboutData.customAuthorRichText().isEmpty()) { - QLabel *bugsLabel = new QLabel(authorWidget); - bugsLabel->setContentsMargins(4, 2, 0, 4); - bugsLabel->setOpenExternalLinks(true); - if (!aboutData.customAuthorTextEnabled()) { - const QString bugAddress = aboutData.bugAddress(); - if (bugAddress.isEmpty() || bugAddress == QLatin1String("submit@bugs.kde.org")) { - bugsLabel->setText(i18n("Please use https://bugs.kde.org to report bugs.\n")); - } else { - QUrl bugUrl(bugAddress); - if (bugUrl.scheme().isEmpty()) { - bugUrl.setScheme(QStringLiteral("mailto")); - } - bugsLabel->setText(i18n("Please report bugs to %2.\n", - bugUrl.toString(), bugAddress)); - } - } else { - bugsLabel->setText(aboutData.customAuthorRichText()); - } - bugsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - authorLayout->addWidget(bugsLabel); - } - - KDEPrivate::KAboutApplicationPersonModel *authorModel = - new KDEPrivate::KAboutApplicationPersonModel(aboutData.authors(), - aboutData.ocsProviderUrl(), - authorWidget); - - KDEPrivate::KAboutApplicationPersonListView *authorView = - new KDEPrivate::KAboutApplicationPersonListView(authorWidget); + QWidget *authorWidget = createAuthorsWidget(aboutData.authors(), aboutData.ocsProviderUrl(), + aboutData.customAuthorTextEnabled(), + aboutData.customAuthorRichText(), + aboutData.bugAddress(), q); - KDEPrivate::KAboutApplicationPersonListDelegate *authorDelegate = - new KDEPrivate::KAboutApplicationPersonListDelegate(authorView, authorView); - - authorView->setModel(authorModel); - authorView->setItemDelegate(authorDelegate); - authorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - authorLayout->addWidget(authorView); - - const QString authorPageTitle = (authorCount == 1) ? i18n("A&uthor") : i18n("A&uthors"); + const QString authorPageTitle = i18np("Author", "Authors", authorCount); tabWidget->addTab(authorWidget, authorPageTitle); } //And credits page... - const int creditsCount = aboutData.credits().count(); - if (creditsCount) { - QWidget *creditWidget = new QWidget(q); - QVBoxLayout *creditLayout = new QVBoxLayout(creditWidget); - creditLayout->setContentsMargins(0, 0, 0, 0); - - KDEPrivate::KAboutApplicationPersonModel *creditModel = - new KDEPrivate::KAboutApplicationPersonModel(aboutData.credits(), - aboutData.ocsProviderUrl(), - creditWidget); - - KDEPrivate::KAboutApplicationPersonListView *creditView = - new KDEPrivate::KAboutApplicationPersonListView(creditWidget); - - KDEPrivate::KAboutApplicationPersonListDelegate *creditDelegate = - new KDEPrivate::KAboutApplicationPersonListDelegate(creditView, creditView); - - creditView->setModel(creditModel); - creditView->setItemDelegate(creditDelegate); - creditView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - creditLayout->addWidget(creditView); - - tabWidget->addTab(creditWidget, i18n("&Thanks To")); + if (!aboutData.credits().isEmpty()) { + QWidget *creditWidget = createCreditWidget(aboutData.credits(), aboutData.ocsProviderUrl(), q); + tabWidget->addTab(creditWidget, i18n("Thanks To")); } //Finally, the optional translators page... - if (!(opt & HideTranslators)) { - const int translatorsCount = aboutData.translators().count(); - if (translatorsCount) { - QWidget *translatorWidget = new QWidget(q); - QVBoxLayout *translatorLayout = new QVBoxLayout(translatorWidget); - translatorLayout->setContentsMargins(0, 0, 0, 0); + if (!(opt & HideTranslators) && !aboutData.translators().isEmpty()) { + QWidget *translatorWidget = createTranslatorsWidget(aboutData.translators(), aboutData.ocsProviderUrl(), q); - KDEPrivate::KAboutApplicationPersonModel *translatorModel = - new KDEPrivate::KAboutApplicationPersonModel(aboutData.translators(), - aboutData.ocsProviderUrl(), - translatorWidget); - - KDEPrivate::KAboutApplicationPersonListView *translatorView = - new KDEPrivate::KAboutApplicationPersonListView(translatorWidget); - - KDEPrivate::KAboutApplicationPersonListDelegate *translatorDelegate = - new KDEPrivate::KAboutApplicationPersonListDelegate(translatorView, translatorView); - - translatorView->setModel(translatorModel); - translatorView->setItemDelegate(translatorDelegate); - translatorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - translatorLayout->addWidget(translatorView); - - QString aboutTranslationTeam = KAboutData::aboutTranslationTeam(); - if (!aboutTranslationTeam.isEmpty()) { - QLabel *translationTeamLabel = new QLabel(translatorWidget); - translationTeamLabel->setContentsMargins(4, 2, 4, 4); - translationTeamLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - translationTeamLabel->setWordWrap(true); - translationTeamLabel->setText(aboutTranslationTeam); - translationTeamLabel->setOpenExternalLinks(true); - translatorLayout->addWidget(translationTeamLabel); - //TODO: this could be displayed as a view item to save space - } - - tabWidget->addTab(translatorWidget, i18n("T&ranslation")); - } + tabWidget->addTab(translatorWidget, i18n("Translation")); } - QDialogButtonBox *buttonBox = new QDialogButtonBox; - buttonBox->setStandardButtons(QDialogButtonBox::Close); - connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept); - connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject); - - //And we jam everything together in a layout... - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(titleWidget); - mainLayout->addWidget(tabWidget); - mainLayout->addWidget(buttonBox); - q->setLayout(mainLayout); + createForm(titleWidget, tabWidget, q); } KAboutApplicationDialog::~KAboutApplicationDialog() @@ -305,44 +150,3 @@ // complains bitterly about it qDeleteAll(findChildren()); } - -void KAboutApplicationDialog::Private::_k_showLicense(const QString &number) -{ - QDialog *dialog = new QDialog(q); - dialog->setAttribute(Qt::WA_DeleteOnClose); - QVBoxLayout *layout = new QVBoxLayout; - dialog->setLayout(layout); - - dialog->setWindowTitle(i18n("License Agreement")); - - const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); - QFontMetrics metrics(font); - - const QString licenseText = aboutData.licenses().at(number.toInt()).text(); - QTextBrowser *licenseBrowser = new QTextBrowser(dialog); - licenseBrowser->setFont(font); - licenseBrowser->setLineWrapMode(QTextEdit::NoWrap); - licenseBrowser->setText(licenseText); - layout->addWidget(licenseBrowser); - - QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); - buttonBox->setStandardButtons(QDialogButtonBox::Close); - connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); - connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); - layout->addWidget(buttonBox); - - // try to set up the dialog such that the full width of the - // document is visible without horizontal scroll-bars being required - const int marginHint = dialog->style()->pixelMetric(QStyle::PM_DefaultChildMargin); - const qreal idealWidth = licenseBrowser->document()->idealWidth() + (2 * marginHint) - + licenseBrowser->verticalScrollBar()->width() * 2; - - // try to allow enough height for a reasonable number of lines to be shown - const int idealHeight = metrics.height() * 30; - - dialog->resize(dialog->sizeHint().expandedTo(QSize(qRound(idealWidth), idealHeight))); - dialog->adjustSize(); - dialog->show(); -} - -#include "moc_kaboutapplicationdialog.cpp" diff --git a/src/kaboutplugindialog.h b/src/kaboutplugindialog.h new file mode 100644 --- /dev/null +++ b/src/kaboutplugindialog.h @@ -0,0 +1,83 @@ +/* This file is part of the KDE libraries + Copyright 2019 Friedrich W. H. Kossebau + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KABOUT_PLUGIN_DIALOG_H +#define KABOUT_PLUGIN_DIALOG_H + +#include +// Qt +#include + +class KPluginMetaData; +class KAboutPluginDialogPrivate; + +/** + * @class KAboutPluginDialog kaboutplugindialog.h KAboutPluginDialog + * + * @short Standard "About Plugin" dialog box. + * + * This class provides a standard "About Plugin" dialog box. + * + * @since 5.65 + */ + +class KXMLGUI_EXPORT KAboutPluginDialog : public QDialog +{ + Q_OBJECT + +public: + /** + * Defines some options which can be applied to the about dialog + */ + enum Option { + NoOptions = 0x0, ///< No options, show the standard about dialog + HideTranslators = 0x1, ///< Don't show the translators tab + }; + Q_DECLARE_FLAGS(Options, Option) + Q_FLAG(Options) + + /** + * Constructor. Creates a fully featured "About Plugin" dialog box. + * + * @param pluginMetaData the data about the plugin to show in the dialog. + * @param options options to apply, such as hiding the translators tab. + * @param parent The parent of the dialog box. You should use the + * toplevel window so that the dialog becomes centered. + */ + explicit KAboutPluginDialog(const KPluginMetaData &pluginMetaData, Options options, QWidget *parent = nullptr); + + /** + * Constructor. Creates a fully featured "About Plugin" dialog box. + * + * @param pluginMetaData the data about the plugin to show in the dialog. + * @param parent The parent of the dialog box. You should use the + * toplevel window so that the dialog becomes centered. + */ + explicit KAboutPluginDialog(const KPluginMetaData &pluginMetaData, QWidget *parent = nullptr); + + ~KAboutPluginDialog() override; + +private: + const QScopedPointer d; + + Q_DISABLE_COPY(KAboutPluginDialog) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(KAboutPluginDialog::Options) + +#endif diff --git a/src/kaboutplugindialog.cpp b/src/kaboutplugindialog.cpp new file mode 100644 --- /dev/null +++ b/src/kaboutplugindialog.cpp @@ -0,0 +1,123 @@ +/* This file is part of the KDE libraries + Copyright (C) 2007 Urs Wolfer + Copyright (C) 2008, 2019 Friedrich W. H. Kossebau + Copyright (C) 2010 Teo Mrnjavac + + Parts of this class have been take from the KAboutApplication class, which was + Copyright (C) 2000 Waldo Bastian (bastian@kde.org) and Espen Sand (espen@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kaboutplugindialog.h" + +#include "kabstractaboutdialog_p.h" +// KF +#include +#include +#include +#include +// Qt +#include +#include + +class KAboutPluginDialogPrivate : public KAbstractAboutDialogPrivate +{ +public: + KAboutPluginDialogPrivate(const KPluginMetaData &pluginMetaData, KAboutPluginDialog *parent) + : q(parent) + , pluginMetaData(pluginMetaData) + , pluginLicense(KAboutLicense::byKeyword(pluginMetaData.license())) + {} + + void init(KAboutPluginDialog::Options opt); + +public: + KAboutPluginDialog * const q; + + const KPluginMetaData pluginMetaData; + const KAboutLicense pluginLicense; +}; + + +KAboutPluginDialog::KAboutPluginDialog(const KPluginMetaData &pluginMetaData, QWidget *parent) + : QDialog(parent) + , d(new KAboutPluginDialogPrivate(pluginMetaData, this)) +{ + d->init(NoOptions); +} + +KAboutPluginDialog::KAboutPluginDialog(const KPluginMetaData &pluginMetaData, Options opt, QWidget *parent) + : QDialog(parent) + , d(new KAboutPluginDialogPrivate(pluginMetaData,this)) +{ + d->init(opt); +} + +KAboutPluginDialog::~KAboutPluginDialog() +{ + // The delegates want to be deleted before the items it created + qDeleteAll(findChildren()); +} + +void KAboutPluginDialogPrivate::init(KAboutPluginDialog::Options opt) +{ + q->setWindowTitle(i18n("About %1", pluginMetaData.name())); + q->setModal(false); + + //Set up the title widget... + const QIcon pluginIcon = !pluginMetaData.iconName().isEmpty() ? QIcon::fromTheme(pluginMetaData.iconName()) : + qApp->windowIcon(); + QWidget *titleWidget = createTitleWidget(pluginIcon.pixmap(48, 48), + pluginMetaData.name(), pluginMetaData.version(), q); + + //Then the tab bar... + QTabWidget *tabWidget = new QTabWidget; + tabWidget->setUsesScrollButtons(false); + + //Set up the first page... + QWidget *aboutWidget = createAboutWidget(pluginMetaData.description(), pluginMetaData.extraInformation(), + pluginMetaData.copyrightText(), pluginMetaData.website(), + {pluginLicense}, q); + + tabWidget->addTab(aboutWidget, i18n("About")); + + //And here we go, authors page... + const int authorCount = pluginMetaData.authors().count(); + if (authorCount) { + // TODO: add bug report address to plugin metadata + QWidget *authorWidget = createAuthorsWidget(pluginMetaData.authors(), QString(), + false, + QString(), + QString(), q); + + const QString authorPageTitle = i18np("Author", "Authors", authorCount); + tabWidget->addTab(authorWidget, authorPageTitle); + } + + //And credits page... + if (!pluginMetaData.otherContributors().isEmpty()) { + QWidget *creditWidget = createCreditWidget(pluginMetaData.otherContributors(), QString(), q); + tabWidget->addTab(creditWidget, i18n("Thanks To")); + } + + //Finally, the optional translators page... + if (!(opt & KAboutPluginDialog::HideTranslators) && !pluginMetaData.translators().isEmpty()) { + QWidget *translatorWidget = createTranslatorsWidget(pluginMetaData.translators(), QString(), q); + tabWidget->addTab(translatorWidget, i18n("Translation")); + } + + createForm(titleWidget, tabWidget, q); +} diff --git a/src/kabstractaboutdialog_p.h b/src/kabstractaboutdialog_p.h new file mode 100644 --- /dev/null +++ b/src/kabstractaboutdialog_p.h @@ -0,0 +1,66 @@ +/* This file is part of the KDE libraries + Copyright 2019 Friedrich W. H. Kossebau + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KABSTRACTABOUTDIALOG_P_H +#define KABSTRACTABOUTDIALOG_P_H + +#include + +class QDialog; +class QWidget; +class QPixmap; + +/** + * @internal + * + * Private base class implementing util methods for assembling an About dialog. + */ +class KAbstractAboutDialogPrivate +{ +public: + KAbstractAboutDialogPrivate() = default; + ~KAbstractAboutDialogPrivate() = default; + +public: + QWidget *createTitleWidget(const QPixmap &pixmap, + const QString &displayName, + const QString &version, + QWidget *parent); + QWidget *createAboutWidget(const QString &shortDescription, + const QString &otherText, + const QString ©rightStatement, + const QString &homepage, + const QList &licenses, + QWidget *parent); + QWidget *createAuthorsWidget(const QList &authors, + const QString &ocsProviderUrl, + bool customAuthorTextEnabled, + const QString &customAuthorRichText, + const QString &bugAddress, + QWidget *parent); + QWidget *createCreditWidget(const QList &credits, + const QString &ocsProviderUrl, + QWidget *parent); + QWidget *createTranslatorsWidget(const QList &translators, + const QString &ocsProviderUrl, + QWidget *parent); + void createForm(QWidget *titleWidget, QWidget *tabWidget, + QDialog *dialog); +}; + +#endif diff --git a/src/kabstractaboutdialog_p.cpp b/src/kabstractaboutdialog_p.cpp new file mode 100644 --- /dev/null +++ b/src/kabstractaboutdialog_p.cpp @@ -0,0 +1,233 @@ +/* This file is part of the KDE libraries + Copyright (C) 2007 Urs Wolfer + Copyright (C) 2008,2019 Friedrich W. H. Kossebau + Copyright (C) 2010 Teo Mrnjavac + + Parts of this class have been take from the KAboutApplication class, which was + Copyright (C) 2000 Waldo Bastian (bastian@kde.org) and Espen Sand (espen@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kabstractaboutdialog_p.h" + +#include "kaboutapplicationpersonmodel_p.h" +#include "kaboutapplicationpersonlistview_p.h" +#include "kaboutapplicationpersonlistdelegate_p.h" +#include "klicensedialog_p.h" +// KF +#include +#include +// Qt +#include +#include +#include +#include + +QWidget *KAbstractAboutDialogPrivate::createTitleWidget(const QPixmap &pixmap, + const QString &displayName, + const QString &version, + QWidget *parent) +{ + KTitleWidget *titleWidget = new KTitleWidget(parent); + + titleWidget->setPixmap(pixmap, KTitleWidget::ImageLeft); + titleWidget->setText(i18n("%1
Version %2", displayName, version)); + + return titleWidget; +} + +QWidget *KAbstractAboutDialogPrivate::createAboutWidget(const QString &shortDescription, + const QString &otherText, + const QString ©rightStatement, + const QString &homepage, + const QList &licenses, + QWidget *parent) +{ + QWidget *aboutWidget = new QWidget(parent); + QVBoxLayout *aboutLayout = new QVBoxLayout(aboutWidget); + + //Set up the first page... + QString aboutPageText = shortDescription + QLatin1Char('\n'); + + if (!otherText.isEmpty()) { + aboutPageText += QLatin1Char('\n') + otherText + QLatin1Char('\n'); + } + + if (!copyrightStatement.isEmpty()) { + aboutPageText += QLatin1Char('\n') + copyrightStatement + QLatin1Char('\n'); + } + + if (!homepage.isEmpty()) { + aboutPageText += QLatin1Char('\n') + QStringLiteral("%1").arg(homepage) + QLatin1Char('\n'); + } + aboutPageText = aboutPageText.trimmed(); + + QLabel *aboutLabel = new QLabel; + aboutLabel->setWordWrap(true); + aboutLabel->setOpenExternalLinks(true); + aboutLabel->setText(aboutPageText.replace(QLatin1Char('\n'), QStringLiteral("
"))); + aboutLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + + aboutLayout->addStretch(); + aboutLayout->addWidget(aboutLabel); + + const int licenseCount = licenses.count(); + for (int i = 0; i < licenseCount; ++i) { + const KAboutLicense &license = licenses.at(i); + + QLabel *showLicenseLabel = new QLabel; + showLicenseLabel->setText(QStringLiteral("%2").arg(QString::number(i), + i18n("License: %1", license.name(KAboutLicense::FullName)))); + showLicenseLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + QObject::connect(showLicenseLabel, &QLabel::linkActivated, parent, [license, parent]() { + auto *dialog = new KLicenseDialog(license, parent); + dialog->show(); + }); + + aboutLayout->addWidget(showLicenseLabel); + } + + aboutLayout->addStretch(); + + return aboutWidget; +} + +QWidget *KAbstractAboutDialogPrivate::createAuthorsWidget(const QList &authors, + const QString &ocsProviderUrl, + bool customAuthorTextEnabled, + const QString &customAuthorRichText, + const QString &bugAddress, + QWidget *parent) +{ + QWidget *authorWidget = new QWidget(parent); + QVBoxLayout *authorLayout = new QVBoxLayout(authorWidget); + authorLayout->setContentsMargins(0, 0, 0, 0); + + if (!customAuthorTextEnabled || !customAuthorRichText.isEmpty()) { + QLabel *bugsLabel = new QLabel(authorWidget); + bugsLabel->setContentsMargins(4, 2, 0, 4); + bugsLabel->setOpenExternalLinks(true); + if (!customAuthorTextEnabled) { + if (bugAddress.isEmpty() || bugAddress == QLatin1String("submit@bugs.kde.org")) { + bugsLabel->setText(i18n("Please use https://bugs.kde.org to report bugs.\n")); + } else { + QUrl bugUrl(bugAddress); + if (bugUrl.scheme().isEmpty()) { + bugUrl.setScheme(QStringLiteral("mailto")); + } + bugsLabel->setText(i18n("Please report bugs to %2.\n", + bugUrl.toString(), bugAddress)); + } + } else { + bugsLabel->setText(customAuthorRichText); + } + bugsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + authorLayout->addWidget(bugsLabel); + } + + KDEPrivate::KAboutApplicationPersonModel *authorModel = + new KDEPrivate::KAboutApplicationPersonModel(authors, ocsProviderUrl, authorWidget); + + KDEPrivate::KAboutApplicationPersonListView *authorView = + new KDEPrivate::KAboutApplicationPersonListView(authorWidget); + + KDEPrivate::KAboutApplicationPersonListDelegate *authorDelegate = + new KDEPrivate::KAboutApplicationPersonListDelegate(authorView, authorView); + + authorView->setModel(authorModel); + authorView->setItemDelegate(authorDelegate); + authorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + authorLayout->addWidget(authorView); + + return authorWidget; +} + +QWidget *KAbstractAboutDialogPrivate::createCreditWidget(const QList &credits, + const QString &ocsProviderUrl, + QWidget *parent) +{ + QWidget *creditWidget = new QWidget(parent); + QVBoxLayout *creditLayout = new QVBoxLayout(creditWidget); + creditLayout->setContentsMargins(0, 0, 0, 0); + + KDEPrivate::KAboutApplicationPersonModel *creditModel = + new KDEPrivate::KAboutApplicationPersonModel(credits, ocsProviderUrl, creditWidget); + + KDEPrivate::KAboutApplicationPersonListView *creditView = + new KDEPrivate::KAboutApplicationPersonListView(creditWidget); + + KDEPrivate::KAboutApplicationPersonListDelegate *creditDelegate = + new KDEPrivate::KAboutApplicationPersonListDelegate(creditView, creditView); + + creditView->setModel(creditModel); + creditView->setItemDelegate(creditDelegate); + creditView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + creditLayout->addWidget(creditView); + + return creditWidget; +} + +QWidget *KAbstractAboutDialogPrivate::createTranslatorsWidget(const QList &translators, + const QString &ocsProviderUrl, + QWidget *parent) +{ + QWidget *translatorWidget = new QWidget(parent); + QVBoxLayout *translatorLayout = new QVBoxLayout(translatorWidget); + translatorLayout->setContentsMargins(0, 0, 0, 0); + + KDEPrivate::KAboutApplicationPersonModel *translatorModel = + new KDEPrivate::KAboutApplicationPersonModel(translators, ocsProviderUrl, translatorWidget); + + KDEPrivate::KAboutApplicationPersonListView *translatorView = + new KDEPrivate::KAboutApplicationPersonListView(translatorWidget); + + KDEPrivate::KAboutApplicationPersonListDelegate *translatorDelegate = + new KDEPrivate::KAboutApplicationPersonListDelegate(translatorView, translatorView); + + translatorView->setModel(translatorModel); + translatorView->setItemDelegate(translatorDelegate); + translatorView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + translatorLayout->addWidget(translatorView); + + QString aboutTranslationTeam = KAboutData::aboutTranslationTeam(); + if (!aboutTranslationTeam.isEmpty()) { + QLabel *translationTeamLabel = new QLabel(translatorWidget); + translationTeamLabel->setContentsMargins(4, 2, 4, 4); + translationTeamLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + translationTeamLabel->setWordWrap(true); + translationTeamLabel->setText(aboutTranslationTeam); + translationTeamLabel->setOpenExternalLinks(true); + translatorLayout->addWidget(translationTeamLabel); + //TODO: this could be displayed as a view item to save space + } + + return translatorWidget; +} + +void KAbstractAboutDialogPrivate::createForm(QWidget *titleWidget, QWidget *tabWidget, + QDialog *dialog) +{ + QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Close); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); + + //And we jam everything together in a layout... + QVBoxLayout *mainLayout = new QVBoxLayout(dialog); + mainLayout->addWidget(titleWidget); + mainLayout->addWidget(tabWidget); + mainLayout->addWidget(buttonBox); +} diff --git a/src/klicensedialog_p.h b/src/klicensedialog_p.h new file mode 100644 --- /dev/null +++ b/src/klicensedialog_p.h @@ -0,0 +1,45 @@ +/* This file is part of the KDE libraries + Copyright 2019 Friedrich W. H. Kossebau + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KLICENSEDIALOG_P_H +#define KLICENSEDIALOG_P_H + +// Qt +#include + +class KAboutLicense; + +/** + * @internal + * + * A dialog to display a license + */ +class KLicenseDialog : public QDialog +{ + Q_OBJECT + +public: + explicit KLicenseDialog(const KAboutLicense &license, QWidget *parent = nullptr); + + ~KLicenseDialog() override; + +private: + Q_DISABLE_COPY(KLicenseDialog) +}; + +#endif diff --git a/src/klicensedialog_p.cpp b/src/klicensedialog_p.cpp new file mode 100644 --- /dev/null +++ b/src/klicensedialog_p.cpp @@ -0,0 +1,75 @@ +/* This file is part of the KDE libraries + Copyright (C) 2007 Urs Wolfer + Copyright (C) 2008 Friedrich W. H. Kossebau + Copyright (C) 2010 Teo Mrnjavac + + Parts of this class have been take from the KAboutApplication class, which was + Copyright (C) 2000 Waldo Bastian (bastian@kde.org) and Espen Sand (espen@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "klicensedialog_p.h" + +// KF +#include +#include +// Qt +#include +#include +#include +#include +#include +#include + +KLicenseDialog::KLicenseDialog(const KAboutLicense &license, QWidget *parent) + : QDialog(parent) +{ + setAttribute(Qt::WA_DeleteOnClose); + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + + setWindowTitle(i18n("License Agreement")); + + const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + + const QString licenseText = license.text(); + + QTextBrowser *licenseBrowser = new QTextBrowser(this); + licenseBrowser->setFont(font); + licenseBrowser->setLineWrapMode(QTextEdit::NoWrap); + licenseBrowser->setText(licenseText); + layout->addWidget(licenseBrowser); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Close); + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + layout->addWidget(buttonBox); + + // try to set up the dialog such that the full width of the + // document is visible without horizontal scroll-bars being required + const int marginHint = style()->pixelMetric(QStyle::PM_DefaultChildMargin); + const qreal idealWidth = licenseBrowser->document()->idealWidth() + (2 * marginHint) + + licenseBrowser->verticalScrollBar()->width() * 2; + + // try to allow enough height for a reasonable number of lines to be shown + QFontMetrics metrics(font); + const int idealHeight = metrics.height() * 30; + + resize(sizeHint().expandedTo(QSize(qRound(idealWidth), idealHeight))); +} + +KLicenseDialog::~KLicenseDialog() = default;