diff --git a/discover/qml/SourcesPage.qml b/discover/qml/SourcesPage.qml index ff9f4114..7ba5e4b7 100644 --- a/discover/qml/SourcesPage.qml +++ b/discover/qml/SourcesPage.qml @@ -1,231 +1,286 @@ import QtQuick 2.4 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.1 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kirigami 2.2 as Kirigami import "navigation.js" as Navigation DiscoverPage { id: page clip: true title: i18n("Settings") property string search: "" Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.View background: Rectangle { color: Kirigami.Theme.backgroundColor } contextualActions: [ KirigamiActionBridge { action: app.action("help_about_app") }, KirigamiActionBridge { action: app.action("help_report_bug") } ] mainItem: ListView { id: sourcesView model: QSortFilterProxyModel { filterRegExp: new RegExp(page.search, 'i') dynamicSortFilter: false //We don't want to sort, as sorting can have some semantics on some backends sourceModel: SourcesModel } currentIndex: -1 Component { id: sourceBackendDelegate Kirigami.AbstractListItem { id: backendItem hoverEnabled: false supportsMouseEvents: false readonly property QtObject backend: sourcesBackend readonly property bool isDefault: ResourcesModel.currentApplicationBackend == resourcesBackend RowLayout { Connections { target: backendItem.backend onPassiveMessage: window.showPassiveNotification(message) + onProceedRequest: { + var dialog = sourceProceedDialog.createObject(window, {sourcesBackend: sourcesBackend, title: title, description: description}) + dialog.open() + } } anchors { right: parent.right left: parent.left rightMargin: parent.rightPadding leftMargin: parent.leftPadding } Kirigami.Heading { Layout.fillWidth: true text: backendItem.isDefault ? i18n("%1 (Default)", resourcesBackend.displayName) : resourcesBackend.displayName } Button { Layout.rightMargin: Kirigami.Units.smallSpacing icon.name: "preferences-other" visible: resourcesBackend && resourcesBackend.hasApplications Component { id: dialogComponent AddSourceDialog { source: backendItem.backend onVisibleChanged: if (!visible) { destroy() } } } id: this onClicked: settingsMenu.popup(this) Menu { id: settingsMenu MenuItem { enabled: !backendItem.isDefault text: i18n("Make default") onTriggered: ResourcesModel.currentApplicationBackend = backendItem.backend.resourcesBackend } MenuItem { text: i18n("Add Source...") visible: backendItem.backend && backendItem.backend.supportsAdding onTriggered: { var addSourceDialog = dialogComponent.createObject(null, {displayName: backendItem.backend.resourcesBackend.displayName }) addSourceDialog.open() } } MenuSeparator { visible: backendActionsInst.count>0 } Instantiator { id: backendActionsInst model: ActionsModel { actions: backendItem.backend ? backendItem.backend.actions : undefined } delegate: MenuItem { action: ActionBridge { action: modelData.action } } + onObjectAdded: { settingsMenu.insertItem(index, object) } onObjectRemoved: { object.destroy() } } } } } } } delegate: ConditionalLoader { anchors { right: parent.right left: parent.left } readonly property variant resourcesBackend: model.resourcesBackend readonly property variant sourcesBackend: model.sourcesBackend readonly property variant display: model.display readonly property variant checked: model.checked readonly property variant statusTip: model.statusTip readonly property variant toolTip: model.toolTip readonly property variant sourceId: model.sourceId readonly property variant modelIndex: sourcesView.model.index(index, 0) condition: resourcesBackend != null componentTrue: sourceBackendDelegate componentFalse: sourceDelegate } + Component { + id: sourceProceedDialog + Kirigami.OverlaySheet { + id: sheet + showCloseButton: false + property QtObject sourcesBackend + property alias title: heading.text + property alias description: desc.text + property bool acted: false + ColumnLayout { + Kirigami.Heading { + id: heading + } + Label { + id: desc + Layout.fillWidth: true + textFormat: Text.StyledText + wrapMode: Text.WordWrap + } + RowLayout { + Layout.alignment: Qt.AlignRight + Button { + text: i18n("Proceed") + icon.name: "dialog-ok" + onClicked: { + sourcesBackend.proceed() + sheet.acted = true + sheet.close() + } + } + Button { + Layout.alignment: Qt.AlignRight + text: i18n("Cancel") + icon.name: "dialog-cancel" + onClicked: { + sourcesBackend.cancel() + sheet.acted = true + sheet.close() + } + } + } + } + onSheetOpenChanged: if(!sheetOpen) { + sheet.destroy(1000) + if (!sheet.acted) + sourcesBackend.cancel() + } + } + } + Component { id: sourceDelegate Kirigami.SwipeListItem { Layout.fillWidth: true enabled: display.length>0 highlighted: ListView.isCurrentItem onClicked: Navigation.openApplicationListSource(sourceId) Keys.onReturnPressed: clicked() actions: [ Kirigami.Action { iconName: "go-up" enabled: sourcesBackend.firstSourceId !== sourceId visible: sourcesBackend.canMoveSources onTriggered: { var ret = sourcesBackend.moveSource(sourceId, -1) if (!ret) window.showPassiveNotification(i18n("Failed to increase '%1' preference", display)) } }, Kirigami.Action { iconName: "go-down" enabled: sourcesBackend.lastSourceId !== sourceId visible: sourcesBackend.canMoveSources onTriggered: { var ret = sourcesBackend.moveSource(sourceId, +1) if (!ret) window.showPassiveNotification(i18n("Failed to decrease '%1' preference", display)) } }, Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Delete the origin") onTriggered: { var backend = sourcesBackend if (!backend.removeSource(sourceId)) { window.showPassiveNotification(i18n("Failed to remove the source '%1'", display)) } } } ] RowLayout { CheckBox { id: enabledBox readonly property variant modelChecked: sourcesView.model.data(modelIndex, Qt.CheckStateRole) checked: modelChecked != Qt.Unchecked enabled: modelChecked !== undefined onClicked: { - sourcesView.model.setData(modelIndex, modelChecked, Qt.CheckStateRole) + sourcesView.model.setData(modelIndex, checkState, Qt.CheckStateRole) } } Label { text: display + " - " + toolTip + "" elide: Text.ElideRight Layout.fillWidth: true } } } } footer: ColumnLayout { id: foot anchors { right: parent.right left: parent.left margins: Kirigami.Units.smallSpacing } Kirigami.Heading { Layout.fillWidth: true text: i18n("Missing Backends") visible: back.count>0 } Repeater { id: back model: ResourcesProxyModel { extending: "org.kde.discover.desktop" } delegate: Kirigami.BasicListItem { supportsMouseEvents: false label: name icon: model.icon InstallApplicationButton { application: model.application } } } } } } diff --git a/libdiscover/backends/FwupdBackend/FwupdBackend.cpp b/libdiscover/backends/FwupdBackend/FwupdBackend.cpp index cca2624b..61100c6d 100644 --- a/libdiscover/backends/FwupdBackend/FwupdBackend.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdBackend.cpp @@ -1,858 +1,858 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdBackend.h" #include "FwupdResource.h" #include "FwupdReviewsBackend.h" #include "FwupdTransaction.h" #include "FwupdSourcesBackend.h" #include #include #include #include #include #include #include #include #include #include #include #include #include DISCOVER_BACKEND_PLUGIN(FwupdBackend) #define STRING(s) #s // For Project Name and Version FwupdBackend::FwupdBackend(QObject* parent) : AbstractResourcesBackend(parent) , m_updater(new FwupdUpdater(this)) , m_reviews(new FwupdReviewsBackend(this)) , m_fetching(true) { QTimer::singleShot(500, this, &FwupdBackend::toggleFetching); connect(m_reviews, &FwupdReviewsBackend::ratingsReady, this, &AbstractResourcesBackend::emitRatingsReady); connect(m_updater, &FwupdUpdater::updatesCountChanged, this, &FwupdBackend::updatesCountChanged); client = fwupd_client_new (); toDownload = g_ptr_array_new_with_free_func (g_free); toIgnore = g_ptr_array_new_with_free_func (g_free); /* use a custom user agent to provide the fwupd version */ userAgent = fwupd_build_user_agent (STRING(PROJECT_NAME),STRING(PROJECT_VERSION)); soupSession = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, userAgent,SOUP_SESSION_TIMEOUT, 10,NULL); soup_session_remove_feature_by_type (soupSession,SOUP_TYPE_CONTENT_DECODER); if (!m_fetching) m_reviews->initialize(); populate(QStringLiteral("Releases")); SourcesModel::global()->addSourcesBackend(new FwupdSourcesBackend(this)); } FwupdBackend::~FwupdBackend() { g_object_unref (client); g_ptr_array_unref (toDownload); g_ptr_array_unref (toIgnore); } gchar* FwupdBackend::FwupdBuildDeviceID(FwupdDevice* device) { g_autofree gchar *tmp = g_strdup (fwupd_device_get_id (device)); g_strdelimit (tmp, "/", '_'); return g_strdup_printf ("org.fwupd.%s.device", tmp); } QString FwupdBackend::FwupdGetAppName(QString ID) { //To Do Implement it! return ID; } QSet FwupdBackend::FwupdGetAllUpdates() { QSet ret; ret.reserve(m_toUpdate.size()); foreach(FwupdResource* r, m_toUpdate) { AbstractResource* res = (AbstractResource*) r; if(r->m_id.isEmpty()) qDebug() << "Resource ID is Empty" << r->m_name; ret.insert(res); } return ret; } FwupdResource * FwupdBackend::FwupdCreateDevice(FwupdDevice *device) { const QString name = QLatin1String(fwupd_device_get_name(device)); - FwupdResource* res = new FwupdResource(name, false, this); + FwupdResource* res = new FwupdResource(name, true, this); res->setId(QLatin1String(FwupdBuildDeviceID(device))); res->addCategories(QStringLiteral("Releases")); res->setIconName(QLatin1String((const gchar *)g_ptr_array_index (fwupd_device_get_icons(device),0)));// Implement a Better way to decide icon FwupdSetDeviceDetails(res,device); return res; } FwupdResource * FwupdBackend::FwupdCreateRelease(FwupdDevice *device) { FwupdRelease *rel = fwupd_device_get_release_default (device); const QString name = QLatin1String(fwupd_release_get_name(rel)); - FwupdResource* res = new FwupdResource(name, false, this); + FwupdResource* res = new FwupdResource(name, true, this); res->setDeviceID(QLatin1String(fwupd_device_get_id (device))); FwupdSetReleaseDetails(res,rel); FwupdSetDeviceDetails(res,device); if (fwupd_release_get_appstream_id (rel) != NULL) res->setId(QLatin1String(fwupd_release_get_appstream_id (rel))); /* the same as we have already */ if (g_strcmp0 (fwupd_device_get_version (device),fwupd_release_get_version (rel)) == 0) { qWarning() << "same firmware version as installed"; } return res; } void FwupdBackend::FwupdSetReleaseDetails(FwupdResource *res,FwupdRelease *rel) { res->addCategories(QLatin1String("Releases")); if(fwupd_release_get_summary(rel)) res->setSummary(QLatin1String(fwupd_release_get_summary(rel))); if(fwupd_release_get_vendor(rel) != NULL) res->setVendor(QLatin1String(fwupd_release_get_vendor(rel))); if(fwupd_release_get_version(rel) != NULL) res->setVersion(QLatin1String(fwupd_release_get_version(rel))); if(fwupd_release_get_description(rel) != NULL) res->setDescription(QLatin1String((fwupd_release_get_description (rel)))); if(fwupd_release_get_homepage(rel) != NULL) res->setHomePage(QUrl(QLatin1String(fwupd_release_get_homepage(rel)))); if(fwupd_release_get_license(rel)) res->setLicense(QLatin1String(fwupd_release_get_license(rel))); if (fwupd_release_get_uri (rel) != NULL) { res->m_updateURI = QLatin1String(fwupd_release_get_uri (rel)); } } void FwupdBackend::FwupdSetDeviceDetails(FwupdResource *res,FwupdDevice *dev) { GPtrArray *guids; if (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE)) res->isLiveUpdatable = true; if (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_ONLY_OFFLINE)) res->isOnlyOffline = true; if (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT)) res->needsReboot = true; if (!fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_INTERNAL)) res->isDeviceRemoval = true; guids = fwupd_device_get_guids (dev); if(guids->len > 0) { g_autofree gchar *guid_str = NULL; g_auto(GStrv) tmp = g_new0 (gchar *, guids->len + 1); for (int i = 0; i < (int)guids->len; i++) tmp[i] = g_strdup ((gchar *)g_ptr_array_index (guids, i)); guid_str = g_strjoinv (",", tmp); res->guidString = guid_str; } if(fwupd_device_get_name (dev) != NULL) { g_autofree gchar *vendor_name = NULL; if (g_str_has_prefix (fwupd_device_get_name (dev),fwupd_device_get_vendor (dev))) { vendor_name = g_strdup (fwupd_device_get_name (dev)); } else { vendor_name = g_strdup_printf ("%s %s",fwupd_device_get_vendor (dev), fwupd_device_get_name (dev)); } res->setName(QLatin1String(vendor_name)); } if(fwupd_device_get_summary (dev) != NULL) res->setSummary(QLatin1String(fwupd_device_get_summary(dev))); if(fwupd_device_get_vendor(dev) != NULL) res->setVendor(QLatin1String(fwupd_device_get_vendor(dev))); if(fwupd_device_get_version(dev) != NULL) res->setVersion(QLatin1String(fwupd_device_get_version(dev))); if(fwupd_device_get_description(dev) != NULL) res->setDescription(QLatin1String((fwupd_device_get_description(dev)))); } void FwupdBackend::populate(const QString& n) { g_autoptr(GPtrArray) devices = NULL; /* get devices */ devices = fwupd_client_get_devices (client, NULL, NULL); if (devices != NULL) { for (int i = 0; i < (int)devices->len; i++) { FwupdDevice *device = (FwupdDevice *)g_ptr_array_index (devices, i); FwupdResource * res = NULL; g_autoptr(GPtrArray) releases = NULL; /* Devices Which are not updatable */ - if (!fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE)) - continue; + // if (!fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE)) + // continue; /* add releases */ res = FwupdCreateDevice(device); res->addCategories(n); releases = fwupd_client_get_releases (client,res->m_deviceID.toUtf8().constData(),NULL,NULL); if (releases != NULL) { for (int j = 0; j < (int)releases->len; j++) { FwupdRelease *rel = (FwupdRelease *)g_ptr_array_index (releases, j); const QString name = QLatin1String(fwupd_release_get_name(rel)); - FwupdResource* res_ = new FwupdResource(name, false, this); + FwupdResource* res_ = new FwupdResource(name, true, this); FwupdSetReleaseDetails (res_, rel); res->m_releases.append(res_); } } /* add all Valid Resources */ m_resources.insert(res->name().toLower(), res); } } } void FwupdBackend::FwupdAddUpdates() { g_autoptr(GPtrArray) remotes = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; g_autoptr(GError) error2 = NULL; g_autoptr(GPtrArray) devices = NULL; g_autoptr(GPtrArray) rels = NULL; /* get All devices, Will filter latter */ devices = fwupd_client_get_devices (client, cancellable, &error); if(devices == NULL){ if (g_error_matches (error,FWUPD_ERROR,FWUPD_ERROR_NOTHING_TO_DO)){ #ifdef FWUPD_DEBUG qDebug() << "No Devices Found"; #endif FwupdHandleError(&error); } } else{ for (int i = 0; i < (int)devices->len; i++) { FwupdDevice *device = (FwupdDevice *)g_ptr_array_index (devices, i); FwupdResource* res; - //res = FwupdCreateDevice(device); //just to test code should be deleted - //m_toUpdate.append(res); //just to test code should be deleted + res = FwupdCreateDevice(device); //just to test code should be deleted + m_toUpdate.append(res); //just to test code should be deleted if (!fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_SUPPORTED)) continue; /*Device is Locked Needs Unlocking*/ if (fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_LOCKED)) { res = FwupdCreateDevice(device); res->setIsDeviceLocked(true); m_toUpdate.append(res); connect(res, &FwupdResource::stateChanged, this, &FwupdBackend::updatesCountChanged); continue; } rels = fwupd_client_get_upgrades (client,fwupd_device_get_id(device),cancellable, &error2); if (rels == NULL) { if (g_error_matches (error2,FWUPD_ERROR,FWUPD_ERROR_NOTHING_TO_DO)){ qWarning() << "No Packages Found for "<< fwupd_device_get_id(device); FwupdHandleError(&error2); continue; } } else{ fwupd_device_add_release(device,(FwupdRelease *)g_ptr_array_index(rels,0)); if(FwupdAddToSchedule(device)) { qWarning() << "Cannot Add To Schdule" << fwupd_device_get_id(device); continue; } } } } } gchar* FwupdBackend::FwupdGetChecksum(const gchar *filename,GChecksumType checksum_type) { gsize len; g_autofree gchar *data = NULL; if (!g_file_get_contents (filename, &data, &len, NULL)) { qWarning() << "Cannot Access File!" << filename; return NULL; } return g_compute_checksum_for_data (checksum_type, (const guchar *)data, len); } bool FwupdBackend::FwupdAddToSchedule(FwupdDevice *device) { FwupdRelease *rel = fwupd_device_get_release_default (device); GPtrArray *checksums; const gchar *update_uri; g_autofree gchar *basename = NULL; g_autofree gchar *filename_cache = NULL; g_autoptr(GFile) file = NULL; FwupdResource* app = NULL; /* update unsupported */ app = FwupdCreateRelease(device); if (!app->isLiveUpdatable) { qWarning() << app->m_name << "[" << app->m_id << "]" << "cannot be updated "; return false; } /* Important Attributes missing */ if (app->m_id.isNull()) { qWarning() << "fwupd: No id for firmware"; return true; } if (app->m_version.isNull()) { qWarning() << "fwupd: No version! for " << app->m_id; return true; } if (app->m_updateVersion.isNull()) { qWarning() << "fwupd: No update-version! for " << app->m_id; return true; } checksums = fwupd_release_get_checksums (rel); if (checksums->len == 0) { qWarning() << app->m_name << "[" << app->m_id << "]" << "(" << app->m_updateVersion << ")" "has no checksums, ignoring as unsafe"; return false; } update_uri = fwupd_release_get_uri (rel); if (update_uri == NULL) { qWarning() << "no location available for" << app->m_name << "[" << app->m_id << "]"; return false; } /* Checking for firmware in the cache? */ basename = g_path_get_basename (update_uri); filename_cache = FwupdCacheFile("fwupd",basename); if (filename_cache == NULL) return false; if (g_file_test (filename_cache, G_FILE_TEST_EXISTS)) { const gchar *checksum_tmp = NULL; g_autofree gchar *checksum = NULL; /* Currently LVFS supports SHA1 only*/ checksum_tmp = fwupd_checksum_get_by_kind (checksums,G_CHECKSUM_SHA1); if (checksum_tmp == NULL) { qWarning() << "No valid checksum for" << filename_cache; } checksum = FwupdGetChecksum(filename_cache,G_CHECKSUM_SHA1); if (checksum == NULL) return false; if (g_strcmp0 (checksum_tmp, checksum) != 0) { qWarning() << filename_cache << " does not match checksum, expected" << checksum_tmp << "got" << checksum; g_unlink (filename_cache); return false; } } /* link file to application and append to update list */ file = g_file_new_for_path (filename_cache); app->m_file = file; m_toUpdate.append(app); /* schedule for download */ if (!g_file_test (filename_cache, G_FILE_TEST_EXISTS)) FwupdAddToScheduleForDownload(update_uri); return true; } bool FwupdBackend::FwupdDownloadFile(const gchar *uri,const gchar *filename) { guint status_code; g_autoptr(SoupMessage) msg = NULL; g_return_val_if_fail (uri != NULL, FALSE); g_return_val_if_fail (filename != NULL, FALSE); g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error_local = NULL; if (g_str_has_prefix (uri, "file://")) { gsize length = 0; g_autofree gchar *contents = NULL; if (!g_file_get_contents (uri + 7, &contents, &length, &error_local)) { qWarning() << "Cannot Access File" << uri; return false; } if (!g_file_set_contents (filename, contents, length, &error_local)) { qWarning() << "Cannot Save the file content in " << filename; return false; } return true; } /* remote */ #ifdef FWUPD_DEBUG qDebug() << "downloading " << uri << " to " << filename; #endif msg = soup_message_new (SOUP_METHOD_GET, uri); if (msg == NULL) { // To DO Error Handling return false; } status_code = soup_session_send_message (soupSession, msg); if (status_code != SOUP_STATUS_OK) { g_autoptr(GString) str = g_string_new (NULL); g_string_append (str, soup_status_get_phrase (status_code)); if (msg->response_body->data != NULL) { g_string_append (str, ": "); g_string_append (str, msg->response_body->data); } // To DO Error Handling return false; } if (!g_file_set_contents (filename,msg->response_body->data,msg->response_body->length,&error_local)) { qWarning() << "Cannot Save the file content in " << filename; return false; } return true; } GBytes* FwupdBackend::FwupdDownloadData(const gchar *uri) { guint status_code; g_autoptr(SoupMessage) msg = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; g_return_val_if_fail (uri != NULL, NULL); /* local */ if (g_str_has_prefix (uri, "file://")) { gsize length = 0; g_autofree gchar *contents = NULL; g_autoptr(GError) error_local = NULL; if (!g_file_get_contents (uri + 7, &contents, &length, &error_local)) { // To DO Error Handling return NULL; } return g_bytes_new (contents, length); } /* remote */ msg = soup_message_new (SOUP_METHOD_GET, uri); status_code = soup_session_send_message (soupSession, msg); if (status_code != SOUP_STATUS_OK) { g_autoptr(GString) str = g_string_new (NULL); g_string_append (str, soup_status_get_phrase (status_code)); if (msg->response_body->data != NULL) { g_string_append (str, ": "); g_string_append (str, msg->response_body->data); } // TO Do Error Handling return NULL; } return g_bytes_new (msg->response_body->data,(gsize) msg->response_body->length); } bool FwupdBackend::FwupdRefreshRemotes(guint cache_age) { g_autoptr(GPtrArray) remotes = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; /*Gets all Remotes will filter later*/ remotes = fwupd_client_get_remotes (client, cancellable, &error); if (remotes == NULL) return false; for (int i = 0; i < (int)remotes->len; i++) { FwupdRemote *remote = (FwupdRemote *)g_ptr_array_index (remotes, i); /*Remotes disabled by user so ignore*/ if (!fwupd_remote_get_enabled (remote)) continue; /*Local Remotes Ignore*/ if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL) continue; /*Refresh the left ones*/ if (!FwupdRefreshRemote(remote, cache_age)) return false; } return true; } bool FwupdBackend::FwupdRefreshRemote(FwupdRemote *remote,guint cache_age) { GChecksumType checksum_kind; const gchar *url_sig = NULL; const gchar *url = NULL; g_autoptr(GError) error_local = NULL; g_autofree gchar *basename = NULL; g_autofree gchar *basename_sig = NULL; g_autofree gchar *cache_id = NULL; g_autofree gchar *checksum = NULL; g_autofree gchar *filename = NULL; g_autofree gchar *filename_sig = NULL; g_autoptr(GBytes) data = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; if (fwupd_remote_get_filename_cache_sig (remote) == NULL) { qWarning() << "Remote " << fwupd_remote_get_id (remote) << "has no cache signature!"; return false; } /* check cache age */ if (cache_age > 0) { guint64 age = fwupd_remote_get_age (remote); guint tmp = age < G_MAXUINT ? (guint) age : G_MAXUINT; if (tmp < cache_age) { #ifdef FWUPD_DEBUG qDebug() << filename_sig << "is only" << tmp << "seconds old, so ignoring refresh! "; #endif return true; } } cache_id = g_strdup_printf ("fwupd/remotes.d/%s", fwupd_remote_get_id (remote)); basename_sig = g_path_get_basename (fwupd_remote_get_filename_cache_sig (remote)); filename_sig = FwupdCacheFile(cache_id,basename_sig); /* download the signature first*/ url_sig = fwupd_remote_get_metadata_uri_sig (remote); #ifdef FWUPD_DEBUG qDebug() << "Download Remotes Signature"; #endif data = FwupdDownloadData(url_sig); if (data == NULL) { //To Do Error Handling return false; } checksum_kind = fwupd_checksum_guess_kind (fwupd_remote_get_checksum (remote)); checksum = g_compute_checksum_for_data (checksum_kind,(const guchar *) g_bytes_get_data (data, NULL),g_bytes_get_size (data)); if (g_strcmp0 (checksum, fwupd_remote_get_checksum (remote)) == 0) { #ifdef FWUPD_DEBUG qDebug() << "signature of" << url_sig << "is unchanged"; #endif return true; } /* save to a file */ #ifdef FWUPD_DEBUG qDebug() << "saving new remote signature to:" << filename_sig; #endif if (!g_file_set_contents (filename_sig,(const gchar*)g_bytes_get_data (data, NULL),(guint) g_bytes_get_size (data),&error_local)) { qWarning() << "cannot save signature"; return false; } basename = g_path_get_basename (fwupd_remote_get_filename_cache (remote)); filename = FwupdCacheFile(cache_id,basename); if (filename == NULL) return FALSE; #ifdef FWUPD_DEBUG qDebug() << "saving new firmware metadata to:" << filename; qDebug() << "Downloading remotes metadata"; #endif url = fwupd_remote_get_metadata_uri (remote); if (!FwupdDownloadFile (url, filename)) { qWarning() << "Cannot Download File : " << filename ; return false; } /* Sending Metadata to fwupd Daemon*/ if (!fwupd_client_update_metadata (client,fwupd_remote_get_id (remote),filename,filename_sig,cancellable,&error)) { FwupdHandleError(&error); return false; } return true; } void FwupdBackend::FwupdHandleError(GError **perror) { GError *error = perror != NULL ? *perror : NULL; if(error == NULL) return; //To DO Indivitual take action based on case,Show Notification on Discover; switch (error->code) { case FWUPD_ERROR_ALREADY_PENDING: qWarning() << "FWUPD_ERROR_ALREADY_PENDING"; break; case FWUPD_ERROR_INVALID_FILE: qWarning() << "FWUPD_ERROR_INVALID_FILE"; break; case FWUPD_ERROR_NOT_SUPPORTED: qWarning() << "FWUPD_ERROR_NOT_SUPPORTED"; break; case FWUPD_ERROR_AUTH_FAILED: qWarning() << "FWUPD_ERROR_AUTH_FAILED"; break; case FWUPD_ERROR_SIGNATURE_INVALID: qWarning() << "FWUPD_ERROR_SIGNATURE_INVALID"; break; case FWUPD_ERROR_AC_POWER_REQUIRED: qWarning() << "FWUPD_ERROR_AC_POWER_REQUIRED"; break; default: qWarning() << "Unknown Error ::" << error->code; break; } } gchar* FwupdBackend::FwupdCacheFile(const gchar *kind,const gchar *resource) { g_autofree gchar *basename = NULL; g_autofree gchar *cachedir = NULL; g_autoptr(GFile) cachedir_file = NULL; g_autoptr(GPtrArray) candidates = g_ptr_array_new_with_free_func (g_free); g_autoptr(GError) error = NULL; basename = g_path_get_basename (resource); cachedir = g_build_filename (g_get_user_cache_dir (),"discover",kind,NULL); cachedir_file = g_file_new_for_path (cachedir); if (!g_file_query_exists (cachedir_file, NULL) && !g_file_make_directory_with_parents (cachedir_file, NULL, &error)) return NULL; g_ptr_array_add (candidates, g_build_filename (cachedir, basename, NULL)); return g_strdup((gchar *)g_ptr_array_index (candidates, 0)); } bool FwupdBackend::FwupdDownloadAllScheduled(guint cache_age) { const gchar *tmp; if (!FwupdRefreshRemotes(cache_age)) return false; /* download the files to the cachedir */ for (int i = 0; i < (int)toDownload->len; i++) { g_autoptr(GError) error_local = NULL; g_autofree gchar *basename = NULL; g_autofree gchar *filename_cache = NULL; tmp = (gchar *)g_ptr_array_index (toDownload, i); basename = g_path_get_basename (tmp); filename_cache = FwupdCacheFile("fwupd", basename); if (filename_cache == NULL) return false; /* download file */ if (!FwupdDownloadFile(tmp, filename_cache)) { qWarning() <<"Failed to download " << tmp << ", ignoring:" ; g_ptr_array_remove_index (toDownload, i--); g_ptr_array_add (toIgnore, g_strdup (tmp)); continue; } } return true; } bool FwupdBackend::FwupdAddToScheduleForDownload(const gchar * uri) { const gchar *tmp; for (int i = 0; i < (int)toIgnore->len; i++) { tmp = (gchar *)g_ptr_array_index (toIgnore, i); if (g_strcmp0 (tmp, uri) == 0) return false; } for (int i = 0; i < (int)toDownload->len; i++) { tmp = (gchar *)g_ptr_array_index (toDownload, i); if (g_strcmp0 (tmp, uri) == 0) return false; } g_ptr_array_add (toDownload, g_strdup (uri)); return true; } void FwupdBackend::toggleFetching() { m_fetching = !m_fetching; #ifdef FWUPD_DEBUG qDebug() << "Fwupd fetching..." << m_fetching; #endif FwupdAddUpdates(); FwupdDownloadAllScheduled(60*60*24*30); // Nicer Way to put time? currently 30 days in seconds emit fetchingChanged(); } int FwupdBackend::updatesCount() const { return m_updater->updatesCount(); } ResultsStream* FwupdBackend::search(const AbstractResourcesBackend::Filters& filter) { QVector ret; if (!filter.resourceUrl.isEmpty() && filter.resourceUrl.scheme() == QLatin1String("fwupd")) return findResourceByPackageName(filter.resourceUrl); else foreach(AbstractResource* r, m_resources) { if(r->name().contains(filter.search, Qt::CaseInsensitive) || r->comment().contains(filter.search, Qt::CaseInsensitive)) ret += r; } return new ResultsStream(QStringLiteral("Firmware Updates Stream"), ret); } ResultsStream * FwupdBackend::findResourceByPackageName(const QUrl& search) { auto res = search.scheme() == QLatin1String("fwupd") ? m_resources.value(search.host().replace(QLatin1Char('.'), QLatin1Char(' '))) : NULL; if (!res) { return new ResultsStream(QStringLiteral("Firmware Updates Stream"), {}); } else return new ResultsStream(QStringLiteral("Firmware Updates Stream"), { res }); } AbstractBackendUpdater* FwupdBackend::backendUpdater() const { return m_updater; } AbstractReviewsBackend* FwupdBackend::reviewsBackend() const { - //return m_reviews; // To Remove the Review backend not needed + //return m_reviews; // To Remove the Review backend ( not needed) return NULL; } Transaction* FwupdBackend::installApplication(AbstractResource* app, const AddonList& addons) { return new FwupdTransaction(qobject_cast(app), this, addons, Transaction::InstallRole); } Transaction* FwupdBackend::installApplication(AbstractResource* app) { return new FwupdTransaction(qobject_cast(app), this, Transaction::InstallRole); } Transaction* FwupdBackend::removeApplication(AbstractResource* app) { return new FwupdTransaction(qobject_cast(app), this, Transaction::RemoveRole); } void FwupdBackend::checkForUpdates() { if(m_fetching) return; toggleFetching(); populate(QStringLiteral("Releases")); QTimer::singleShot(500, this, &FwupdBackend::toggleFetching); #ifdef FWUPD_DEBUG qDebug() << "FwupdBackend::checkForUpdates"; #endif } AbstractResource * FwupdBackend::resourceForFile(const QUrl& path) { g_autofree gchar *content_type = NULL; g_autofree gchar *filename = NULL; g_autoptr(GPtrArray) devices = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; QMimeDatabase db; QMimeType type = db.mimeTypeForFile(path.fileName()); if(type.isValid() && type.inherits(QStringLiteral("application/vnd.ms-cab-compressed"))) { filename = path.fileName().toUtf8().data(); devices = fwupd_client_get_details (client,filename,cancellable,&error); if (devices != NULL) { for (int i = 0; i < (int)devices->len; i++) { FwupdDevice *dev = (FwupdDevice *)g_ptr_array_index (devices, i); FwupdResource* app = NULL; app = FwupdCreateRelease(dev); app->setState(AbstractResource::None); m_resources.insert(app->packageName(), app); connect(app, &FwupdResource::stateChanged, this, &FwupdBackend::updatesCountChanged); return app; } } else { FwupdHandleError(&error); } } return NULL; } QString FwupdBackend::displayName() const { return QStringLiteral("Firmware Updates"); } bool FwupdBackend::hasApplications() const { return m_resources.count() ? true : false; } #include "FwupdBackend.moc" diff --git a/libdiscover/backends/FwupdBackend/FwupdNotifier.cpp b/libdiscover/backends/FwupdBackend/FwupdNotifier.cpp index 0bb14906..1496840a 100644 --- a/libdiscover/backends/FwupdBackend/FwupdNotifier.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdNotifier.cpp @@ -1,46 +1,48 @@ /*************************************************************************** * Copyright © 2013 Lukas Appelhans * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdNotifier.h" #include FwupdNotifier::FwupdNotifier(QObject* parent) : BackendNotifierModule(parent) + , m_securityUpdates(0) + , m_normalUpdates(0) { } FwupdNotifier::~FwupdNotifier() { } void FwupdNotifier::recheckSystemUpdateNeeded() { emit foundUpdates(); } uint FwupdNotifier::securityUpdatesCount() { return 0; } uint FwupdNotifier::updatesCount() { return 0; } diff --git a/libdiscover/backends/FwupdBackend/FwupdNotifier.h b/libdiscover/backends/FwupdBackend/FwupdNotifier.h index 329f8d61..d6a5da9f 100644 --- a/libdiscover/backends/FwupdBackend/FwupdNotifier.h +++ b/libdiscover/backends/FwupdBackend/FwupdNotifier.h @@ -1,39 +1,43 @@ /*************************************************************************** * Copyright © 2013 Lukas Appelhans * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #ifndef FWUPDNOTIFIER_H #define FWUPDNOTIFIER_H #include class FwupdNotifier : public BackendNotifierModule { Q_OBJECT Q_PLUGIN_METADATA(IID "org.kde.discover.BackendNotifierModule") Q_INTERFACES(BackendNotifierModule) public: explicit FwupdNotifier(QObject* parent = nullptr); ~FwupdNotifier() override; void recheckSystemUpdateNeeded() override; uint securityUpdatesCount() override; uint updatesCount() override; + +private: + uint m_securityUpdates; + uint m_normalUpdates; }; #endif diff --git a/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.cpp b/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.cpp index 390cb6b8..1833c76a 100644 --- a/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.cpp @@ -1,127 +1,175 @@ /*************************************************************************** * Copyright © 2014 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdSourcesBackend.h" #include #include #include +#include + class FwupdSourcesModel : public QStandardItemModel { +Q_OBJECT public: FwupdSourcesModel(FwupdSourcesBackend* backend) : QStandardItemModel(backend) , m_backend(backend) {} QHash roleNames() const override { auto roles = QStandardItemModel::roleNames(); roles[Qt::CheckStateRole] = "checked"; return roles; } bool setData(const QModelIndex & index, const QVariant & value, int role) override { auto item = itemFromIndex(index); if (!item) return false; - switch(role) { - case Qt::CheckStateRole: { - // To Do Show Agrement - status = fwupd_remote_get_enabled(fwupd_client_get_remote_by_id(m_backend->backend->client,item->data(AbstractSourcesBackend::IdRole).toString().toUtf8().constData(),NULL,NULL)); - fwupd_client_modify_remote(m_backend->backend->client,item->data(AbstractSourcesBackend::IdRole).toString().toUtf8().constData(),QString(QLatin1String("Enabled")).toUtf8().constData(),(!status) ? (QString(QLatin1String("true")).toUtf8().constData()) : (QString(QLatin1String("false")).toUtf8().constData()),NULL,NULL); - return true; + remote = fwupd_client_get_remote_by_id(m_backend->backend->client,item->data(AbstractSourcesBackend::IdRole).toString().toUtf8().constData(),NULL,NULL); + status = fwupd_remote_get_enabled(remote); + switch(role) + { + case Qt::CheckStateRole: + { + if((value.toInt() == Qt::Checked) ) + { + m_backend->eulaRequired(QLatin1String(fwupd_remote_get_title(remote)),QLatin1String(fwupd_remote_get_agreement(remote))); + connect(m_backend,&FwupdSourcesBackend::proceed,this, + [=]() + { + if((value.toInt() == Qt::Checked) ) + { + if(fwupd_client_modify_remote(m_backend->backend->client,fwupd_remote_get_id(remote),QString(QLatin1String("Enabled")).toUtf8().constData(),(QString(QLatin1String("true")).toUtf8().constData()),NULL,NULL)) + item->setData(value, role); + } + else + { + if(fwupd_client_modify_remote(m_backend->backend->client,fwupd_remote_get_id(remote),QString(QLatin1String("Enabled")).toUtf8().constData(),(QString(QLatin1String("false")).toUtf8().constData()),NULL,NULL)) + item->setData(value, role); + } + } + ); + } + else if(value.toInt() == Qt::Unchecked) + { + if((value.toInt() == Qt::Checked) ) + { + if(fwupd_client_modify_remote(m_backend->backend->client,fwupd_remote_get_id(remote),QString(QLatin1String("Enabled")).toUtf8().constData(),(QString(QLatin1String("true")).toUtf8().constData()),NULL,NULL)) + item->setData(value, role); + } + else + { + if(fwupd_client_modify_remote(m_backend->backend->client,fwupd_remote_get_id(remote),QString(QLatin1String("Enabled")).toUtf8().constData(),(QString(QLatin1String("false")).toUtf8().constData()),NULL,NULL)) + item->setData(value, role); + } + } + } } - item->setData(value, role); + Q_EMIT dataChanged(index,index,{}); return true; } private: FwupdSourcesBackend* m_backend; + FwupdRemote* remote; bool status; }; FwupdSourcesBackend::FwupdSourcesBackend(AbstractResourcesBackend * parent) : AbstractSourcesBackend(parent) , m_sources(new FwupdSourcesModel(this)) { backend = qobject_cast(parent); g_autoptr(GPtrArray) remotes = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; /* find all remotes */ remotes = fwupd_client_get_remotes (backend->client,cancellable,&error); - if(remotes != NULL) + if(remotes != NULL) { for (int i = 0; i < (int)remotes->len; i++) { FwupdRemote *remote = (FwupdRemote *)g_ptr_array_index (remotes, i); if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL) continue; addSource(QLatin1String(fwupd_remote_get_id (remote))); } } } QAbstractItemModel* FwupdSourcesBackend::sources() { return m_sources; } +void FwupdSourcesBackend::eulaRequired( const QString& remoteName , const QString& licenseAgreement) +{ + Q_EMIT proceedRequest(i18n("Accept EULA"), i18n("The remote %1 require that you accept their license:\n %2", + remoteName, licenseAgreement)); +} + +void FwupdSourcesBackend::cancel() +{ + qDebug() << "Request Cancelled"; +} + bool FwupdSourcesBackend::addSource(const QString& id) { g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; FwupdBackend* backend = qobject_cast(parent()); FwupdRemote* remote; + bool status ; if (id.isEmpty()) return false; remote = fwupd_client_get_remote_by_id(backend->client,id.toUtf8().constData(),cancellable,&error); + status = !fwupd_remote_get_enabled(remote); QStandardItem* it = new QStandardItem(id); it->setData(id, AbstractSourcesBackend::IdRole); it->setData(QVariant(QLatin1Literal(fwupd_remote_get_title (remote))), Qt::ToolTipRole); it->setCheckable(true); - it->setCheckState(!fwupd_remote_get_enabled(remote) ? Qt::Unchecked : Qt::Checked); + it->setCheckState(status ? Qt::Unchecked : Qt::Checked); m_sources->appendRow(it); return true; } bool FwupdSourcesBackend::removeSource(const QString& id) { - QList items = m_sources->findItems(id); - if (items.count()==1) { - m_sources->removeRow(items.first()->row()); - } else { - qWarning() << "couldn't find " << id << items; - } - return items.count()==1; + qWarning() << "Removal of Sources Not Allowed" << "Remote-ID" << id; + return false; } QList FwupdSourcesBackend::actions() const { return m_actions ; } +#include "FwupdSourcesBackend.moc" + + diff --git a/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.h b/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.h index 6f150e55..c4870762 100644 --- a/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.h +++ b/libdiscover/backends/FwupdBackend/FwupdSourcesBackend.h @@ -1,49 +1,56 @@ /*************************************************************************** * Copyright © 2014 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #ifndef FWUPDSOURCESBACKEND_H #define FWUPDSOURCESBACKEND_H #include +#include "FwupdBackend.h" #include #include "FwupdBackend.h" class FwupdSourcesModel; class FwupdSourcesBackend : public AbstractSourcesBackend { + Q_OBJECT public: explicit FwupdSourcesBackend(AbstractResourcesBackend * parent); FwupdBackend* backend ; QAbstractItemModel* sources() override; bool addSource(const QString& id) override; bool removeSource(const QString& id) override; QString idDescription() override { return QStringLiteral(""); } QList actions() const override; bool supportsAdding() const override { return false; } + void eulaRequired(const QString& remoteName , const QString& licenseAgreement); + void cancel() override; +Q_SIGNALS: + void proceed() override; + private: FwupdSourcesModel* m_sources; QList m_actions; }; #endif // FWUPDSOURCESBACKEND_H diff --git a/libdiscover/backends/FwupdBackend/FwupdTransaction.cpp b/libdiscover/backends/FwupdBackend/FwupdTransaction.cpp index cfd2d85d..12f66ebc 100644 --- a/libdiscover/backends/FwupdBackend/FwupdTransaction.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdTransaction.cpp @@ -1,190 +1,191 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdTransaction.h" #include #include #include + #define TEST_PROCEED FwupdTransaction::FwupdTransaction(FwupdResource* app, FwupdBackend* backend, Role role) : FwupdTransaction(app, backend,{}, role) { } FwupdTransaction::FwupdTransaction(FwupdResource* app, FwupdBackend* backend, const AddonList& addons, Transaction::Role role) : Transaction(app->backend(), app, role, addons) , m_app(app) , m_backend(backend) { setCancellable(true); if(role == InstallRole) { if(!FwupdCheck()) qWarning() << "Error In Install!"; } else if(role == RemoveRole) { if(!FwupdRemove()) qWarning() << "Error in Remove!"; } iterateTransaction(); } FwupdTransaction::~FwupdTransaction() { } bool FwupdTransaction::FwupdCheck() { g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; if(m_app->isDeviceLocked) { const gchar *device_id; device_id = m_app->m_deviceID.toUtf8().constData(); if(device_id == NULL) { qWarning("No Device ID Set"); return false; } if (!fwupd_client_unlock (m_backend->client, device_id,cancellable, &error)) { m_backend->FwupdHandleError(&error); return false; } return true; } if(!FwupdInstall()) { // To DO error handling return false; } return true; } bool FwupdTransaction::FwupdInstall() { const gchar *device_id; FwupdInstallFlags install_flags = FWUPD_INSTALL_FLAG_NONE;//Removed 0 check for ussage GFile *local_file; g_autofree gchar *filename = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new(); g_autoptr(GError) error = NULL; local_file = m_app->m_file; if(local_file == NULL) { //to Do error handling qWarning("No Local File Set For this Resource"); return false; } filename = g_file_get_path (local_file); if (!g_file_query_exists (local_file, cancellable)) { const gchar *uri = m_app->m_updateURI.toUtf8().constData(); if(!m_backend->FwupdDownloadFile(uri,filename)) return false; } /* limit to single device? */ device_id = m_app->m_deviceID.toUtf8().constData(); if (device_id == NULL) device_id = FWUPD_DEVICE_ID_ANY; /* only offline supported */ if (m_app->isOnlyOffline) install_flags = FWUPD_INSTALL_FLAG_OFFLINE; // removed the bit wise or operation |= if (!fwupd_client_install (m_backend->client, device_id,filename, install_flags,cancellable, &error)) { m_backend->FwupdHandleError(&error); return false; } return true; } bool FwupdTransaction::FwupdRemove() { // To Do Implement It return true; } int FwupdTransaction::speed() { //To Do Implement It return 0; } void FwupdTransaction::iterateTransaction() { if (!m_iterate) return; setStatus(CommittingStatus); if(progress()<100) { setProgress(fwupd_client_get_percentage (m_backend->client)); QTimer::singleShot(100, this, &FwupdTransaction::iterateTransaction); } else #ifdef TEST_PROCEED Q_EMIT proceedRequest(QStringLiteral("yadda yadda"), QStringLiteral("Biii BOooo
  • A
  • A
  • A
  • A
")); #else finishTransaction(); #endif } void FwupdTransaction::proceed() { finishTransaction(); } void FwupdTransaction::cancel() { m_iterate = false; setStatus(CancelledStatus); } void FwupdTransaction::finishTransaction() { AbstractResource::State newState; switch(role()) { case InstallRole: case ChangeAddonsRole: newState = AbstractResource::Installed; break; case RemoveRole: newState = AbstractResource::None; break; } m_app->setAddons(addons()); m_app->setState(newState); setStatus(DoneStatus); deleteLater(); } diff --git a/libdiscover/backends/FwupdBackend/tests/CMakeLists.txt b/libdiscover/backends/FwupdBackend/tests/CMakeLists.txt index ddac8b17..008573e7 100644 --- a/libdiscover/backends/FwupdBackend/tests/CMakeLists.txt +++ b/libdiscover/backends/FwupdBackend/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -#add_unit_test(fwupdtest FwupdTest.cpp) +add_unit_test(fwupdtest FwupdTest.cpp) add_unit_test(updatefwupdtest UpdateFwupdTest.cpp) target_link_libraries(updatefwupdtest KF5::CoreAddons) diff --git a/libdiscover/backends/FwupdBackend/tests/FwupdTest.cpp b/libdiscover/backends/FwupdBackend/tests/FwupdTest.cpp index e4b4b0cd..ab6e43c5 100644 --- a/libdiscover/backends/FwupdBackend/tests/FwupdTest.cpp +++ b/libdiscover/backends/FwupdBackend/tests/FwupdTest.cpp @@ -1,289 +1,202 @@ /*************************************************************************** * Copyright © 2012 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdTest.h" #include "DiscoverBackendsFactory.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include QTEST_MAIN(FwupdTest) AbstractResourcesBackend* backendByName(ResourcesModel* m, const QString& name) { QVector backends = m->backends(); foreach(AbstractResourcesBackend* backend, backends) { if(QString::fromLatin1(backend->metaObject()->className()) == name) { return backend; } } return nullptr; } FwupdTest::FwupdTest(QObject* parent): QObject(parent) { DiscoverBackendsFactory::setRequestedBackends({ QStringLiteral("fwupd-backend") }); m_model = new ResourcesModel(QStringLiteral("fwupd-backend"), this); m_appBackend = backendByName(m_model, QStringLiteral("FwupdBackend")); // CategoryModel::global()->populateCategories(); } void FwupdTest::initTestCase() { QVERIFY(m_appBackend); while(m_appBackend->isFetching()) { QSignalSpy spy(m_appBackend, &AbstractResourcesBackend::fetchingChanged); QVERIFY(spy.wait()); } } QVector fetchResources(ResultsStream* stream) { QVector ret; QObject::connect(stream, &ResultsStream::resourcesFound, stream, [&ret](const QVector& res) { ret += res; }); QSignalSpy spy(stream, &ResultsStream::destroyed); Q_ASSERT(spy.wait()); return ret; } void FwupdTest::testReadData() { const auto resources = fetchResources(m_appBackend->search({})); QCOMPARE(m_appBackend->property("startElements").toInt()*2, resources.size()); QBENCHMARK { for(AbstractResource* res: resources) { QVERIFY(!res->name().isEmpty()); } } } void FwupdTest::testProxy() { ResourcesProxyModel pm; QSignalSpy spy(&pm, &ResourcesProxyModel::busyChanged); // QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); pm.setFiltersFromCategory(CategoryModel::global()->rootCategories().first()); pm.componentComplete(); QVERIFY(pm.isBusy()); QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); QCOMPARE(m_appBackend->property("startElements").toInt()*2, pm.rowCount()); pm.setSearch(QStringLiteral("techie")); QVERIFY(pm.isBusy()); QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); QCOMPARE(m_appBackend->property("startElements").toInt(), pm.rowCount()); QCOMPARE(pm.subcategories().count(), 7); pm.setSearch(QString()); QVERIFY(pm.isBusy()); QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); QCOMPARE(m_appBackend->property("startElements").toInt()*2, pm.rowCount()); } void FwupdTest::testProxySorting() { ResourcesProxyModel pm; QSignalSpy spy(&pm, &ResourcesProxyModel::busyChanged); // QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); pm.setFiltersFromCategory(CategoryModel::global()->rootCategories().first()); pm.setSortOrder(Qt::DescendingOrder); pm.setSortRole(ResourcesProxyModel::RatingCountRole); pm.componentComplete(); QVERIFY(pm.isBusy()); QVERIFY(spy.wait()); QVERIFY(!pm.isBusy()); QCOMPARE(m_appBackend->property("startElements").toInt()*2, pm.rowCount()); QVariant lastRatingCount; for(int i=0, rc=pm.rowCount(); isearch({})); QCOMPARE(m_appBackend->property("startElements").toInt()*2, resources.count()); //fetches updates, adds new things m_appBackend->checkForUpdates(); QSignalSpy spy(m_model, SIGNAL(allInitialized())); QVERIFY(spy.wait(80000)); auto resources2 = fetchResources(m_appBackend->search({})); QCOMPARE(m_appBackend->property("startElements").toInt()*4, resources2.count()); } void FwupdTest::testSort() { ResourcesProxyModel pm; QCollator c; QBENCHMARK_ONCE { pm.setSortRole(ResourcesProxyModel::NameRole); pm.sort(0); QCOMPARE(pm.sortOrder(), Qt::AscendingOrder); QString last; for(int i = 0, count = pm.rowCount(); ifindResourceByPackageName(QUrl(QStringLiteral("fwupd://Fwupd.1")))); - QCOMPARE(resources.count(), 1); - AbstractResource* res = resources.first(); - QVERIFY(res); - - ApplicationAddonsModel m; - new ModelTest(&m, &m); - m.setApplication(res); - QCOMPARE(m.rowCount(), res->addonsInformation().count()); - QCOMPARE(res->addonsInformation().at(0).isInstalled(), false); - - QString firstAddonName = m.data(m.index(0,0)).toString(); - m.changeState(firstAddonName, true); - QVERIFY(m.hasChanges()); - - m.applyChanges(); - QSignalSpy sR(TransactionModel::global(), &TransactionModel::transactionRemoved); - QVERIFY(sR.wait()); - QVERIFY(!m.hasChanges()); - - QCOMPARE(m.data(m.index(0,0)).toString(), firstAddonName); - QCOMPARE(res->addonsInformation().at(0).name(), firstAddonName); - QCOMPARE(res->addonsInformation().at(0).isInstalled(), true); - - m.changeState(m.data(m.index(1,0)).toString(), true); - QVERIFY(m.hasChanges()); - for(int i=0, c=m.rowCount(); ifindResourceByPackageName(QUrl(QStringLiteral("fwupd://Fwupd.1")))); - QCOMPARE(resources.count(), 1); - AbstractResource* res = resources.first(); - QVERIFY(res); - - ReviewsModel m; - new ModelTest(&m, &m); - m.setResource(res); - m.fetchMore(); - - QVERIFY(m.rowCount()>0); - - QCOMPARE(ReviewsModel::UserChoice(m.data(m.index(0,0), ReviewsModel::UsefulChoice).toInt()), ReviewsModel::None); - m.markUseful(0, true); - QCOMPARE(ReviewsModel::UserChoice(m.data(m.index(0,0), ReviewsModel::UsefulChoice).toInt()), ReviewsModel::Yes); - m.markUseful(0, false); - QCOMPARE(ReviewsModel::UserChoice(m.data(m.index(0,0), ReviewsModel::UsefulChoice).toInt()), ReviewsModel::No); - - const auto resources2 = fetchResources(m_appBackend->findResourceByPackageName(QUrl(QStringLiteral("fwupd://Fwupd.1")))); - QCOMPARE(resources2.count(), 1); - res = resources2.first(); - m.setResource(res); - m.fetchMore(); - - QSignalSpy spy(&m, &ReviewsModel::rowsChanged); - QVERIFY(m.rowCount()>0); -} - void FwupdTest::testUpdateModel() { const auto backend = m_model->backends().first(); ResourcesUpdatesModel ruModel; new ModelTest(&ruModel, &ruModel); UpdateModel model; new ModelTest(&model, &model); model.setBackend(&ruModel); QCOMPARE(model.rowCount(), 4*backend->property("startElements").toInt()/3); QCOMPARE(model.hasUpdates(), true); } -void FwupdTest::testScreenshotsModel() -{ - ScreenshotsModel m; - new ModelTest(&m, &m); - - const auto resources = fetchResources(m_appBackend->findResourceByPackageName(QUrl(QStringLiteral("fwupd://Fwupd.1")))); - QCOMPARE(resources.count(), 1); - AbstractResource* res = resources.first(); - QVERIFY(res); - m.setResource(res); - QCOMPARE(res, m.resource()); - - int c=m.rowCount(); - for(int i=0; i * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ -#ifndef DUMMYTEST_H -#define DUMMYTEST_H +#ifndef FWUPDTEST_H +#define FWUPDTEST_H #include class ResourcesModel; class AbstractResourcesBackend; class FwupdTest : public QObject { Q_OBJECT public: explicit FwupdTest(QObject* parent = nullptr); private Q_SLOTS: void initTestCase(); void testReadData(); void testProxy(); void testProxySorting(); void testFetch(); void testSort(); - void testInstallAddons(); - void testReviewsModel(); void testUpdateModel(); - void testScreenshotsModel(); private: AbstractResourcesBackend* m_appBackend; ResourcesModel* m_model; }; -#endif // DUMMYTEST_H +#endif // FWUPDTEST_H diff --git a/libdiscover/resources/AbstractSourcesBackend.h b/libdiscover/resources/AbstractSourcesBackend.h index a8cab709..ba0d5b3a 100644 --- a/libdiscover/resources/AbstractSourcesBackend.h +++ b/libdiscover/resources/AbstractSourcesBackend.h @@ -1,76 +1,81 @@ /*************************************************************************** * Copyright © 2014 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #ifndef ABSTRACTSOURCESMANAGER_H #define ABSTRACTSOURCESMANAGER_H #include #include "discovercommon_export.h" class QAction; class QAbstractItemModel; class AbstractResourcesBackend; class DISCOVERCOMMON_EXPORT AbstractSourcesBackend : public QObject { Q_OBJECT Q_PROPERTY(AbstractResourcesBackend* resourcesBackend READ resourcesBackend CONSTANT) Q_PROPERTY(QAbstractItemModel* sources READ sources CONSTANT) Q_PROPERTY(QString idDescription READ idDescription CONSTANT) Q_PROPERTY(QList actions READ actions CONSTANT) Q_PROPERTY(bool supportsAdding READ supportsAdding CONSTANT) Q_PROPERTY(bool canMoveSources READ canMoveSources CONSTANT) Q_PROPERTY(QString firstSourceId READ firstSourceId NOTIFY firstSourceIdChanged) Q_PROPERTY(QString lastSourceId READ lastSourceId NOTIFY lastSourceIdChanged) public: explicit AbstractSourcesBackend(AbstractResourcesBackend* parent); ~AbstractSourcesBackend() override; enum Roles { IdRole = Qt::UserRole, LastRole }; Q_ENUM(Roles) virtual QString idDescription() = 0; Q_SCRIPTABLE virtual bool addSource(const QString& id) = 0; Q_SCRIPTABLE virtual bool removeSource(const QString& id) = 0; virtual QAbstractItemModel* sources() = 0; virtual QList actions() const = 0; virtual bool supportsAdding() const = 0; AbstractResourcesBackend* resourcesBackend() const; virtual bool canMoveSources() const { return false; } Q_SCRIPTABLE virtual bool moveSource(const QString &sourceId, int delta); QString firstSourceId() const; QString lastSourceId() const; + public Q_SLOTS: + virtual void cancel() {} + virtual void proceed() {} + Q_SIGNALS: void firstSourceIdChanged(); void lastSourceIdChanged(); void passiveMessage(const QString &message); + void proceedRequest(const QString &title, const QString &description); }; #endif // ABSTRACTRESOURCESBACKEND_H