diff --git a/src/lib/kaboutdata.cpp b/src/lib/kaboutdata.cpp index 63210f0..89f04b6 100644 --- a/src/lib/kaboutdata.cpp +++ b/src/lib/kaboutdata.cpp @@ -1,1245 +1,1244 @@ /* * This file is part of the KDE Libraries * Copyright (C) 2000 Espen Sand (espen@kde.org) * Copyright (C) 2006 Nicolas GOUTTE * Copyright (C) 2008 Friedrich W. H. Kossebau * Copyright (C) 2010 Teo Mrnjavac * Copyright (C) 2017 Harald Sitter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 "kaboutdata.h" #include "kpluginmetadata.h" #include #include #include #include #include -#include #include #include #include #include #include #include #include #include Q_DECLARE_LOGGING_CATEGORY(KABOUTDATA) // logging category for this framework, default: log stuff >= warning Q_LOGGING_CATEGORY(KABOUTDATA, "kf5.kcoreaddons.kaboutdata", QtWarningMsg) class Q_DECL_HIDDEN KAboutPerson::Private { public: QString _name; QString _task; QString _emailAddress; QString _webAddress; QString _ocsUsername; }; KAboutPerson::KAboutPerson(const QString &_name, const QString &_task, const QString &_emailAddress, const QString &_webAddress, const QString &_ocsUsername) : d(new Private) { d->_name = _name; d->_task = _task; d->_emailAddress = _emailAddress; d->_webAddress = _webAddress; d->_ocsUsername = _ocsUsername; } KAboutPerson::KAboutPerson(const QString &_name, const QString &_email, bool) : d(new Private) { d->_name = _name; d->_emailAddress = _email; } KAboutPerson::KAboutPerson(const KAboutPerson &other): d(new Private) { *d = *other.d; } KAboutPerson::~KAboutPerson() { delete d; } QString KAboutPerson::name() const { return d->_name; } QString KAboutPerson::task() const { return d->_task; } QString KAboutPerson::emailAddress() const { return d->_emailAddress; } QString KAboutPerson::webAddress() const { return d->_webAddress; } QString KAboutPerson::ocsUsername() const { return d->_ocsUsername; } KAboutPerson &KAboutPerson::operator=(const KAboutPerson &other) { *d = *other.d; return *this; } KAboutPerson KAboutPerson::fromJSON(const QJsonObject &obj) { const QString name = KPluginMetaData::readTranslatedString(obj, QStringLiteral("Name")); const QString task = KPluginMetaData::readTranslatedString(obj, QStringLiteral("Task")); const QString email = obj[QStringLiteral("Email")].toString(); const QString website = obj[QStringLiteral("Website")].toString(); const QString userName = obj[QStringLiteral("UserName")].toString(); return KAboutPerson(name, task, email, website, userName); } class Q_DECL_HIDDEN KAboutLicense::Private : public QSharedData { public: Private(LicenseKey licenseType, VersionRestriction versionRestriction, const KAboutData *aboutData); Private(const Private &other); QString spdxID() const; LicenseKey _licenseKey; QString _licenseText; QString _pathToLicenseTextFile; VersionRestriction _versionRestriction; // needed for access to the possibly changing copyrightStatement() const KAboutData *_aboutData; }; KAboutLicense::Private::Private(LicenseKey licenseType, VersionRestriction versionRestriction, const KAboutData *aboutData) : QSharedData(), _licenseKey(licenseType), _versionRestriction(versionRestriction), _aboutData(aboutData) { } KAboutLicense::Private::Private(const KAboutLicense::Private &other) : QSharedData(other), _licenseKey(other._licenseKey), _licenseText(other._licenseText), _pathToLicenseTextFile(other._pathToLicenseTextFile), _versionRestriction(other._versionRestriction), _aboutData(other._aboutData) {} QString KAboutLicense::Private::spdxID() const { switch (_licenseKey) { case KAboutLicense::GPL_V2: return QStringLiteral("GPL-2.0"); case KAboutLicense::LGPL_V2: return QStringLiteral("LGPL-2.0"); case KAboutLicense::BSDL: return QStringLiteral("BSD-2-Clause"); case KAboutLicense::Artistic: return QStringLiteral("Artistic-1.0"); case KAboutLicense::QPL_V1_0: return QStringLiteral("QPL-1.0"); case KAboutLicense::GPL_V3: return QStringLiteral("GPL-3.0"); case KAboutLicense::LGPL_V3: return QStringLiteral("LGPL-3.0"); case KAboutLicense::LGPL_V2_1: return QStringLiteral("LGPL-2.1"); case KAboutLicense::Custom: case KAboutLicense::File: case KAboutLicense::Unknown: return QString(); } return QString(); } KAboutLicense::KAboutLicense() : d(new Private(Unknown, {}, nullptr)) {} KAboutLicense::KAboutLicense(LicenseKey licenseType, VersionRestriction versionRestriction, const KAboutData *aboutData) : d(new Private(licenseType, versionRestriction, aboutData)) { } KAboutLicense::KAboutLicense(LicenseKey licenseType, const KAboutData *aboutData) : d(new Private(licenseType, OnlyThisVersion, aboutData)) { } KAboutLicense::KAboutLicense(const KAboutData *aboutData) : d(new Private(Unknown, OnlyThisVersion, aboutData)) { } KAboutLicense::KAboutLicense(const KAboutLicense &other) : d(other.d) { } KAboutLicense::~KAboutLicense() {} void KAboutLicense::setLicenseFromPath(const QString &pathToFile) { d->_licenseKey = KAboutLicense::File; d->_pathToLicenseTextFile = pathToFile; } void KAboutLicense::setLicenseFromText(const QString &licenseText) { d->_licenseKey = KAboutLicense::Custom; d->_licenseText = licenseText; } QString KAboutLicense::text() const { QString result; const QString lineFeed = QStringLiteral("\n\n"); if (d->_aboutData && !d->_aboutData->copyrightStatement().isEmpty()) { result = d->_aboutData->copyrightStatement() + lineFeed; } bool knownLicense = false; QString pathToFile; // rel path if known license switch (d->_licenseKey) { case KAboutLicense::File: pathToFile = d->_pathToLicenseTextFile; break; case KAboutLicense::GPL_V2: knownLicense = true; pathToFile = QStringLiteral("GPL_V2"); break; case KAboutLicense::LGPL_V2: knownLicense = true; pathToFile = QStringLiteral("LGPL_V2"); break; case KAboutLicense::BSDL: knownLicense = true; pathToFile = QStringLiteral("BSD"); break; case KAboutLicense::Artistic: knownLicense = true; pathToFile = QStringLiteral("ARTISTIC"); break; case KAboutLicense::QPL_V1_0: knownLicense = true; pathToFile = QStringLiteral("QPL_V1.0"); break; case KAboutLicense::GPL_V3: knownLicense = true; pathToFile = QStringLiteral("GPL_V3"); break; case KAboutLicense::LGPL_V3: knownLicense = true; pathToFile = QStringLiteral("LGPL_V3"); break; case KAboutLicense::LGPL_V2_1: knownLicense = true; pathToFile = QStringLiteral("LGPL_V21"); break; case KAboutLicense::Custom: if (!d->_licenseText.isEmpty()) { result = d->_licenseText; break; } Q_FALLTHROUGH(); // fall through default: result += QCoreApplication::translate( "KAboutLicense", "No licensing terms for this program have been specified.\n" "Please check the documentation or the source for any\n" "licensing terms.\n"); } if (knownLicense) { pathToFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString::fromLatin1("kf5/licenses/") + pathToFile); result += QCoreApplication::translate( "KAboutLicense", "This program is distributed under the terms of the %1.").arg(name(KAboutLicense::ShortName)); if (!pathToFile.isEmpty()) { result += lineFeed; } } if (!pathToFile.isEmpty()) { QFile file(pathToFile); if (file.open(QIODevice::ReadOnly)) { QTextStream str(&file); result += str.readAll(); } } return result; } QString KAboutLicense::spdx() const { // SPDX licenses are comprised of an identifier (e.g. GPL-2.0), an optional + to denote 'or // later versions' and optional ' WITH $exception' to denote standardized exceptions from the // core license. As we do not offer exceptions we effectively only return GPL-2.0 or GPL-2.0+, // this may change in the future. To that end the documentation makes no assertations about the // actual content of the SPDX license expression we return. // Expressions can in theory also contain AND, OR and () to build constructs involving more than // one license. As this is outside the scope of a single license object we'll ignore this here // for now. // The expecation is that the return value is only run through spec-compliant parsers, so this // can potentially be changed. auto id = d->spdxID(); if (id.isNull()) { // Guard against potential future changes which would allow 'Foo+' as input. return id; } return d->_versionRestriction == OrLaterVersions ? id.append(QLatin1Char('+')) : id; } QString KAboutLicense::name(KAboutLicense::NameFormat formatName) const { QString licenseShort; QString licenseFull; switch (d->_licenseKey) { case KAboutLicense::GPL_V2: licenseShort = QCoreApplication::translate("KAboutLicense", "GPL v2", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "GNU General Public License Version 2", "@item license"); break; case KAboutLicense::LGPL_V2: licenseShort = QCoreApplication::translate("KAboutLicense", "LGPL v2", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "GNU Lesser General Public License Version 2", "@item license"); break; case KAboutLicense::BSDL: licenseShort = QCoreApplication::translate("KAboutLicense", "BSD License", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "BSD License", "@item license"); break; case KAboutLicense::Artistic: licenseShort = QCoreApplication::translate("KAboutLicense", "Artistic License", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "Artistic License", "@item license"); break; case KAboutLicense::QPL_V1_0: licenseShort = QCoreApplication::translate("KAboutLicense", "QPL v1.0", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "Q Public License", "@item license"); break; case KAboutLicense::GPL_V3: licenseShort = QCoreApplication::translate("KAboutLicense", "GPL v3", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "GNU General Public License Version 3", "@item license"); break; case KAboutLicense::LGPL_V3: licenseShort = QCoreApplication::translate("KAboutLicense", "LGPL v3", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "GNU Lesser General Public License Version 3", "@item license"); break; case KAboutLicense::LGPL_V2_1: licenseShort = QCoreApplication::translate("KAboutLicense", "LGPL v2.1", "@item license (short name)"); licenseFull = QCoreApplication::translate("KAboutLicense", "GNU Lesser General Public License Version 2.1", "@item license"); break; case KAboutLicense::Custom: case KAboutLicense::File: licenseShort = licenseFull = QCoreApplication::translate("KAboutLicense", "Custom", "@item license"); break; default: licenseShort = licenseFull = QCoreApplication::translate("KAboutLicense", "Not specified", "@item license"); } const QString result = (formatName == KAboutLicense::ShortName) ? licenseShort : (formatName == KAboutLicense::FullName) ? licenseFull : QString(); return result; } KAboutLicense &KAboutLicense::operator=(const KAboutLicense &other) { d = other.d; return *this; } KAboutLicense::LicenseKey KAboutLicense::key() const { return d->_licenseKey; } KAboutLicense KAboutLicense::byKeyword(const QString &rawKeyword) { // Setup keyword->enum dictionary on first call. // Use normalized keywords, by the algorithm below. static const QHash licenseDict { { "gpl", KAboutLicense::GPL }, { "gplv2", KAboutLicense::GPL_V2 }, { "gplv2+", KAboutLicense::GPL_V2 }, { "gpl20", KAboutLicense::GPL_V2 }, { "gpl20+", KAboutLicense::GPL_V2 }, { "lgpl", KAboutLicense::LGPL }, { "lgplv2", KAboutLicense::LGPL_V2 }, { "lgplv2+", KAboutLicense::LGPL_V2 }, { "lgpl20", KAboutLicense::LGPL_V2 }, { "lgpl20+", KAboutLicense::LGPL_V2 }, { "bsd", KAboutLicense::BSDL }, { "bsd2clause", KAboutLicense::BSDL }, { "artistic", KAboutLicense::Artistic }, { "artistic10", KAboutLicense::Artistic }, { "qpl", KAboutLicense::QPL }, { "qplv1", KAboutLicense::QPL_V1_0 }, { "qplv10", KAboutLicense::QPL_V1_0 }, { "qpl10", KAboutLicense::QPL_V1_0 }, { "gplv3", KAboutLicense::GPL_V3 }, { "gplv3+", KAboutLicense::GPL_V3 }, { "gpl30", KAboutLicense::GPL_V3 }, { "gpl30+", KAboutLicense::GPL_V3 }, { "lgplv3", KAboutLicense::LGPL_V3 }, { "lgplv3+", KAboutLicense::LGPL_V3 }, { "lgpl30", KAboutLicense::LGPL_V3 }, { "lgpl30+", KAboutLicense::LGPL_V3 }, { "lgplv21", KAboutLicense::LGPL_V2_1 }, { "lgplv21+", KAboutLicense::LGPL_V2_1 }, { "lgpl21", KAboutLicense::LGPL_V2_1 }, { "lgpl21+", KAboutLicense::LGPL_V2_1 }, }; // Normalize keyword. QString keyword = rawKeyword; keyword = keyword.toLower(); keyword.remove(QLatin1Char(' ')); keyword.remove(QLatin1Char('.')); keyword.remove(QLatin1Char('-')); LicenseKey license = licenseDict.value(keyword.toLatin1(), KAboutLicense::Custom); auto restriction = keyword.endsWith(QLatin1Char('+')) ? OrLaterVersions : OnlyThisVersion; return KAboutLicense(license, restriction, nullptr); } class Q_DECL_HIDDEN KAboutData::Private { public: Private() : customAuthorTextEnabled(false) {} QString _componentName; QString _displayName; QString _shortDescription; QString _copyrightStatement; QString _otherText; QString _homepageAddress; QList _authorList; QList _creditList; QList _translatorList; QList _licenseList; QString productName; QString programIconName; QVariant programLogo; QString customAuthorPlainText, customAuthorRichText; bool customAuthorTextEnabled; QString organizationDomain; QString _ocsProviderUrl; QString desktopFileName; // Everything dr.konqi needs, we store as utf-8, so we // can just give it a pointer, w/o any allocations. QByteArray _internalProgramName; QByteArray _version; QByteArray _bugAddress; static QList parseTranslators(const QString &translatorName, const QString &translatorEmail); }; KAboutData::KAboutData(const QString &_componentName, const QString &_displayName, const QString &_version, const QString &_shortDescription, enum KAboutLicense::LicenseKey licenseType, const QString &_copyrightStatement, const QString &text, const QString &homePageAddress, const QString &bugAddress ) : d(new Private) { d->_componentName = _componentName; int p = d->_componentName.indexOf(QLatin1Char('/')); if (p >= 0) { d->_componentName = d->_componentName.mid(p + 1); } d->_displayName = _displayName; if (!d->_displayName.isEmpty()) { // KComponentData("klauncher") gives empty program name d->_internalProgramName = _displayName.toUtf8(); } d->_version = _version.toUtf8(); d->_shortDescription = _shortDescription; d->_licenseList.append(KAboutLicense(licenseType, this)); d->_copyrightStatement = _copyrightStatement; d->_otherText = text; d->_homepageAddress = homePageAddress; d->_bugAddress = bugAddress.toUtf8(); QUrl homePageUrl(homePageAddress); if (!homePageUrl.isValid() || homePageUrl.scheme().isEmpty()) { // Default domain if nothing else is better homePageUrl.setUrl(QStringLiteral("https://kde.org/")); } const QChar dotChar(QLatin1Char('.')); QStringList hostComponents = homePageUrl.host().split(dotChar); // Remove leading component unless 2 (or less) components are present if (hostComponents.size() > 2) { hostComponents.removeFirst(); } d->organizationDomain = hostComponents.join(dotChar); // KF6: do not set a default desktopFileName value here, but remove this code and leave it empty // see KAboutData::desktopFileName() for details // desktop file name is reverse domain name std::reverse(hostComponents.begin(), hostComponents.end()); hostComponents.append(_componentName); d->desktopFileName = hostComponents.join(dotChar); } KAboutData::KAboutData(const QString &_componentName, const QString &_displayName, const QString &_version ) : d(new Private) { d->_componentName = _componentName; int p = d->_componentName.indexOf(QLatin1Char('/')); if (p >= 0) { d->_componentName = d->_componentName.mid(p + 1); } d->_displayName = _displayName; if (!d->_displayName.isEmpty()) { // KComponentData("klauncher") gives empty program name d->_internalProgramName = _displayName.toUtf8(); } d->_version = _version.toUtf8(); // match behaviour of other constructors d->_licenseList.append(KAboutLicense(KAboutLicense::Unknown, this)); d->_bugAddress = "submit@bugs.kde.org"; d->organizationDomain = QStringLiteral("kde.org"); // KF6: do not set a default desktopFileName value here, but remove this code and leave it empty // see KAboutData::desktopFileName() for details d->desktopFileName = QStringLiteral("org.kde.%1").arg(d->_componentName); } KAboutData::~KAboutData() { delete d; } KAboutData::KAboutData(const KAboutData &other): d(new Private) { *d = *other.d; QList::iterator it = d->_licenseList.begin(), itEnd = d->_licenseList.end(); for (; it != itEnd; ++it) { KAboutLicense &al = *it; al.d.detach(); al.d->_aboutData = this; } } KAboutData &KAboutData::operator=(const KAboutData &other) { if (this != &other) { *d = *other.d; QList::iterator it = d->_licenseList.begin(), itEnd = d->_licenseList.end(); for (; it != itEnd; ++it) { KAboutLicense &al = *it; al.d.detach(); al.d->_aboutData = this; } } return *this; } KAboutData KAboutData::fromPluginMetaData(const KPluginMetaData &plugin) { KAboutData ret(plugin.pluginId(), plugin.name(), plugin.version(), plugin.description(), KAboutLicense::byKeyword(plugin.license()).key(), plugin.copyrightText(), plugin.extraInformation(), plugin.website()); ret.d->programIconName = plugin.iconName(); ret.d->_authorList = plugin.authors(); ret.d->_translatorList = plugin.translators(); ret.d->_creditList = plugin.otherContributors(); return ret; } KAboutData &KAboutData::addAuthor(const QString &name, const QString &task, const QString &emailAddress, const QString &webAddress, const QString &ocsUsername) { d->_authorList.append(KAboutPerson(name, task, emailAddress, webAddress, ocsUsername)); return *this; } KAboutData &KAboutData::addCredit(const QString &name, const QString &task, const QString &emailAddress, const QString &webAddress, const QString &ocsUsername) { d->_creditList.append(KAboutPerson(name, task, emailAddress, webAddress, ocsUsername)); return *this; } KAboutData &KAboutData::setTranslator(const QString &name, const QString &emailAddress) { d->_translatorList = Private::parseTranslators(name, emailAddress); return *this; } KAboutData &KAboutData::setLicenseText(const QString &licenseText) { d->_licenseList[0] = KAboutLicense(this); d->_licenseList[0].setLicenseFromText(licenseText); return *this; } KAboutData &KAboutData::addLicenseText(const QString &licenseText) { // if the default license is unknown, overwrite instead of append KAboutLicense &firstLicense = d->_licenseList[0]; KAboutLicense newLicense(this); newLicense.setLicenseFromText(licenseText); if (d->_licenseList.count() == 1 && firstLicense.d->_licenseKey == KAboutLicense::Unknown) { firstLicense = newLicense; } else { d->_licenseList.append(newLicense); } return *this; } KAboutData &KAboutData::setLicenseTextFile(const QString &pathToFile) { d->_licenseList[0] = KAboutLicense(this); d->_licenseList[0].setLicenseFromPath(pathToFile); return *this; } KAboutData &KAboutData::addLicenseTextFile(const QString &pathToFile) { // if the default license is unknown, overwrite instead of append KAboutLicense &firstLicense = d->_licenseList[0]; KAboutLicense newLicense(this); newLicense.setLicenseFromPath(pathToFile); if (d->_licenseList.count() == 1 && firstLicense.d->_licenseKey == KAboutLicense::Unknown) { firstLicense = newLicense; } else { d->_licenseList.append(newLicense); } return *this; } KAboutData &KAboutData::setComponentName(const QString &componentName) { d->_componentName = componentName; return *this; } KAboutData &KAboutData::setDisplayName(const QString &_displayName) { d->_displayName = _displayName; d->_internalProgramName = _displayName.toUtf8(); return *this; } KAboutData &KAboutData::setOcsProvider(const QString &_ocsProviderUrl) { d->_ocsProviderUrl = _ocsProviderUrl; return *this; } KAboutData &KAboutData::setVersion(const QByteArray &_version) { d->_version = _version; return *this; } KAboutData &KAboutData::setShortDescription(const QString &_shortDescription) { d->_shortDescription = _shortDescription; return *this; } KAboutData &KAboutData::setLicense(KAboutLicense::LicenseKey licenseKey) { return setLicense(licenseKey, KAboutLicense::OnlyThisVersion); } KAboutData &KAboutData::setLicense(KAboutLicense::LicenseKey licenseKey, KAboutLicense::VersionRestriction versionRestriction) { d->_licenseList[0] = KAboutLicense(licenseKey, versionRestriction, this); return *this; } KAboutData &KAboutData::addLicense(KAboutLicense::LicenseKey licenseKey) { return addLicense(licenseKey, KAboutLicense::OnlyThisVersion); } KAboutData &KAboutData::addLicense(KAboutLicense::LicenseKey licenseKey, KAboutLicense::VersionRestriction versionRestriction) { // if the default license is unknown, overwrite instead of append KAboutLicense &firstLicense = d->_licenseList[0]; if (d->_licenseList.count() == 1 && firstLicense.d->_licenseKey == KAboutLicense::Unknown) { firstLicense = KAboutLicense(licenseKey, versionRestriction, this); } else { d->_licenseList.append(KAboutLicense(licenseKey, versionRestriction, this)); } return *this; } KAboutData &KAboutData::setCopyrightStatement(const QString &_copyrightStatement) { d->_copyrightStatement = _copyrightStatement; return *this; } KAboutData &KAboutData::setOtherText(const QString &_otherText) { d->_otherText = _otherText; return *this; } KAboutData &KAboutData::setHomepage(const QString &homepage) { d->_homepageAddress = homepage; return *this; } KAboutData &KAboutData::setBugAddress(const QByteArray &_bugAddress) { d->_bugAddress = _bugAddress; return *this; } KAboutData &KAboutData::setOrganizationDomain(const QByteArray &domain) { d->organizationDomain = QString::fromLatin1(domain.data()); return *this; } KAboutData &KAboutData::setProductName(const QByteArray &_productName) { d->productName = QString::fromUtf8(_productName.data()); return *this; } QString KAboutData::componentName() const { return d->_componentName; } QString KAboutData::productName() const { if (!d->productName.isEmpty()) { return d->productName; } return componentName(); } QString KAboutData::displayName() const { if (!d->_displayName.isEmpty()) { return d->_displayName; } return componentName(); } /// @internal /// Return the program name. It is always pre-allocated. /// Needed for KCrash in particular. const char *KAboutData::internalProgramName() const { return d->_internalProgramName.constData(); } QString KAboutData::programIconName() const { return d->programIconName.isEmpty() ? componentName() : d->programIconName; } KAboutData &KAboutData::setProgramIconName(const QString &iconName) { d->programIconName = iconName; return *this; } QVariant KAboutData::programLogo() const { return d->programLogo; } KAboutData &KAboutData::setProgramLogo(const QVariant &image) { d->programLogo = image; return *this; } QString KAboutData::ocsProviderUrl() const { return d->_ocsProviderUrl; } QString KAboutData::version() const { return QString::fromUtf8(d->_version.data()); } /// @internal /// Return the untranslated and uninterpreted (to UTF8) string /// for the version information. Used in particular for KCrash. const char *KAboutData::internalVersion() const { return d->_version.constData(); } QString KAboutData::shortDescription() const { return d->_shortDescription; } QString KAboutData::homepage() const { return d->_homepageAddress; } QString KAboutData::bugAddress() const { return QString::fromUtf8(d->_bugAddress.constData()); } QString KAboutData::organizationDomain() const { return d->organizationDomain; } /// @internal /// Return the untranslated and uninterpreted (to UTF8) string /// for the bug mail address. Used in particular for KCrash. const char *KAboutData::internalBugAddress() const { if (d->_bugAddress.isEmpty()) { return nullptr; } return d->_bugAddress.constData(); } QList KAboutData::authors() const { return d->_authorList; } QList KAboutData::credits() const { return d->_creditList; } QList KAboutData::Private::parseTranslators(const QString &translatorName, const QString &translatorEmail) { QList personList; if (translatorName.isEmpty() || translatorName == QStringLiteral("Your names")) { return personList; } const QStringList nameList(translatorName.split(QLatin1Char(','))); QStringList emailList; if (!translatorEmail.isEmpty() && translatorEmail != QStringLiteral("Your emails")) { emailList = translatorEmail.split(QLatin1Char(','), QString::KeepEmptyParts); } QStringList::const_iterator nit; QStringList::const_iterator eit = emailList.constBegin(); for (nit = nameList.constBegin(); nit != nameList.constEnd(); ++nit) { QString email; if (eit != emailList.constEnd()) { email = *eit; ++eit; } personList.append(KAboutPerson((*nit).trimmed(), email.trimmed(), true)); } return personList; } QList KAboutData::translators() const { return d->_translatorList; } QString KAboutData::aboutTranslationTeam() { return QCoreApplication::translate( "KAboutData", "

KDE is translated into many languages thanks to the work " "of the translation teams all over the world.

" "

For more information on KDE internationalization " "visit https://l10n.kde.org

", "replace this with information about your translation team" ); } QString KAboutData::otherText() const { return d->_otherText; } QList KAboutData::licenses() const { return d->_licenseList; } QString KAboutData::copyrightStatement() const { return d->_copyrightStatement; } QString KAboutData::customAuthorPlainText() const { return d->customAuthorPlainText; } QString KAboutData::customAuthorRichText() const { return d->customAuthorRichText; } bool KAboutData::customAuthorTextEnabled() const { return d->customAuthorTextEnabled; } KAboutData &KAboutData::setCustomAuthorText(const QString &plainText, const QString &richText) { d->customAuthorPlainText = plainText; d->customAuthorRichText = richText; d->customAuthorTextEnabled = true; return *this; } KAboutData &KAboutData::unsetCustomAuthorText() { d->customAuthorPlainText = QString(); d->customAuthorRichText = QString(); d->customAuthorTextEnabled = false; return *this; } KAboutData &KAboutData::setDesktopFileName(const QString &desktopFileName) { d->desktopFileName = desktopFileName; return *this; } QString KAboutData::desktopFileName() const { return d->desktopFileName; // KF6: switch to this code and adapt API dox #if 0 // if desktopFileName has been explicitly set, use that value if (!d->desktopFileName.isEmpty()) { return d->desktopFileName; } // return a string calculated on-the-fly from the current org domain & component name const QChar dotChar(QLatin1Char('.')); QStringList hostComponents = d->organizationDomain.split(dotChar); // desktop file name is reverse domain name std::reverse(hostComponents.begin(), hostComponents.end()); hostComponents.append(componentName()); return hostComponents.join(dotChar); #endif } class KAboutDataRegistry { public: KAboutDataRegistry() : m_appData(nullptr) {} ~KAboutDataRegistry() { delete m_appData; qDeleteAll(m_pluginData); } KAboutData *m_appData; QHash m_pluginData; }; Q_GLOBAL_STATIC(KAboutDataRegistry, s_registry) namespace { void warnIfOutOfSync(const char *aboutDataString, const QString &aboutDataValue, const char *appDataString, const QString &appDataValue) { if (aboutDataValue != appDataValue) { qCWarning(KABOUTDATA) << appDataString <m_appData; // not yet existing if (!aboutData) { // init from current Q*Application data aboutData = new KAboutData(QCoreApplication::applicationName(), QString(), QString()); // For applicationDisplayName & desktopFileName, which are only properties of QGuiApplication, // we have to try to get them via the property system, as the static getter methods are // part of QtGui only. Disadvantage: requires an app instance. // Either get all or none of the properties & warn about it if (app) { aboutData->setOrganizationDomain(QCoreApplication::organizationDomain().toUtf8()); aboutData->setVersion(QCoreApplication::applicationVersion().toUtf8()); aboutData->setDisplayName(app->property("applicationDisplayName").toString()); aboutData->setDesktopFileName(app->property("desktopFileName").toString()); } else { qCWarning(KABOUTDATA) << "Could not initialize the properties of KAboutData::applicationData by the equivalent properties from Q*Application: no app instance (yet) existing."; } s_registry->m_appData = aboutData; } else { // check if in-sync with Q*Application metadata, as their setters could have been called // after the last KAboutData::setApplicationData, with different values warnIfOutOfSync("KAboutData::applicationData().componentName", aboutData->componentName(), "QCoreApplication::applicationName", QCoreApplication::applicationName()); warnIfOutOfSync("KAboutData::applicationData().version", aboutData->version(), "QCoreApplication::applicationVersion", QCoreApplication::applicationVersion()); warnIfOutOfSync("KAboutData::applicationData().organizationDomain", aboutData->organizationDomain(), "QCoreApplication::organizationDomain", QCoreApplication::organizationDomain()); if (app) { warnIfOutOfSync("KAboutData::applicationData().displayName", aboutData->displayName(), "QGuiApplication::applicationDisplayName", app->property("applicationDisplayName").toString()); warnIfOutOfSync("KAboutData::applicationData().desktopFileName", aboutData->desktopFileName(), "QGuiApplication::desktopFileName", app->property("desktopFileName").toString()); } } return *aboutData; } void KAboutData::setApplicationData(const KAboutData &aboutData) { if (s_registry->m_appData) { *s_registry->m_appData = aboutData; } else { s_registry->m_appData = new KAboutData(aboutData); } // For applicationDisplayName & desktopFileName, which are only properties of QGuiApplication, // we have to try to set them via the property system, as the static getter methods are // part of QtGui only. Disadvantage: requires an app instance. // So set either all or none of the properties & warn about it QCoreApplication *app = QCoreApplication::instance(); if (app) { app->setApplicationVersion(aboutData.version()); app->setApplicationName(aboutData.componentName()); app->setOrganizationDomain(aboutData.organizationDomain()); app->setProperty("applicationDisplayName", aboutData.displayName()); app->setProperty("desktopFileName", aboutData.desktopFileName()); } else { qCWarning(KABOUTDATA) << "Could not initialize the equivalent properties of Q*Application: no instance (yet) existing."; } // KF6: Rethink the current relation between KAboutData::applicationData and the Q*Application metadata // Always overwriting the Q*Application metadata here, but not updating back the KAboutData // in applicationData() is unbalanced and can result in out-of-sync data if the Q*Application // setters have been called meanwhile // Options are to remove the overlapping properties of KAboutData for cleancode, or making the // overlapping properties official shadow properties of their Q*Application countparts, though // that increases behavioural complexity a little. } void KAboutData::registerPluginData(const KAboutData &aboutData) { s_registry->m_pluginData.insert(aboutData.componentName(), new KAboutData(aboutData)); } KAboutData *KAboutData::pluginData(const QString &componentName) { KAboutData *ad = s_registry->m_pluginData.value(componentName); return ad; } // only for KCrash (no memory allocation allowed) const KAboutData *KAboutData::applicationDataPointer() { if (s_registry.exists()) { return s_registry->m_appData; } return nullptr; } bool KAboutData::setupCommandLine(QCommandLineParser *parser) { if (!d->_shortDescription.isEmpty()) { parser->setApplicationDescription(d->_shortDescription); } parser->addHelpOption(); QCoreApplication *app = QCoreApplication::instance(); if (app && !app->applicationVersion().isEmpty()) { parser->addVersionOption(); } return parser->addOption(QCommandLineOption(QStringLiteral("author"), QCoreApplication::translate("KAboutData CLI", "Show author information."))) && parser->addOption(QCommandLineOption(QStringLiteral("license"), QCoreApplication::translate("KAboutData CLI", "Show license information."))) && parser->addOption(QCommandLineOption(QStringLiteral("desktopfile"), QCoreApplication::translate("KAboutData CLI", "The base file name of the desktop entry for this application."), QCoreApplication::translate("KAboutData CLI", "file name"))); } void KAboutData::processCommandLine(QCommandLineParser *parser) { bool foundArgument = false; if (parser->isSet(QStringLiteral("author"))) { foundArgument = true; if (d->_authorList.isEmpty()) { printf("%s\n", qPrintable(QCoreApplication::translate("KAboutData CLI", "This application was written by somebody who wants to remain anonymous."))); } else { printf("%s\n", qPrintable(QCoreApplication::translate("KAboutData CLI", "%1 was written by:").arg(qAppName()))); Q_FOREACH (const KAboutPerson &person, d->_authorList) { QString authorData = QStringLiteral(" ") + person.name(); if (!person.emailAddress().isEmpty()) { authorData.append(QStringLiteral(" <") + person.emailAddress() + QStringLiteral(">")); } printf("%s\n", qPrintable(authorData)); } } if (!customAuthorTextEnabled()) { if (bugAddress() == QLatin1String("submit@bugs.kde.org") ) { printf("%s\n", qPrintable(QCoreApplication::translate("KAboutData CLI", "Please use https://bugs.kde.org to report bugs."))); } else if (!bugAddress().isEmpty()) { printf("%s\n", qPrintable(QCoreApplication::translate("KAboutData CLI", "Please report bugs to %1.").arg(bugAddress()))); } } else { printf("%s\n", qPrintable(customAuthorPlainText())); } } else if (parser->isSet(QStringLiteral("license"))) { foundArgument = true; Q_FOREACH (const KAboutLicense &license, d->_licenseList) { printf("%s\n", qPrintable(license.text())); } } const QString desktopFileName = parser->value(QStringLiteral("desktopfile")); if (!desktopFileName.isEmpty()) { d->desktopFileName = desktopFileName; } if (foundArgument) { ::exit(EXIT_SUCCESS); } } template QVariantList listToVariant(const QList& values) { QVariantList ret; ret.reserve(values.count()); for(const auto &license: values) { ret << QVariant::fromValue(license); } return ret; } QVariantList KAboutData::licensesVariant() const { return listToVariant(d->_licenseList); } QVariantList KAboutData::authorsVariant() const { return listToVariant(d->_authorList); } QVariantList KAboutData::creditsVariant() const { return listToVariant(d->_creditList); } QVariantList KAboutData::translatorsVariant() const { return listToVariant(d->_translatorList); } diff --git a/src/lib/kaboutdata.h b/src/lib/kaboutdata.h index 135148e..4a822d1 100644 --- a/src/lib/kaboutdata.h +++ b/src/lib/kaboutdata.h @@ -1,1178 +1,1178 @@ /* * This file is part of the KDE Libraries * Copyright (C) 2000 Espen Sand (espen@kde.org) * Copyright (C) 2008 Friedrich W. H. Kossebau * Copyright (C) 2010 Teo Mrnjavac * Copyright (C) 2013 David Faure * Copyright (C) 2017 Harald Sitter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 KABOUTDATA_H #define KABOUTDATA_H #include #include #include #include +#include template class QList; class QCommandLineParser; class QJsonObject; -class QVariant; class KAboutData; class KPluginMetaData; namespace KCrash { Q_DECL_IMPORT void defaultCrashHandler(int sig); } /** * This class is used to store information about a person or developer. * It can store the person's name, a task, an email address and a * link to a home page. This class is intended for use in the * KAboutData class, but it can be used elsewhere as well. * Normally you should at least define the person's name. * Creating a KAboutPerson object by yourself is relatively useless, * but the KAboutData methods KAboutData::authors() and KAboutData::credits() * return lists of KAboutPerson data objects which you can examine. * * Example usage within a main(), retrieving the list of people involved * with a program and re-using data from one of them: * * @code * KAboutData about("khello", i18n("KHello"), "0.1", * i18n("A KDE version of Hello, world!"), * KAboutLicense::LGPL, * i18n("Copyright (C) 2014 Developer")); * * about.addAuthor(i18n("Joe Developer"), i18n("developer"), "joe@host.com", 0); * QList people = about.authors(); * about.addCredit(people[0].name(), people[0].task()); * @endcode */ class KCOREADDONS_EXPORT KAboutPerson { Q_GADGET Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString task READ task CONSTANT) Q_PROPERTY(QString emailAddress READ emailAddress CONSTANT) Q_PROPERTY(QString webAddress READ webAddress CONSTANT) Q_PROPERTY(QString ocsUsername READ ocsUsername CONSTANT) friend class KAboutData; public: /** * Convenience constructor * * @param name The name of the person. * * @param task The task of this person. * * @param emailAddress The email address of the person. * * @param webAddress Home page of the person. * * @param ocsUsername Open Collaboration Services username of the person. * * @p name default argument @since 5.53 */ explicit KAboutPerson(const QString &name = QString(), const QString &task = QString(), const QString &emailAddress = QString(), const QString &webAddress = QString(), const QString &ocsUsername = QString()); /** * Copy constructor. Performs a deep copy. * @param other object to copy */ KAboutPerson(const KAboutPerson &other); ~KAboutPerson(); /** * Assignment operator. Performs a deep copy. * @param other object to copy */ KAboutPerson &operator=(const KAboutPerson &other); /** * The person's name * @return the person's name (can be QString(), if it has been * constructed with an empty name) */ QString name() const; /** * The person's task * @return the person's task (can be QString(), if it has been * constructed with an empty task) */ QString task() const; /** * The person's email address * @return the person's email address (can be QString(), if it has been * constructed with an empty email) */ QString emailAddress() const; /** * The home page or a relevant link * @return the persons home page (can be QString(), if it has been * constructed with an empty home page) */ QString webAddress() const; /** * The person's Open Collaboration Services username * @return the persons OCS username (can be QString(), if it has been * constructed with an empty username) */ QString ocsUsername() const; /** * Creates a @c KAboutPerson from a JSON object with the following structure: * * Key | Accessor * -----------| ---------------------------- * Name | name() * Email | emailAddress() * Task | task() * Website | webAddress() * UserName | ocsUsername() * * The @c Name and @c Task key are translatable (by using e.g. a "Task[de_DE]" key) * * @since 5.18 */ static KAboutPerson fromJSON(const QJsonObject &obj); private: /** * @internal Used by KAboutData to construct translator data. */ explicit KAboutPerson(const QString &name, const QString &email, bool disambiguation); class Private; Private *const d; }; /** * This class is used to store information about a license. * The license can be one of some predefined, one given as text or one * that can be loaded from a file. This class is used in the KAboutData class. * Explicitly creating a KAboutLicense object is not possible. * If the license is wanted for a KDE component having KAboutData object, * use KAboutData::licenses() to get the licenses for that component. * If the license is for a non-code resource and given by a keyword * (e.g. in .desktop files), try using KAboutLicense::byKeyword(). */ class KCOREADDONS_EXPORT KAboutLicense { Q_GADGET Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString text READ text CONSTANT) Q_PROPERTY(KAboutLicense::LicenseKey key READ key CONSTANT) Q_PROPERTY(QString spdx READ spdx CONSTANT) friend class KAboutData; public: /** * Describes the license of the software. */ enum LicenseKey { Custom = -2, File = -1, Unknown = 0, GPL = 1, GPL_V2 = 1, LGPL = 2, LGPL_V2 = 2, BSDL = 3, Artistic = 4, QPL = 5, QPL_V1_0 = 5, GPL_V3 = 6, LGPL_V3 = 7, LGPL_V2_1 = 8 ///< @since 5.25 }; Q_ENUM(LicenseKey) /** * Format of the license name. */ enum NameFormat { ShortName, FullName }; Q_ENUM(NameFormat) /** * Whether later versions of the license are allowed. */ enum VersionRestriction { OnlyThisVersion, OrLaterVersions }; Q_ENUM(VersionRestriction) /** * @since 5.53 */ explicit KAboutLicense(); /** * Copy constructor. Performs a deep copy. * @param other object to copy */ KAboutLicense(const KAboutLicense &other); ~KAboutLicense(); /** * Assignment operator. Performs a deep copy. * @param other object to copy */ KAboutLicense &operator=(const KAboutLicense &other); /** * Returns the full license text. If the licenseType argument of the * constructor has been used, any text defined by setLicenseText is ignored, * and the standard text for the chosen license will be returned. * * @return The license text. */ QString text() const; /** * Returns the license name. * * Default argument @since 5.53 * * @return The license name as a string. */ QString name(KAboutLicense::NameFormat formatName = ShortName) const; /** * Returns the license key. * * @return The license key as element of KAboutLicense::LicenseKey enum. */ KAboutLicense::LicenseKey key() const; /** * Returns the SPDX license expression of this license. * If the underlying license cannot be expressed as a SPDX expression a null string is returned. * * @note SPDX expression are expansive constructs. If you parse the return value, do it in a * SPDX specification compliant manner by splitting on whitespaces to discard unwanted * information or by using a complete SPDX license expression parser. * @note SPDX identifiers are case-insensitive. Do not use case-sensitive checks on the return * value. * @see https://spdx.org/licenses * @return SPDX license expression or QString() if the license has no identifier. Compliant * with SPDX 2.1. * * @since 5.37 */ QString spdx() const; /** * Fetch a known license by a keyword/spdx ID * * Frequently the license data is provided by a terse keyword-like string, * e.g. by a field in a .desktop file. Using this method, an application * can get hold of a proper KAboutLicense object, providing that the * license is one of the several known to KDE, and use it to present * more human-readable information to the user. * * Keywords are matched by stripping all whitespace and lowercasing. * The known keywords correspond to the KAboutLicense::LicenseKey enumeration, * e.g. any of "LGPLV3", "LGPLv3", "LGPL v3" would match KAboutLicense::LGPL_V3. * If there is no match for the keyword, a valid license object is still * returned, with its name and text informing about a custom license, * and its key equal to KAboutLicense::Custom. * * @param keyword The license keyword. * @return The license object. * * @see KAboutLicense::LicenseKey */ static KAboutLicense byKeyword(const QString &keyword); private: /** * @internal Used by KAboutData to construct a predefined license. */ explicit KAboutLicense(enum KAboutLicense::LicenseKey licenseType, enum KAboutLicense::VersionRestriction versionRestriction, const KAboutData *aboutData); /** * @internal Used by KAboutData to construct a predefined license. */ explicit KAboutLicense(enum KAboutLicense::LicenseKey licenseType, const KAboutData *aboutData); /** * @internal Used by KAboutData to construct a KAboutLicense */ explicit KAboutLicense(const KAboutData *aboutData); /** * @internal Used by KAboutData to construct license by given text */ void setLicenseFromPath(const QString &pathToFile); /** * @internal Used by KAboutData to construct license by given text */ void setLicenseFromText(const QString &licenseText); class Private; QSharedDataPointer d; }; /** * @class KAboutData kaboutdata.h KAboutData * * This class is used to store information about a program or plugin. * It can store such values as version number, program name, home page, address * for bug reporting, multiple authors and contributors * (using KAboutPerson), license and copyright information. * * Currently, the values set here are shown by the "About" box * (see KAboutDialog), used by the bug report dialog (see KBugReport), * and by the help shown on command line (see KAboutData::setupCommandLine()). * * Porting Notes: Since KDE Frameworks 5.0, the translation catalog mechanism * must provided by your translation framework to load the correct catalog * instead (eg: KLocalizedString::setApplicationDomain() for KI18n, or * QCoreApplication::installTranslator() for Qt's translation system). This * applies to the old setCatalogName() and catalogName() members. But see also * K4AboutData in kde4support as a compatibility class. * * Example: * Setting the metadata of an application using KAboutData in code also relying * on the KDE Framework modules KI18n and KDBusAddons: * @code * // create QApplication instance * QApplication app(argc, argv); * // setup translation string domain for the i18n calls * KLocalizedString::setApplicationDomain("foo"); * // create a KAboutData object to use for setting the application metadata * KAboutData aboutData("foo", i18n("Foo"), "0.1", * i18n("To Foo or not To Foo"), * KAboutLicense::LGPL, * i18n("Copyright 2017 Bar Foundation"), QString(), * "https://www.foo-the-app.net"); * // overwrite default-generated values of organizationDomain & desktopFileName * aboutData.setOrganizationDomain("barfoundation.org"); * aboutData.setDesktopFileName("org.barfoundation.foo"); * * // set the application metadata * KAboutData::setApplicationData(aboutData); * // in GUI apps set the window icon manually, not covered by KAboutData * // needed for environments where the icon name is not extracted from * // the information in the application's desktop file * QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("foo"))); * * // integrate with commandline argument handling * QCommandLineParser parser; * aboutData.setupCommandLine(&parser); * // setup of app specific commandline args * [...] * parser.process(app); * aboutData.processCommandLine(&parser); * * // with the application metadata set, register to the D-Bus session * KDBusService programDBusService(KDBusService::Multiple | KDBusService::NoExitOnFailure); * @endcode * * @short Holds information needed by the "About" box and other * classes. * @author Espen Sand (espen@kde.org), David Faure (faure@kde.org) * */ class KCOREADDONS_EXPORT KAboutData { Q_GADGET Q_PROPERTY(QString displayName READ displayName CONSTANT) Q_PROPERTY(QString productName READ productName CONSTANT) Q_PROPERTY(QString componentName READ componentName CONSTANT) Q_PROPERTY(QVariant programLogo READ programLogo CONSTANT) Q_PROPERTY(QString shortDescription READ shortDescription CONSTANT) Q_PROPERTY(QString homepage READ homepage CONSTANT) Q_PROPERTY(QString bugAddress READ bugAddress CONSTANT) Q_PROPERTY(QString version READ version CONSTANT) Q_PROPERTY(QString otherText READ otherText CONSTANT) Q_PROPERTY(QVariantList authors READ authorsVariant CONSTANT) //constant in practice as addAuthor is not exposed to Q_GADGET Q_PROPERTY(QVariantList credits READ creditsVariant CONSTANT) Q_PROPERTY(QVariantList translators READ translatorsVariant CONSTANT) Q_PROPERTY(QVariantList licenses READ licensesVariant CONSTANT) Q_PROPERTY(QString copyrightStatement READ copyrightStatement CONSTANT) Q_PROPERTY(QString desktopFileName READ desktopFileName CONSTANT) public: /** * Returns the KAboutData for the application. * * This contains information such as authors, license, etc., * provided that setApplicationData has been called before. * If not called before, the returned KAboutData will be initialized from the * equivalent properties of QCoreApplication (and its subclasses), * if an instance of that already exists. * For the list of such properties see setApplicationData * (before 5.22: limited to QCoreApplication::applicationName). * @see setApplicationData */ static KAboutData applicationData(); /** * Sets the application data for this application. * * In addition to changing the result of applicationData(), this initializes * the equivalent properties of QCoreApplication (and its subclasses) with * information from @p aboutData, if an instance of that already exists. * Those properties are:
  • QCoreApplication::applicationName
  • QCoreApplication::applicationVersion
  • QCoreApplication::organizationDomain
  • QGuiApplication::applicationDisplayName
  • QGuiApplication::desktopFileName (since 5.16)
* @see applicationData */ static void setApplicationData(const KAboutData &aboutData); /** * Register the KAboutData information for a plugin. * Call this from the constructor of the plugin. * This will register the plugin's @p aboutData under the component name * that was set in @p aboutData. */ static void registerPluginData(const KAboutData &aboutData); /** * Return the KAboutData for the given plugin identified by @p componentName. */ static KAboutData *pluginData(const QString &componentName); /** * Creates a @c KAboutData from the given @p plugin metadata * * @since 5.18 */ static KAboutData fromPluginMetaData(const KPluginMetaData &plugin); public: /** * Constructor. * * Porting Note: The @p catalogName parameter present in KDE4 was * deprecated and removed. See also K4AboutData * in kde4support if this feature is needed for compatibility purposes, or * consider using componentName() instead. * * @param componentName The program name or plugin name used internally. * Example: QStringLiteral("kwrite"). This should never be translated. * * @param displayName A displayable name for the program or plugin. This string * should be translated. Example: i18n("KWrite") * * @param version The component version string. Example: QStringLiteral("1.0"). * * @param shortDescription A short description of what the component does. * This string should be translated. * Example: i18n("A simple text editor.") * * @param licenseType The license identifier. Use setLicenseText or setLicenseTextFile if you use a license not predefined here. * * @param copyrightStatement A copyright statement, that can look like this: * i18n("Copyright (C) 1999-2000 Name"). The string specified here is * taken verbatim; the author information from addAuthor is not used. * * @param otherText Some free form text, that can contain any kind of * information. The text can contain newlines. This string * should be translated. * * @param homePageAddress The URL to the component's homepage, including * URL scheme. "http://some.domain" is correct, "some.domain" is * not. Since KDE Frameworks 5.17, https and other valid URL schemes * are also valid. See also the note below. * * @param bugAddress The bug report address string, an email address or a URL. * This defaults to the kde.org bug system. * * @note The @p homePageAddress argument is used to derive a default organization * domain for the application (which is used to register on the session D-Bus, * locate the appropriate desktop file, etc.), by taking the host name and dropping * the first component, unless there are less than three (e.g. "www.kde.org" -> "kde.org"). * Use both setOrganizationDomain(const QByteArray&) and setDesktopFileName() if their default values * do not have proper values. * * @see setOrganizationDomain(const QByteArray&), setDesktopFileName(const QString&) */ // KF6: remove constructor that includes catalogName, and put default // values back in for shortDescription and licenseType KAboutData(const QString &componentName, const QString &displayName, const QString &version, const QString &shortDescription, enum KAboutLicense::LicenseKey licenseType, const QString ©rightStatement = QString(), const QString &otherText = QString(), const QString &homePageAddress = QString(), const QString &bugAddress = QStringLiteral("submit@bugs.kde.org") ); /** * Constructor. * * @param componentName The program name or plugin name used internally. * Example: "kwrite". * * @param displayName A displayable name for the program or plugin. This string * should be translated. Example: i18n("KWrite") * * @param version The component version string. * * Sets the property desktopFileName to "org.kde."+componentName and * the property organizationDomain to "kde.org". * * Default arguments @since 5.53 * * @see setOrganizationDomain(const QByteArray&), setDesktopFileName(const QString&) */ explicit KAboutData(const QString &componentName = {}, const QString &displayName = {}, const QString &version = {} ); /** * Copy constructor. Performs a deep copy. * @param other object to copy */ KAboutData(const KAboutData &other); /** * Assignment operator. Performs a deep copy. * @param other object to copy */ KAboutData &operator=(const KAboutData &other); ~KAboutData(); /** * Defines an author. * * You can call this function as many times as you need. Each entry is * appended to a list. The person in the first entry is assumed to be * the leader of the project. * * @param name The developer's name. It should be translated. * * @param task What the person is responsible for. This text can contain * newlines. It should be translated. * Can be left empty. * * @param emailAddress An Email address where the person can be reached. * Can be left empty. * * @param webAddress The person's homepage or a relevant link. * Start the address with "http://". "http://some.domain" is * correct, "some.domain" is not. Can be left empty. * * @param ocsUsername The person's Open Collaboration Services username. * The provider can be optionally specified with @see setOcsProvider. * */ KAboutData &addAuthor(const QString &name, const QString &task = QString(), const QString &emailAddress = QString(), const QString &webAddress = QString(), const QString &ocsUsername = QString()); /** * Defines a person that deserves credit. * * You can call this function as many times as you need. Each entry * is appended to a list. * * @param name The person's name. It should be translated. * * @param task What the person has done to deserve the honor. The * text can contain newlines. It should be translated. * Can be left empty. * * @param emailAddress An email address when the person can be reached. * Can be left empty. * * @param webAddress The person's homepage or a relevant link. * Start the address with "http://". "http://some.domain" is * is correct, "some.domain" is not. Can be left empty. * * @param ocsUsername The person's Open Collaboration Services username. * The provider can be optionally specified with @see setOcsProvider. * */ KAboutData &addCredit(const QString &name, const QString &task = QString(), const QString &emailAddress = QString(), const QString &webAddress = QString(), const QString &ocsUsername = QString()); /** * @brief Sets the name(s) of the translator(s) of the GUI. * * The canonical use with the ki18n framework is: * * \code * setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), * i18nc("EMAIL OF TRANSLATORS", "Your emails")); * \endcode * * If you are using a KMainWindow this is done for you automatically. * * The name and emailAddress are treated as lists separated with ",". * * If the strings are empty or "Your names"/"Your emails" * respectively they will be ignored. * * @param name the name(s) of the translator(s) * @param emailAddress the email address(es) of the translator(s) * @see KAboutTranslator */ KAboutData &setTranslator(const QString &name, const QString &emailAddress); /** * Defines a license text, which is translated. * * Example: * \code * setLicenseText( i18n("This is my license") ); * \endcode * * @param license The license text. */ KAboutData &setLicenseText(const QString &license); /** * Adds a license text, which is translated. * * If there is only one unknown license set, e.g. by using the default * parameter in the constructor, that one is replaced. * * Example: * \code * addLicenseText( i18n("This is my license") ); * \endcode * * @param license The license text. * @see setLicenseText, addLicense, addLicenseTextFile */ KAboutData &addLicenseText(const QString &license); /** * Defines a license text by pointing to a file where it resides. * The file format has to be plain text in an encoding compatible to the locale. * * @param file Path to the file in the local filesystem containing the license text. */ KAboutData &setLicenseTextFile(const QString &file); /** * Adds a license text by pointing to a file where it resides. * The file format has to be plain text in an encoding compatible to the locale. * * If there is only one unknown license set, e.g. by using the default * parameter in the constructor, that one is replaced. * * @param file Path to the file in the local filesystem containing the license text. * @see addLicenseText, addLicense, setLicenseTextFile */ KAboutData &addLicenseTextFile(const QString &file); /** * Defines the component name used internally. * * @param componentName The application or plugin name. Example: "kate". */ KAboutData &setComponentName(const QString &componentName); /** * Defines the displayable component name string. * * @param displayName The display name. This string should be * translated. * Example: i18n("Advanced Text Editor"). */ KAboutData &setDisplayName(const QString &displayName); /** * Obsolete method * * This method used to set the icon name but this is no longer * possible in KDE Frameworks 5 because KCoreAddons does not * depend on QtGui. * * @param iconName name of the icon. Example: "accessories-text-editor" * @see programIconName() * * @deprecated since 5.2, use QApplication::setWindowIcon(QIcon::fromTheme()) instead. */ KCOREADDONS_DEPRECATED KAboutData &setProgramIconName(const QString &iconName); // KF6 remove this /** * Defines the program logo. * * Use this if you need to have an application logo * in AboutData other than the application icon. * * Because KAboutData is a core class it cannot use QImage directly, * so this is a QVariant that should contain a QImage. * * @param image logo image. * @see programLogo() */ KAboutData &setProgramLogo(const QVariant &image); /** * Specifies an Open Collaboration Services provider by URL. * A provider file must be available for the chosen provider. * * Use this if you need to override the default provider. * * If this method is not used, all the KAboutPerson OCS usernames * will be used with the openDesktop.org entry from the default * provider file. * * @param providerUrl The provider URL as defined in the provider file. */ KAboutData &setOcsProvider(const QString &providerUrl); /** * Defines the program version string. * * @param version The program version. */ KAboutData &setVersion(const QByteArray &version); /** * Defines a short description of what the program does. * * @param shortDescription The program description. This string should * be translated. Example: i18n("An advanced text * editor with syntax highlighting support."). */ KAboutData &setShortDescription(const QString &shortDescription); /** * Defines the license identifier. * * @param licenseKey The license identifier. * @see addLicenseText, setLicenseText, setLicenseTextFile */ KAboutData &setLicense(KAboutLicense::LicenseKey licenseKey); /** * Defines the license identifier. * * @param licenseKey The license identifier. * @param versionRestriction Whether later versions of the license are also allowed. * e.g. licensed under "GPL 2.0 or at your option later versions" would be OrLaterVersions. * @see addLicenseText, setLicenseText, setLicenseTextFile * * @since 5.37 */ KAboutData &setLicense(KAboutLicense::LicenseKey licenseKey, KAboutLicense::VersionRestriction versionRestriction); /** * Adds a license identifier. * * If there is only one unknown license set, e.g. by using the default * parameter in the constructor, that one is replaced. * * @param licenseKey The license identifier. * @see setLicenseText, addLicenseText, addLicenseTextFile */ KAboutData &addLicense(KAboutLicense::LicenseKey licenseKey); /** * Adds a license identifier. * * If there is only one unknown license set, e.g. by using the default * parameter in the constructor, that one is replaced. * * @param licenseKey The license identifier. * @param versionRestriction Whether later versions of the license are also allowed. * e.g. licensed under "GPL 2.0 or at your option later versions" would be OrLaterVersions. * @see setLicenseText, addLicenseText, addLicenseTextFile * * @since 5.37 */ KAboutData &addLicense(KAboutLicense::LicenseKey licenseKey, KAboutLicense::VersionRestriction versionRestriction); /** * Defines the copyright statement to show when displaying the license. * * @param copyrightStatement A copyright statement, that can look like * this: i18n("Copyright (C) 1999-2000 Name"). The string specified here is * taken verbatim; the author information from addAuthor is not used. */ KAboutData &setCopyrightStatement(const QString ©rightStatement); /** * Defines the additional text to show in the about dialog. * * @param otherText Some free form text, that can contain any kind of * information. The text can contain newlines. This string * should be translated. */ KAboutData &setOtherText(const QString &otherText); /** * Defines the program homepage. * * @param homepage The program homepage string. * Start the address with "http://". "http://kate.kde.org" * is correct but "kate.kde.org" is not. */ KAboutData &setHomepage(const QString &homepage); /** * Defines the address where bug reports should be sent. * * @param bugAddress The bug report email address or URL. * This defaults to the kde.org bug system. */ KAboutData &setBugAddress(const QByteArray &bugAddress); /** * Defines the domain of the organization that wrote this application. * The domain is set to kde.org by default, or the domain of the homePageAddress constructor argument, * if set. * * Make sure to call setOrganizationDomain(const QByteArray&) if your product * is not developed inside the KDE community. * * Used e.g. for the registration to D-Bus done by KDBusService * from the KDE Frameworks KDBusAddons module. * * Calling this method has no effect on the value of the desktopFileName property. * * @note If your program should work as a D-Bus activatable service, the base name * of the D-Bus service description file or of the desktop file you install must match * the D-Bus "well-known name" for which the program will register. * For example, KDBusService will use a name created from the reversed organization domain * with the component name attached, so for an organization domain "bar.org" and a * component name "foo" the name of an installed D-Bus service file needs to be * "org.bar.foo.service" or the name of the installed desktop file "org.bar.foo.desktop" * (and the desktopFileName property accordingly set to "org.bar.foo"). * For still supporting the deprecated start of services via KToolInvocation, * the desktop file needs to have an entry with the key "X-DBUS-ServiceName" * and a value which matches the used D-Bus "well-known name" as just described, * so with the above used values it needs a line "X-DBUS-ServiceName=org.bar.foo" * * @param domain the domain name, for instance kde.org, koffice.org, etc. * * @see setDesktopFileName(const QString&) */ KAboutData &setOrganizationDomain(const QByteArray &domain); /** * Defines the product name which will be used in the KBugReport dialog. * By default it's the componentName, but you can overwrite it here to provide * support for special components e.g. in the form 'product/component', * such as 'kontact/summary'. * * @param name The name of product */ KAboutData &setProductName(const QByteArray &name); /** * Returns the application's internal name. * @return the internal program name. */ QString componentName() const; /** * Returns the application's product name, which will be used in KBugReport * dialog. By default it returns componentName(), otherwise the one which is set * with setProductName() * * @return the product name. */ QString productName() const; /** * Returns the translated program name. * @return the program name (translated). */ QString displayName() const; /** * Returns the domain name of the organization that wrote this application. * * @see setOrganizationDomain(const QByteArray&) */ QString organizationDomain() const; /** * @internal * Provided for use by KCrash */ const char *internalProgramName() const; /** * Returns the program's icon name. * * The default value is componentName(). * @return the program's icon name. * * This is mostly for compatibility, given that setProgramIconName is deprecated. */ QString programIconName() const; /** * Returns the program logo image. * * Because KAboutData is a core class it cannot use QImage directly, * so this is a QVariant containing a QImage. * * @return the program logo data, or a null image if there is * no custom application logo defined. */ QVariant programLogo() const; /** * Returns the chosen Open Collaboration Services provider URL. * @return the provider URL. */ QString ocsProviderUrl() const; /** * Returns the program's version. * @return the version string. */ QString version() const; /** * @internal * Provided for use by KCrash */ const char *internalVersion() const; /** * Returns a short, translated description. * @return the short description (translated). Can be * QString() if not set. */ QString shortDescription() const; /** * Returns the application homepage. * @return the application homepage URL. Can be QString() if * not set. */ QString homepage() const; /** * Returns the email address or URL for bugs. * @return the address where to report bugs. */ QString bugAddress() const; /** * @internal * Provided for use by KCrash */ const char *internalBugAddress() const; /** * Returns a list of authors. * @return author information (list of persons). */ QList authors() const; /** * Returns a list of persons who contributed. * @return credit information (list of persons). */ QList credits() const; /** * Returns a list of translators. * @return translators information (list of persons) */ QList translators() const; /** * Returns a message about the translation team. * @return a message about the translation team */ static QString aboutTranslationTeam(); /** * Returns a translated, free form text. * @return the free form text (translated). Can be QString() if not set. */ QString otherText() const; /** * Returns a list of licenses. * * @return licenses information (list of licenses) */ QList licenses() const; /** * Returns the copyright statement. * @return the copyright statement. Can be QString() if not set. */ QString copyrightStatement() const; /** * Returns the plain text displayed around the list of authors instead * of the default message telling users to send bug reports to bugAddress(). * * @return the plain text displayed around the list of authors instead * of the default message. Can be QString(). */ QString customAuthorPlainText() const; /** * Returns the rich text displayed around the list of authors instead * of the default message telling users to send bug reports to bugAddress(). * * @return the rich text displayed around the list of authors instead * of the default message. Can be QString(). */ QString customAuthorRichText() const; /** * Returns whether custom text should be displayed around the list of * authors. * * @return whether custom text should be displayed around the list of * authors. */ bool customAuthorTextEnabled() const; /** * Sets the custom text displayed around the list of authors instead * of the default message telling users to send bug reports to bugAddress(). * * @param plainText The plain text. * @param richText The rich text. * * Setting both to parameters to QString() will cause no message to be * displayed at all. Call unsetCustomAuthorText() to revert to the default * message. */ KAboutData &setCustomAuthorText(const QString &plainText, const QString &richText); /** * Clears any custom text displayed around the list of authors and falls * back to the default message telling users to send bug reports to * bugAddress(). */ KAboutData &unsetCustomAuthorText(); /** * Configures the @p parser command line parser to provide an authors entry with * information about the developers of the application and an entry specifying the license. * * Additionally, it will set the description to the command line parser, will add the help * option and if the QApplication has a version set (e.g. via KAboutData::setApplicationData) * it will also add the version option. * * Since 5.16 it also adds an option to set the desktop file name. * * @returns true if adding the options was successful; otherwise returns false. * * @sa processCommandLine() */ bool setupCommandLine(QCommandLineParser *parser); /** * Reads the processed @p parser and sees if any of the arguments are the ones set * up from setupCommandLine(). * * @sa setupCommandLine() */ void processCommandLine(QCommandLineParser *parser); /** * Sets the base name of the desktop entry for this application. * * This is the file name, without the full path and without extension, * of the desktop entry that represents this application according to * the freedesktop desktop entry specification (e.g. "org.kde.foo"). * * A default desktop file name is constructed when the KAboutData * object is created, using the reverse domain name of the * organizationDomain() and the componentName() as they are at the time * of the KAboutData object creation. * Call this method to override that default name. Typically this is * done when also setOrganizationDomain(const QByteArray&) or setComponentName(const QString&) * need to be called to override the initial values. * * The desktop file name can also be passed to the application at runtime through * the @c desktopfile command line option which is added by setupCommandLine(QCommandLineParser*). * This is useful if an application supports multiple desktop files with different runtime * settings. * * @param desktopFileName The desktop file name of this application * * @sa desktopFileName() * @sa organizationDomain() * @sa componentName() * @sa setupCommandLine(QCommandLineParser*) * @since 5.16 **/ KAboutData &setDesktopFileName(const QString &desktopFileName); /** * @returns The desktop file name of this application (e.g. "org.kde.foo") * @sa setDesktopFileName(const QString&) * @since 5.16 **/ QString desktopFileName() const; private: QVariantList licensesVariant() const; QVariantList authorsVariant() const; QVariantList creditsVariant() const; QVariantList translatorsVariant() const; friend void KCrash::defaultCrashHandler(int sig); static const KAboutData *applicationDataPointer(); class Private; Private *const d; }; Q_DECLARE_METATYPE(KAboutData) Q_DECLARE_METATYPE(KAboutLicense) Q_DECLARE_METATYPE(KAboutPerson) #endif