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"));
#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