diff --git a/src/attica/atticaprovider.cpp b/src/attica/atticaprovider.cpp --- a/src/attica/atticaprovider.cpp +++ b/src/attica/atticaprovider.cpp @@ -163,7 +163,7 @@ emit providerInitialized(this); emit categoriesMetadataLoded(categoryMetadataList); } else { - emit signalError(i18n("All categories are missing")); + emit signalErrorCode(KNSCore::ConfigFileError, i18n("All categories are missing"), QVariant()); } } @@ -437,13 +437,13 @@ qCDebug(KNEWSTUFFCORE) << "job error: " << job->metadata().error() << " status code: " << job->metadata().statusCode() << job->metadata().message(); if (job->metadata().error() == Attica::Metadata::NetworkError) { - emit signalError(i18n("Network error %1: %2", job->metadata().statusCode(), job->metadata().statusString())); + emit signalErrorCode(KNSCore::NetworkError, i18n("Network error %1: %2", job->metadata().statusCode(), job->metadata().statusString()), job->metadata().statusCode()); } if (job->metadata().error() == Attica::Metadata::OcsError) { if (job->metadata().statusCode() == 200) { - emit signalError(i18n("Too many requests to server. Please try again in a few minutes.")); + emit signalErrorCode(KNSCore::OcsError, i18n("Too many requests to server. Please try again in a few minutes."), job->metadata().statusCode()); } else { - emit signalError(i18n("Unknown Open Collaboration Service API error. (%1)", job->metadata().statusCode())); + emit signalErrorCode(KNSCore::OcsError, i18n("Unknown Open Collaboration Service API error. (%1)", job->metadata().statusCode()), job->metadata().statusCode()); } } return false; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -71,6 +71,7 @@ DownloadManager Engine EntryInternal + ErrorCode Installation ItemsModel Provider diff --git a/src/core/downloadmanager.cpp b/src/core/downloadmanager.cpp --- a/src/core/downloadmanager.cpp +++ b/src/core/downloadmanager.cpp @@ -82,7 +82,7 @@ q->connect(engine, &KNSCore::Engine::signalUpdateableEntriesLoaded, q, &DownloadManager::searchResult); q->connect(engine, &KNSCore::Engine::signalEntriesLoaded, q, &DownloadManager::searchResult); q->connect(engine, &KNSCore::Engine::signalEntryChanged, q, &DownloadManager::entryStatusChanged); - q->connect(engine, &KNSCore::Engine::signalError, q, &DownloadManager::errorFound); + q->connect(engine, &KNSCore::Engine::signalErrorCode, q, [this](const KNSCore::ErrorCode &, const QString &message, const QVariant &){ emit q->errorFound(message); }); engine->init(configFile); } diff --git a/src/core/engine.h b/src/core/engine.h --- a/src/core/engine.h +++ b/src/core/engine.h @@ -28,6 +28,7 @@ #include "provider.h" #include "entryinternal.h" +#include "errorcode.h" #include "knewstuffcore_export.h" @@ -417,9 +418,17 @@ void signalDownloadDialogDone(KNSCore::EntryInternal::List); void jobStarted(KJob *, const QString &); - void signalError(const QString &); + QT_DEPRECATED void signalError(const QString &); void signalBusy(const QString &); void signalIdle(const QString &); + /** + * Fires in the case of any critical or serious errors, such as network or API problems. + * @param errorCode Represents the specific type of error which has occurred + * @param message A human-readable message which can be shown to the end user + * @param metadata Any additional data which might be hepful to further work out the details of the error (see KNSCore::EntryInternal::ErrorCode for the metadata details) + * @see KNSCore::EntryInternal::ErrorCode + */ + void signalErrorCode(const KNSCore::ErrorCode &errorCode, const QString &message, const QVariant &metadata); void signalCategoriesMetadataLoded(const QList &categories); diff --git a/src/core/engine.cpp b/src/core/engine.cpp --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -83,6 +83,8 @@ connect(m_searchTimer, &QTimer::timeout, this, &Engine::slotSearchTimerExpired); connect(m_installation, &Installation::signalInstallationFinished, this, &Engine::slotInstallationFinished); connect(m_installation, &Installation::signalInstallationFailed, this, &Engine::slotInstallationFailed); + // Pass along old error signal through new signal for locations which have not been updated yet + connect(this, &Engine::signalError, this, [this](const QString& message){ emit signalErrorCode(ErrorCode::UnknownError, message, QVariant()); }); } Engine::~Engine() @@ -104,7 +106,7 @@ KConfig conf(configfile); if (conf.accessMode() == KConfig::NoAccess) { - emit signalError(i18n("Configuration file exists, but cannot be opened: \"%1\"", configfile)); + emit signalErrorCode(KNSCore::ConfigFileError, i18n("Configuration file exists, but cannot be opened: \"%1\"", configfile), configfile); qCCritical(KNEWSTUFFCORE) << "The knsrc file '" << configfile << "' was found but could not be opened."; return false; } @@ -117,7 +119,7 @@ qCDebug(KNEWSTUFFCORE) << "Loading KNewStuff2 config: " << configfile; group = conf.group("KNewStuff2"); } else { - emit signalError(i18n("Configuration file is invalid: \"%1\"", configfile)); + emit signalErrorCode(KNSCore::ConfigFileError, i18n("Configuration file is invalid: \"%1\"", configfile), configfile); qCCritical(KNEWSTUFFCORE) << configfile << " doesn't contain a KNewStuff3 section."; return false; } @@ -209,7 +211,7 @@ isAtticaProviderFile = true; } else if (providers.tagName() != QLatin1String("ghnsproviders") && providers.tagName() != QLatin1String("knewstuffproviders")) { qWarning() << "No document in providers.xml."; - emit signalError(i18n("Could not load get hot new stuff providers from file: %1", m_providerFileUrl)); + emit signalErrorCode(KNSCore::ProviderError, i18n("Could not load get hot new stuff providers from file: %1", m_providerFileUrl), m_providerFileUrl); return; } @@ -232,7 +234,7 @@ if (provider->setProviderXML(n)) { addProvider(provider); } else { - emit signalError(i18n("Error initializing provider.")); + emit signalErrorCode(KNSCore::ProviderError, i18n("Error initializing provider."), m_providerFileUrl); } n = n.nextSiblingElement(); } @@ -267,6 +269,7 @@ connect(provider.data(), &Provider::entryDetailsLoaded, this, &Engine::slotEntryDetailsLoaded); connect(provider.data(), &Provider::payloadLinkLoaded, this, &Engine::downloadLinkLoaded); connect(provider.data(), &Provider::signalError, this, &Engine::signalError); + connect(provider.data(), &Provider::signalErrorCode, this, &Engine::signalErrorCode); connect(provider.data(), &Provider::signalInformation, this, &Engine::signalIdle); } @@ -277,7 +280,7 @@ void Engine::slotProvidersFailed() { - emit signalError(i18n("Loading of providers from file: %1 failed", m_providerFileUrl)); + emit signalErrorCode(KNSCore::ProviderError, i18n("Loading of providers from file: %1 failed", m_providerFileUrl), m_providerFileUrl); } void Engine::providerInitialized(Provider *p) @@ -511,7 +514,7 @@ void Engine::slotInstallationFailed(const QString &message) { --m_numInstallJobs; - emit signalError(message); + emit signalErrorCode(KNSCore::InstallationError, message, QVariant()); } void Engine::slotEntryDetailsLoaded(const KNSCore::EntryInternal &entry) @@ -569,6 +572,7 @@ connect(l, &ImageLoader::signalError, this, [this](const KNSCore::EntryInternal &entry, EntryInternal::PreviewType type, const QString &errorText) { + emit signalErrorCode(KNSCore::ImageError, errorText, QVariantList() << entry.name() << type); qCDebug(KNEWSTUFFCORE) << "ERROR preview: " << errorText << entry.name() << type; --m_numPictureJobs; updateStatus(); diff --git a/src/core/errorcode.h b/src/core/errorcode.h new file mode 100644 --- /dev/null +++ b/src/core/errorcode.h @@ -0,0 +1,39 @@ +/* + knewstuff3/errorcode.h. + Copyright (c) 2018 Dan Leinir Turthra Jensen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + + +#ifndef KNSCORE_ERRORCODE_H +#define KNSCORE_ERRORCODE_H + +namespace KNSCore { + /** + * An enumeration of specific error conditions which might occur and which + * users of KNewStuff would want to react to. It is used by both the Engine and + * Provider classes. + */ + enum ErrorCode { + UnknownError, // An unknown error (this should not be used, an error report of this nature should be considered a bug) + NetworkError, // A network error. In signalErrorCode, this will be accompanied by the QtNetwork error code in the metadata + OcsError, // An error reported by the OCS API server. In signalErrorCode, this will be accompanied by the OCS error code in the metadata + ConfigFileError, // The configuration file is missing or somehow incorrect. The configuration file filename will be held in the metadata + ProviderError, // A provider has failed to load or initialize. The provider file URL or provider URL will be held in the metadata + InstallationError, // Installation of a content item has failed + ImageError // Loading an image has failed. The entry name and preview type which failed will be held in the metadata as a QVariantList + }; +} +#endif//KNSCORE_ERRORCODE_H diff --git a/src/core/provider.h b/src/core/provider.h --- a/src/core/provider.h +++ b/src/core/provider.h @@ -25,6 +25,7 @@ #include #include "entryinternal.h" +#include "errorcode.h" #include "knewstuffcore_export.h" @@ -202,6 +203,7 @@ void signalInformation(const QString &) const; void signalError(const QString &) const; + void signalErrorCode(const KNSCore::ErrorCode &errorCode, const QString &message, const QVariant &metadata) const; void categoriesMetadataLoded(const QList &categories); diff --git a/src/downloadwidget.cpp b/src/downloadwidget.cpp --- a/src/downloadwidget.cpp +++ b/src/downloadwidget.cpp @@ -242,7 +242,7 @@ q->connect(engine, &KNSCore::Engine::signalMessage, this, &DownloadWidgetPrivate::slotShowMessage); q->connect(engine, &KNSCore::Engine::signalBusy, ui.progressIndicator, &ProgressIndicator::busy); - q->connect(engine, &KNSCore::Engine::signalError, ui.progressIndicator, &ProgressIndicator::error); + q->connect(engine, &KNSCore::Engine::signalErrorCode, ui.progressIndicator, &ProgressIndicator::error); q->connect(engine, &KNSCore::Engine::signalIdle, ui.progressIndicator, &ProgressIndicator::idle); q->connect(engine, &KNSCore::Engine::signalProvidersLoaded, this, &DownloadWidgetPrivate::slotProvidersLoaded); diff --git a/src/ui/progressindicator.cpp b/src/ui/progressindicator.cpp --- a/src/ui/progressindicator.cpp +++ b/src/ui/progressindicator.cpp @@ -59,7 +59,7 @@ busyWidget->setSequence(m_busyPixmap); } -void ProgressIndicator::error(const QString &message) +void KNS3::ProgressIndicator::error(const KNSCore::ErrorCode& /*errorCode*/, const QString& message, const QVariant& /*metadata*/) { m_statusLabel->setText(message); busyWidget->setVisible(true); diff --git a/src/ui/progressindicator_p.h b/src/ui/progressindicator_p.h --- a/src/ui/progressindicator_p.h +++ b/src/ui/progressindicator_p.h @@ -21,6 +21,8 @@ #ifndef KNEWSTUFF3_PROGRESSINDICATOR_P_H #define KNEWSTUFF3_PROGRESSINDICATOR_P_H +#include "errorcode.h" + #include #include @@ -48,7 +50,7 @@ public Q_SLOTS: void busy(const QString &message); - void error(const QString &message); + void error(const KNSCore::ErrorCode &errorCode, const QString &message, const QVariant &metadata); void idle(const QString &message); private: