diff --git a/AppSetup/SimplePage.h b/AppSetup/SimplePage.h index fd27ec1..b40296f 100644 --- a/AppSetup/SimplePage.h +++ b/AppSetup/SimplePage.h @@ -1,51 +1,50 @@ /* This file is part of Apper * * Copyright (C) 2012 Matthias Klumpp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SIMPLE_PAGE_H #define SIMPLE_PAGE_H #include #include -#include namespace Ui { class SimplePage; } class SimplePage : public QWidget { Q_OBJECT public: explicit SimplePage(QWidget *parent = 0); ~SimplePage(); void setTitle(const QString& title); void setDescription(const QString &description); void setDetails(const QString &details, bool isHtml = true); void reset(); void addWidget(QWidget *widget); private: int m_pageId; Ui::SimplePage *ui; }; #endif diff --git a/ApperKCM/ApperKCM.cpp b/ApperKCM/ApperKCM.cpp index 8cfe823..bea3101 100644 --- a/ApperKCM/ApperKCM.cpp +++ b/ApperKCM/ApperKCM.cpp @@ -1,942 +1,944 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "ApperKCM.h" #include "ui_ApperKCM.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include #ifdef HAVE_APPSTREAM #include #endif #include #include #include "FiltersMenu.h" #include "BrowseView.h" #include "CategoryModel.h" #include "TransactionHistory.h" #include "Settings/Settings.h" #include "Updater/Updater.h" #define BAR_SEARCH 0 #define BAR_UPDATE 1 #define BAR_SETTINGS 2 #define BAR_TITLE 3 KCONFIGGROUP_DECLARE_ENUM_QOBJECT(Transaction, Filter) K_PLUGIN_FACTORY(ApperFactory, registerPlugin();) K_EXPORT_PLUGIN(ApperFactory("kcm_apper", "apper")) ApperKCM::ApperKCM(QWidget *parent, const QVariantList &args) : KCModule(parent, args), ui(new Ui::ApperKCM), m_currentAction(0), m_groupsProxyModel(0), m_settingsPage(0), m_updaterPage(0), m_searchTransaction(0), - m_findIcon("edit-find"), - m_cancelIcon("dialog-cancel"), + m_findIcon(QIcon::fromTheme("edit-find")), + m_cancelIcon(QIcon::fromTheme("dialog-cancel")), m_forceRefreshCache(false), m_cacheAge(600), m_history(0), m_searchRole(Transaction::RoleUnknown) { KAboutData *aboutData; aboutData = new KAboutData("kcm_apper", "apper", APPER_VERSION, i18n("KDE interface for managing software"), KAboutLicense::LicenseKey::GPL); aboutData->addAuthor(i18n("(C) 2008-2013 Daniel Nicoletti"), QString(), "dantti12@gmail.com", "http://dantti.wordpress.com"); aboutData->addAuthor(i18n("Matthias Klumpp"), QString(), QStringLiteral("matthias@tenstral.net")); setAboutData(aboutData); setButtons(Apply); // store the actions supported by the backend connect(Daemon::global(), SIGNAL(changed()), this, SLOT(daemonChanged())); // Set the current locale - QString locale(KGlobal::locale()->language() % QLatin1Char('.') % KGlobal::locale()->encoding()); + QString locale(KLocale::global()->language() % QLatin1Char('.') % KLocale::global()->encoding()); Daemon::global()->setHints(QLatin1String("locale=") % locale); ui->setupUi(this); // Browse TAB - ui->backTB->setIcon(KIcon("go-previous")); + ui->backTB->setIcon(QIcon::fromTheme("go-previous")); // create our toolbar QToolBar *toolBar = new QToolBar(this); ui->gridLayout_2->addWidget(toolBar); toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); connect(ui->browseView, SIGNAL(categoryActivated(QModelIndex)), this, SLOT(on_homeView_activated(QModelIndex))); QMenu *findMenu = new QMenu(this); // find is just a generic name in case we don't have any search method m_genericActionK = new KToolBarPopupAction(m_findIcon, i18n("Find"), this); toolBar->addAction(m_genericActionK); // Add actions that the backend supports findMenu->addAction(ui->actionFindName); setCurrentAction(ui->actionFindName); findMenu->addAction(ui->actionFindDescription); if (!m_currentAction) { setCurrentAction(ui->actionFindDescription); } findMenu->addAction(ui->actionFindFile); if (!m_currentAction) { setCurrentAction(ui->actionFindFile); } // If no action was set we can't use this search if (m_currentAction == 0) { m_genericActionK->setEnabled(false); ui->searchKLE->setEnabled(false); } else { // Check to see if we need the KToolBarPopupAction setCurrentActionCancel(false); if (findMenu->actions().size() > 1) { m_currentAction->setVisible(false); m_genericActionK->setMenu(findMenu); } else { m_currentAction->setVisible(true); toolBar->removeAction(m_genericActionK); toolBar->addAction(m_currentAction); } connect(m_genericActionK, SIGNAL(triggered()), this, SLOT(genericActionKTriggered())); } // Create the groups model m_groupsModel = new CategoryModel(this); ui->browseView->setCategoryModel(m_groupsModel); connect(m_groupsModel, SIGNAL(finished()), this, SLOT(setupHomeModel())); ui->homeView->setSpacing(KDialog::spacingHint()); ui->homeView->viewport()->setAttribute(Qt::WA_Hover); KFileItemDelegate *delegate = new KFileItemDelegate(this); delegate->setWrapMode(QTextOption::WordWrap); ui->homeView->setItemDelegate(delegate); // install the backend filters ui->filtersTB->setMenu(m_filtersMenu = new FiltersMenu(this)); connect(m_filtersMenu, SIGNAL(filtersChanged()), this, SLOT(search())); - ui->filtersTB->setIcon(KIcon("view-filter")); + ui->filtersTB->setIcon(QIcon::fromTheme("view-filter")); ApplicationSortFilterModel *proxy = ui->browseView->proxy(); proxy->setApplicationFilter(m_filtersMenu->filterApplications()); connect(m_filtersMenu, SIGNAL(filterApplications(bool)), proxy, SLOT(setApplicationFilter(bool))); //initialize the model, delegate, client and connect it's signals m_browseModel = ui->browseView->model(); // CHANGES TAB ui->changesView->viewport()->setAttribute(Qt::WA_Hover); m_changesModel = new PackageModel(this); KCategorizedSortFilterProxyModel *changedProxy = new KCategorizedSortFilterProxyModel(this); changedProxy->setSourceModel(m_changesModel); changedProxy->setDynamicSortFilter(true); changedProxy->setCategorizedModel(true); changedProxy->setSortCaseSensitivity(Qt::CaseInsensitive); changedProxy->setSortRole(PackageModel::SortRole); changedProxy->sort(0); ui->changesView->setModel(changedProxy); ChangesDelegate *changesDelegate = new ChangesDelegate(ui->changesView); changesDelegate->setExtendPixmapWidth(0); ui->changesView->setItemDelegate(changesDelegate); // Connect this signal to keep track of changes connect(m_browseModel, SIGNAL(changed(bool)), this, SLOT(checkChanged())); // packageUnchecked from changes model connect(m_changesModel, SIGNAL(packageUnchecked(QString)), m_changesModel, SLOT(removePackage(QString))); connect(m_changesModel, SIGNAL(packageUnchecked(QString)), m_browseModel, SLOT(uncheckPackage(QString))); - ui->changesPB->setIcon(KIcon("edit-redo")); + ui->changesPB->setIcon(QIcon::fromTheme("edit-redo")); - KMenu *menu = new KMenu(this); + auto menu = new KMenu(this); ui->settingsTB->setMenu(menu); - ui->settingsTB->setIcon(KIcon("preferences-other")); - QSignalMapper *signalMapper = new QSignalMapper(this); + ui->settingsTB->setIcon(QIcon::fromTheme("preferences-other")); + auto signalMapper = new QSignalMapper(this); QAction *action; - action = menu->addAction(KIcon("view-history"), i18n("History")); + action = menu->addAction(QIcon::fromTheme("view-history"), i18n("History")); signalMapper->setMapping(action, "history"); connect(action, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(setPage(QString))); - action = menu->addAction(KIcon("preferences-other"), i18n("Settings")); + action = menu->addAction(QIcon::fromTheme("preferences-other"), i18n("Settings")); signalMapper->setMapping(action, "settings"); connect(action, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(setPage(QString))); // Only show help menu if not on System Settings if (!args.isEmpty()) { // adds the help menu //! KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::mainComponent().aboutData()); //! menu->addMenu(helpMenu->menu()); } // Make sure the search bar is visible ui->stackedWidgetBar->setCurrentIndex(BAR_SEARCH); } void ApperKCM::setupHomeModel() { KCategorizedSortFilterProxyModel *oldProxy = m_groupsProxyModel; m_groupsProxyModel = new KCategorizedSortFilterProxyModel(this); m_groupsProxyModel->setSourceModel(m_groupsModel); m_groupsProxyModel->setCategorizedModel(true); m_groupsProxyModel->sort(0); ui->homeView->setModel(m_groupsProxyModel); if (oldProxy) { oldProxy->deleteLater(); } } void ApperKCM::genericActionKTriggered() { m_currentAction->trigger(); } void ApperKCM::setCurrentAction(QAction *action) { // just load the new action if it changes this // also ensures that our menu has more than one action if (m_currentAction != action) { // hides the item from the list action->setVisible(false); // ensures the current action was created if (m_currentAction) { // show the item back in the list m_currentAction->setVisible(true); } m_currentAction = action; // copy data from the curront action m_genericActionK->setText(m_currentAction->text()); m_genericActionK->setIcon(m_currentAction->icon()); } } void ApperKCM::setCurrentActionEnabled(bool state) { if (m_currentAction) { m_currentAction->setEnabled(state); } m_genericActionK->setEnabled(state); } void ApperKCM::setCurrentActionCancel(bool cancel) { if (cancel) { // every action should like cancel ui->actionFindName->setText(i18n("&Cancel")); ui->actionFindFile->setText(i18n("&Cancel")); ui->actionFindDescription->setText(i18n("&Cancel")); m_genericActionK->setText(i18n("&Cancel")); // set cancel icons ui->actionFindFile->setIcon(m_cancelIcon); ui->actionFindDescription->setIcon(m_cancelIcon); ui->actionFindName->setIcon(m_cancelIcon); m_genericActionK->setIcon(m_cancelIcon); } else { ui->actionFindName->setText(i18n("Find by &name")); ui->actionFindFile->setText(i18n("Find by f&ile name")); ui->actionFindDescription->setText(i18n("Find by &description")); // Define actions icon - ui->actionFindFile->setIcon(KIcon("document-open")); - ui->actionFindDescription->setIcon(KIcon("document-edit")); + ui->actionFindFile->setIcon(QIcon::fromTheme("document-open")); + ui->actionFindDescription->setIcon(QIcon::fromTheme("document-edit")); ui->actionFindName->setIcon(m_findIcon); m_genericActionK->setIcon(m_findIcon); if (m_currentAction) { m_genericActionK->setText(m_currentAction->text()); } else { // This might happen when the backend can // only search groups m_genericActionK->setText(i18n("Find")); } } } void ApperKCM::checkChanged() { bool hasChanges = false; if (ui->stackedWidget->currentWidget() == ui->pageHome || ui->stackedWidget->currentWidget() == ui->pageChanges || ui->stackedWidget->currentWidget() == ui->pageBrowse) { hasChanges = m_browseModel->hasChanges(); if (!hasChanges && ui->stackedWidget->currentWidget() == ui->pageChanges) { search(); } ui->changesPB->setEnabled(hasChanges); } else if (ui->stackedWidget->currentWidget() == m_updaterPage) { hasChanges = m_updaterPage->hasChanges(); } else if (ui->stackedWidget->currentWidget() == m_settingsPage) { hasChanges = m_settingsPage->hasChanges(); } emit changed(hasChanges); } void ApperKCM::errorCode(PackageKit::Transaction::Error error, const QString &details) { if (error != Transaction::ErrorTransactionCancelled) { KMessageBox::detailedSorry(this, PkStrings::errorMessage(error), details, PkStrings::error(error), KMessageBox::Notify); } } ApperKCM::~ApperKCM() { delete ui; } void ApperKCM::daemonChanged() { Transaction::Roles roles = Daemon::roles(); if (m_roles == roles) { return; } m_roles = roles; // Add actions that the backend supports ui->actionFindName->setEnabled(roles & Transaction::RoleSearchName); ui->actionFindDescription->setEnabled(roles & Transaction::RoleSearchDetails); ui->actionFindFile->setEnabled(roles & Transaction::RoleSearchFile); ui->browseView->init(roles); m_groupsModel->setRoles(roles); m_filtersMenu->setFilters(Daemon::filters()); } void ApperKCM::on_actionFindName_triggered() { setCurrentAction(ui->actionFindName); if (!ui->searchKLE->text().isEmpty()) { // cache the search m_searchRole = Transaction::RoleSearchName; m_searchString = ui->searchKLE->text(); // create the main transaction search(); } } void ApperKCM::on_actionFindDescription_triggered() { setCurrentAction(ui->actionFindDescription); if (!ui->searchKLE->text().isEmpty()) { // cache the search m_searchRole = Transaction::RoleSearchDetails; m_searchString = ui->searchKLE->text(); // create the main transaction search(); } } void ApperKCM::on_actionFindFile_triggered() { setCurrentAction(ui->actionFindFile); if (!ui->searchKLE->text().isEmpty()) { // cache the search m_searchRole = Transaction::RoleSearchFile; m_searchString = ui->searchKLE->text(); // create the main transaction search(); } } void ApperKCM::on_homeView_activated(const QModelIndex &index) { if (index.isValid()) { const QSortFilterProxyModel *proxy; proxy = qobject_cast(index.model()); // If the cast failed it's the index came from browseView if (proxy) { m_searchParentCategory = proxy->mapToSource(index); } else { m_searchParentCategory = index; } // cache the search m_searchRole = static_cast(index.data(CategoryModel::SearchRole).toUInt()); kDebug() << m_searchRole << index.data(CategoryModel::CategoryRole).toString(); if (m_searchRole == Transaction::RoleResolve) { #ifdef HAVE_APPSTREAM CategoryMatcher parser = index.data(CategoryModel::CategoryRole).value(); m_searchCategory = AppStream::instance()->findPkgNames(parser); #endif // HAVE_APPSTREAM } else if (m_searchRole == Transaction::RoleSearchGroup) { if (index.data(CategoryModel::GroupRole).type() == QVariant::String) { QString category = index.data(CategoryModel::GroupRole).toString(); if (category.startsWith('@') || (category.startsWith(QLatin1String("repo:")) && category.size() > 5)) { m_searchGroupCategory = category; } else { m_groupsModel->setRootIndex(m_searchParentCategory); ui->backTB->setEnabled(true); return; } } else { m_searchGroupCategory.clear(); int groupRole = index.data(CategoryModel::GroupRole).toInt(); m_searchGroup = static_cast(groupRole); m_searchString = index.data().toString(); // Store the nice name to change the title } } else if (m_searchRole == Transaction::RoleGetUpdates) { setPage("updates"); return; } // create the main transaction search(); } } bool ApperKCM::canChangePage() { bool changed; // Check if we can change the current page if (ui->stackedWidget->currentWidget() == m_updaterPage) { changed = m_updaterPage->hasChanges(); } else if (ui->stackedWidget->currentWidget() == m_settingsPage) { changed = m_settingsPage->hasChanges(); } else { changed = m_browseModel->hasChanges(); } // if there are no changes don't ask the user if (!changed) { return true; } const int queryUser = KMessageBox::warningYesNoCancel( this, i18n("The settings of the current module have changed.\n" "Do you want to apply the changes or discard them?"), i18n("Apply Settings"), KStandardGuiItem::apply(), KStandardGuiItem::discard(), KStandardGuiItem::cancel()); switch (queryUser) { case KMessageBox::Yes: save(); return true; case KMessageBox::No: load(); return true; case KMessageBox::Cancel: return false; default: return false; } } QString ApperKCM::page() const { return QString(); } void ApperKCM::setPage(const QString &page) { PkTransaction *transaction = qobject_cast(ui->stackedWidget->currentWidget()); if (transaction) { return; } if (page == QLatin1String("settings")) { if (ui->stackedWidget->currentWidget() != m_settingsPage) { if (!canChangePage()) { return; } if (m_settingsPage == 0) { m_settingsPage = new Settings(m_roles, this); connect(m_settingsPage, SIGNAL(changed(bool)), this, SLOT(checkChanged())); connect(m_settingsPage, SIGNAL(refreshCache()), SLOT(refreshCache())); ui->stackedWidget->addWidget(m_settingsPage); connect(ui->generalSettingsPB, SIGNAL(toggled(bool)), m_settingsPage, SLOT(showGeneralSettings())); connect(ui->repoSettingsPB, SIGNAL(toggled(bool)), m_settingsPage, SLOT(showRepoSettings())); } checkChanged(); setButtons(KCModule::Default | KCModule::Apply); emit changed(true); // THIS IS DUMB setButtons only take effect after changed goes true emit changed(false); ui->generalSettingsPB->setChecked(true); ui->stackedWidgetBar->setCurrentIndex(BAR_SETTINGS); ui->stackedWidget->setCurrentWidget(m_settingsPage); m_settingsPage->load(); ui->titleL->clear(); ui->backTB->setEnabled(true); emit caption(i18n("Settings")); } } else if (page == QLatin1String("updates")) { if (ui->stackedWidget->currentWidget() != m_updaterPage) { if (!canChangePage()) { return; } if (m_updaterPage == 0) { m_updaterPage = new Updater(m_roles, this); connect(m_updaterPage, SIGNAL(refreshCache()), this, SLOT(refreshCache())); connect(m_updaterPage, SIGNAL(downloadSize(QString)), ui->downloadL, SLOT(setText(QString))); connect(m_updaterPage, SIGNAL(changed(bool)), this, SLOT(checkChanged())); ui->stackedWidget->addWidget(m_updaterPage); - ui->checkUpdatesPB->setIcon(KIcon("view-refresh")); + ui->checkUpdatesPB->setIcon(QIcon::fromTheme("view-refresh")); connect(ui->checkUpdatesPB, SIGNAL(clicked(bool)), this, SLOT(refreshCache())); } checkChanged(); ui->stackedWidget->setCurrentWidget(m_updaterPage); m_updaterPage->load(); ui->stackedWidgetBar->setCurrentIndex(BAR_UPDATE); ui->backTB->setEnabled(true); emit caption(i18n("Updates")); } } else if (page == QLatin1String("home")) { if (ui->stackedWidget->currentWidget() == m_updaterPage || ui->stackedWidget->currentWidget() == m_settingsPage) { on_backTB_clicked(); } } else if (page == QLatin1String("history")) { m_history = new TransactionHistory(this); ui->searchKLE->clear(); connect(ui->searchKLE, SIGNAL(textChanged(QString)), m_history, SLOT(setFilterRegExp(QString))); ui->stackedWidget->addWidget(m_history); ui->stackedWidget->setCurrentWidget(m_history); ui->backTB->setEnabled(true); ui->filtersTB->setEnabled(false); ui->widget->setEnabled(false); emit caption(i18n("History")); } } void ApperKCM::on_backTB_clicked() { bool canGoBack = false; if (ui->stackedWidget->currentWidget() == ui->pageBrowse) { if (!ui->browseView->goBack()) { return; } else if (m_groupsModel->hasParent()) { canGoBack = true; } } else if (ui->stackedWidget->currentWidget() == m_history) { ui->filtersTB->setEnabled(true); ui->widget->setEnabled(true); m_history->deleteLater(); m_history = 0; } else if (ui->stackedWidget->currentWidget() == ui->pageHome) { if (m_groupsModel->setParentIndex()) { // if we are able to set a new parent item // do not disable back button return; } } else if (ui->stackedWidget->currentWidget() == m_updaterPage) { if (!canChangePage()) { return; } ui->stackedWidgetBar->setCurrentIndex(BAR_SEARCH); checkChanged(); } else if (ui->stackedWidget->currentWidget() == m_settingsPage) { if (!canChangePage()) { return; } setButtons(Apply); emit changed(true); // THIS IS DUMB setButtons only take effect after changed goes true ui->stackedWidgetBar->setCurrentIndex(BAR_SEARCH); checkChanged(); } ui->homeView->selectionModel()->clear(); ui->stackedWidget->setCurrentWidget(ui->pageHome); ui->backTB->setEnabled(canGoBack); // reset the search role m_searchRole = Transaction::RoleUnknown; emit caption(); } void ApperKCM::on_changesPB_clicked() { m_changesModel->clear(); m_changesModel->addSelectedPackagesFromModel(m_browseModel); ui->stackedWidget->setCurrentWidget(ui->pageChanges); ui->backTB->setEnabled(true); emit caption(i18n("Pending Changes")); } void ApperKCM::disconnectTransaction() { if (m_searchTransaction) { // Disconnect everything so that the model don't store // wrong data m_searchTransaction->cancel(); disconnect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), ui->browseView->busyCursor(), SLOT(stop())); disconnect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(finished())); disconnect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_browseModel, SLOT(finished())); disconnect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_browseModel, SLOT(fetchSizes())); disconnect(m_searchTransaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_browseModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); disconnect(m_searchTransaction, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), this, SLOT(errorCode(PackageKit::Transaction::Error,QString))); } } void ApperKCM::search() { ui->browseView->cleanUi(); if (ui->stackedWidgetBar->currentIndex() != BAR_SEARCH) { ui->stackedWidgetBar->setCurrentIndex(BAR_SEARCH); } disconnectTransaction(); // search switch (m_searchRole) { case Transaction::RoleSearchName: m_searchTransaction = Daemon::searchNames(m_searchString, m_filtersMenu->filters()); emit caption(m_searchString); break; case Transaction::RoleSearchDetails: m_searchTransaction = Daemon::searchDetails(m_searchString, m_filtersMenu->filters()); emit caption(m_searchString); break; case Transaction::RoleSearchFile: m_searchTransaction = Daemon::searchFiles(m_searchString, m_filtersMenu->filters()); emit caption(m_searchString); break; case Transaction::RoleSearchGroup: if (m_searchGroupCategory.isEmpty()) { m_searchTransaction = Daemon::searchGroup(m_searchGroup, m_filtersMenu->filters()); // m_searchString has the group nice name emit caption(m_searchString); } else { ui->browseView->setParentCategory(m_searchParentCategory); emit caption(m_searchParentCategory.data().toString()); #ifndef HAVE_APPSTREAM if (m_searchGroupCategory.startsWith('@') || m_searchGroupCategory.startsWith(QLatin1String("repo:"))) { m_searchTransaction = Daemon::searchGroup(m_searchGroupCategory, m_filtersMenu->filters()); } #endif // else the transaction is useless } break; case Transaction::RoleGetPackages: // we want all the installed ones ui->browseView->disableExportInstalledPB(); m_searchTransaction = Daemon::getPackages(Transaction::FilterInstalled | m_filtersMenu->filters()); connect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), ui->browseView, SLOT(enableExportInstalledPB())); emit caption(i18n("Installed Software")); break; case Transaction::RoleResolve: #ifdef HAVE_APPSTREAM if (!m_searchCategory.isEmpty()) { ui->browseView->setParentCategory(m_searchParentCategory); // WARNING the resolve might fail if the backend // has a low limit MaximumItemsToResolve m_searchTransaction = Daemon::resolve(m_searchCategory, m_filtersMenu->filters()); emit caption(m_searchParentCategory.data().toString()); } else { ui->browseView->setParentCategory(m_searchParentCategory); KMessageBox::sorry(this, i18n("Could not find an application that matched this category")); emit caption(); disconnectTransaction(); m_searchTransaction = 0; return; } break; #endif default: kWarning() << "Search type not defined yet"; emit caption(); disconnectTransaction(); m_searchTransaction = 0; return; } connect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), ui->browseView->busyCursor(), SLOT(stop())); connect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(finished())); connect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_browseModel, SLOT(finished())); if (ui->browseView->isShowingSizes()) { connect(m_searchTransaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_browseModel, SLOT(fetchSizes())); } connect(m_searchTransaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_browseModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); connect(m_searchTransaction, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), this, SLOT(errorCode(PackageKit::Transaction::Error,QString))); // cleans the models m_browseModel->clear(); ui->browseView->showInstalledPanel(m_searchRole == Transaction::RoleGetPackages); ui->browseView->busyCursor()->start(); ui->backTB->setEnabled(true); setCurrentActionCancel(true); setCurrentActionEnabled(m_searchTransaction->allowCancel()); ui->stackedWidget->setCurrentWidget(ui->pageBrowse); } void ApperKCM::changed() { Transaction *trans = qobject_cast(sender()); setCurrentActionEnabled(trans->allowCancel()); } void ApperKCM::refreshCache() { emit changed(false); QWidget *currentWidget = ui->stackedWidget->currentWidget(); PkTransactionWidget *transactionW = new PkTransactionWidget(this); connect(transactionW, SIGNAL(titleChangedProgress(QString)), this, SIGNAL(caption(QString))); QPointer transaction = new PkTransaction(transactionW); Daemon::setHints (QLatin1String("cache-age=")+QString::number(m_cacheAge)); transaction->refreshCache(m_forceRefreshCache); transactionW->setTransaction(transaction, Transaction::RoleRefreshCache); ui->stackedWidget->addWidget(transactionW); ui->stackedWidget->setCurrentWidget(transactionW); ui->stackedWidgetBar->setCurrentIndex(BAR_TITLE); ui->backTB->setEnabled(false); connect(transactionW, SIGNAL(titleChanged(QString)), ui->titleL, SLOT(setText(QString))); QEventLoop loop; connect(transaction, SIGNAL(finished(PkTransaction::ExitStatus)), &loop, SLOT(quit())); // wait for the end of transaction if (!transaction->isFinished()) { loop.exec(); if (!transaction) { // Avoid crashing return; } // If the refresh failed force next refresh Cache call m_forceRefreshCache = transaction->exitStatus() == PkTransaction::Failed; } if (m_updaterPage) { m_updaterPage->getUpdates(); } if (currentWidget == m_settingsPage) { setPage("settings"); } else { setPage("updates"); } QTimer::singleShot(0, this, SLOT(checkChanged())); } void ApperKCM::save() { QWidget *currentWidget = ui->stackedWidget->currentWidget(); if (currentWidget == m_settingsPage) { m_settingsPage->save(); } else { PkTransactionWidget *transactionW = new PkTransactionWidget(this); connect(transactionW, SIGNAL(titleChangedProgress(QString)), this, SIGNAL(caption(QString))); QPointer transaction = new PkTransaction(transactionW); ui->stackedWidget->addWidget(transactionW); ui->stackedWidget->setCurrentWidget(transactionW); ui->stackedWidgetBar->setCurrentIndex(BAR_TITLE); ui->backTB->setEnabled(false); connect(transactionW, SIGNAL(titleChanged(QString)), ui->titleL, SLOT(setText(QString))); emit changed(false); QEventLoop loop; connect(transaction, SIGNAL(finished(PkTransaction::ExitStatus)), &loop, SLOT(quit())); if (currentWidget == m_updaterPage) { transaction->updatePackages(m_updaterPage->packagesToUpdate()); transactionW->setTransaction(transaction, Transaction::RoleUpdatePackages); // wait for the end of transaction if (!transaction->isFinished()) { loop.exec(); if (!transaction) { // Avoid crashing return; } } } else { // install then remove packages QStringList installPackages = m_browseModel->selectedPackagesToInstall(); if (!installPackages.isEmpty()) { transaction->installPackages(installPackages); transactionW->setTransaction(transaction, Transaction::RoleInstallPackages); // wait for the end of transaction if (!transaction->isFinished()) { loop.exec(); if (!transaction) { // Avoid crashing return; } } if (transaction->exitStatus() == PkTransaction::Success) { m_browseModel->uncheckAvailablePackages(); } } QStringList removePackages = m_browseModel->selectedPackagesToRemove(); if (!removePackages.isEmpty()) { transaction->removePackages(removePackages); transactionW->setTransaction(transaction, Transaction::RoleRemovePackages); // wait for the end of transaction if (!transaction->isFinished()) { loop.exec(); if (!transaction) { // Avoid crashing return; } } if (transaction->exitStatus() == PkTransaction::Success) { m_browseModel->uncheckInstalledPackages(); } } } transaction->deleteLater(); if (currentWidget == m_updaterPage) { m_updaterPage->getUpdates(); setPage("updates"); } else { // install then remove packages search(); } QTimer::singleShot(0, this, SLOT(checkChanged())); } } void ApperKCM::load() { if (ui->stackedWidget->currentWidget() == m_updaterPage) { m_updaterPage->load(); } else if (ui->stackedWidget->currentWidget() == m_settingsPage) { m_settingsPage->load(); } else { // set focus on the search lineEdit ui->searchKLE->setFocus(Qt::OtherFocusReason); m_browseModel->setAllChecked(false); } } void ApperKCM::defaults() { if (ui->stackedWidget->currentWidget() == m_settingsPage) { m_settingsPage->defaults(); } } void ApperKCM::finished() { // if m_currentAction is false means that our // find button should be disable as there aren't any // search methods setCurrentActionEnabled(m_currentAction); setCurrentActionCancel(false); m_searchTransaction = 0; } void ApperKCM::keyPressEvent(QKeyEvent *event) { if (ui->searchKLE->hasFocus() && ui->stackedWidget->currentWidget() != m_history && (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) { // special tab handling here m_currentAction->trigger(); return; } KCModule::keyPressEvent(event); } void ApperKCM::closeEvent(QCloseEvent *event) { // PkTransaction *transaction = qobject_cast(stackedWidget->currentWidget()); // if (transaction) { event->ignore(); // } else { // event->accept(); // } } #include "ApperKCM.moc" diff --git a/ApperKCM/ApperKCM.h b/ApperKCM/ApperKCM.h index 18e9c70..1c74748 100644 --- a/ApperKCM/ApperKCM.h +++ b/ApperKCM/ApperKCM.h @@ -1,135 +1,134 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef APPER_KCM_U #define APPER_KCM_U #include #include #include #include -#include #include #include #include using namespace PackageKit; namespace Ui { class ApperKCM; } class PackageModel; class FiltersMenu; class TransactionHistory; class CategoryModel; class Settings; class Updater; class ApperKCM : public KCModule { Q_OBJECT Q_PROPERTY(QString page READ page WRITE setPage USER true) public: ApperKCM(QWidget *parent, const QVariantList &args); ~ApperKCM(); QString page() const; Q_SIGNALS: void changed(bool state); void caption(const QString &title = QString()); public Q_SLOTS: void daemonChanged(); void load(); void save(); void defaults(); void setPage(const QString &page); private Q_SLOTS: void search(); void setupHomeModel(); void genericActionKTriggered(); void on_backTB_clicked(); void on_changesPB_clicked(); void on_actionFindName_triggered(); void on_actionFindDescription_triggered(); void on_actionFindFile_triggered(); void on_homeView_activated(const QModelIndex &index); void finished(); void errorCode(PackageKit::Transaction::Error error, const QString &detail); void checkChanged(); void changed(); void refreshCache(); protected: virtual void closeEvent(QCloseEvent *event); private: void disconnectTransaction(); bool canChangePage(); void setCurrentActionEnabled(bool state); void setCurrentAction(QAction *action); void setCurrentActionCancel(bool cancel); void setActionCancel(bool enabled); void keyPressEvent(QKeyEvent *event); Ui::ApperKCM *ui; KToolBarPopupAction *m_genericActionK; QAction *m_currentAction; CategoryModel *m_groupsModel; KCategorizedSortFilterProxyModel *m_groupsProxyModel; PackageModel *m_browseModel; PackageModel *m_changesModel; Settings *m_settingsPage; Updater *m_updaterPage; Transaction *m_searchTransaction; - KIcon m_findIcon; - KIcon m_cancelIcon; + QIcon m_findIcon; + QIcon m_cancelIcon; FiltersMenu *m_filtersMenu; Transaction::Roles m_roles; bool m_forceRefreshCache; uint m_cacheAge; TransactionHistory *m_history; // Old search cache Transaction::Role m_searchRole; QString m_searchString; QString m_searchGroupCategory; PackageKit::Transaction::Group m_searchGroup; QModelIndex m_searchParentCategory; QStringList m_searchCategory; }; #endif diff --git a/ApperKCM/ApperKCM.ui b/ApperKCM/ApperKCM.ui index 20ab2cd..f0505d3 100644 --- a/ApperKCM/ApperKCM.ui +++ b/ApperKCM/ApperKCM.ui @@ -1,380 +1,447 @@ ApperKCM 0 0 411 322 0 0 Add and Remove Software - + + 0 + + 0 - + + 0 + + + 0 + + 0 0 0 0 - + + 0 + + + 0 + + + 0 + + 0 Qt::Vertical - - + + Search packages true 0 0 11 0 - + + 0 + + + 0 + + + 0 + + 0 0 0 Filters QToolButton::InstantPopup Qt::ToolButtonTextBesideIcon true Qt::NoArrow Qt::Vertical false Pending Changes true QToolButton::InstantPopup true - + + 0 + + + 0 + + + 0 + + 0 Qt::Vertical Check for new Updates true Qt::Horizontal 40 20 Average size for download General Settings true true true true Software Origins true false true true Qt::Horizontal 40 20 - + + 0 + + + 0 + + + 0 + + 0 Some Title false Back true - + + 0 + + + 0 + + + 0 + + 0 true QAbstractItemView::NoEditTriggers QAbstractItemView::DragDrop Qt::ElideNone QListView::IconMode true - + + 0 + + + 0 + + + 0 + + 0 - + + 0 + + + 0 + + + 0 + + 0 true QAbstractItemView::NoEditTriggers false true QAbstractItemView::ScrollPerPixel Find by &name Find by &description Find by f&ile name - - KLineEdit - QLineEdit -
klineedit.h
-
CategorizedView QListView
CategorizedView.h
BrowseView QWidget
BrowseView.h
1
diff --git a/ApperKCM/BrowseView.cpp b/ApperKCM/BrowseView.cpp index 8fbedd0..6bd3083 100644 --- a/ApperKCM/BrowseView.cpp +++ b/ApperKCM/BrowseView.cpp @@ -1,338 +1,338 @@ /*************************************************************************** * Copyright (C) 2009-2010 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "BrowseView.h" #include "PackageDetails.h" #include "CategoryModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PackageKit; BrowseView::BrowseView(QWidget *parent) : QWidget(parent) { setupUi(this); connect(categoryView, SIGNAL(clicked(QModelIndex)), this, SIGNAL(categoryActivated(QModelIndex))); m_busySeq = new KPixmapSequenceOverlayPainter(this); m_busySeq->setSequence(KPixmapSequence("process-working", KIconLoader::SizeSmallMedium)); m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_busySeq->setWidget(packageView->viewport()); m_model = new PackageModel(this); m_proxy = new ApplicationSortFilterModel(this); m_proxy->setSourceModel(m_model); packageView->setModel(m_proxy); packageView->sortByColumn(PackageModel::NameCol, Qt::AscendingOrder); packageView->header()->setDefaultAlignment(Qt::AlignCenter); packageView->header()->setStretchLastSection(false); packageView->header()->setResizeMode(PackageModel::NameCol, QHeaderView::Stretch); packageView->header()->setResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents); packageView->header()->setResizeMode(PackageModel::ArchCol, QHeaderView::ResizeToContents); packageView->header()->setResizeMode(PackageModel::OriginCol, QHeaderView::ResizeToContents); packageView->header()->setResizeMode(PackageModel::SizeCol, QHeaderView::ResizeToContents); packageView->header()->setResizeMode(PackageModel::ActionCol, QHeaderView::ResizeToContents); // Hide current Version since it's useless for us packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, true); ApplicationsDelegate *delegate = new ApplicationsDelegate(packageView); packageView->setItemDelegate(delegate); - exportInstalledPB->setIcon(KIcon("document-export")); - importInstalledPB->setIcon(KIcon("document-import")); + exportInstalledPB->setIcon(QIcon::fromTheme("document-export")); + importInstalledPB->setIcon(QIcon::fromTheme("document-import")); KConfig config("apper"); KConfigGroup viewGroup(&config, "BrowseView"); // Version packageView->header()->setSectionHidden(PackageModel::VersionCol, true); m_showPackageVersion = new QAction(i18n("Show Versions"), this); m_showPackageVersion->setCheckable(true); connect(m_showPackageVersion, SIGNAL(toggled(bool)), this, SLOT(showVersions(bool))); m_showPackageVersion->setChecked(viewGroup.readEntry("ShowApplicationVersions", true)); // Arch packageView->header()->setSectionHidden(PackageModel::ArchCol, true); m_showPackageArch = new QAction(i18n("Show Architectures"), this); m_showPackageArch->setCheckable(true); connect(m_showPackageArch, SIGNAL(toggled(bool)), this, SLOT(showArchs(bool))); m_showPackageArch->setChecked(viewGroup.readEntry("ShowApplicationArchitectures", false)); // Origin packageView->header()->setSectionHidden(PackageModel::OriginCol, true); m_showPackageOrigin = new QAction(i18n("Show Origins"), this); m_showPackageOrigin->setCheckable(true); connect(m_showPackageOrigin, SIGNAL(toggled(bool)), this, SLOT(showOrigins(bool))); m_showPackageOrigin->setChecked(viewGroup.readEntry("ShowApplicationOrigins", false)); // Sizes packageView->header()->setSectionHidden(PackageModel::SizeCol, true); m_showPackageSizes = new QAction(i18n("Show Sizes"), this); m_showPackageSizes->setCheckable(true); connect(m_showPackageSizes, SIGNAL(toggled(bool)), this, SLOT(showSizes(bool))); m_showPackageSizes->setChecked(viewGroup.readEntry("ShowPackageSizes", false)); // Ensure the index is visible when the packageDetails appears connect(packageDetails, SIGNAL(ensureVisible(QModelIndex)), this, SLOT(ensureVisible(QModelIndex))); } void BrowseView::init(Transaction::Roles roles) { packageDetails->init(roles); } BrowseView::~BrowseView() { } bool BrowseView::showPageHeader() const { return false; } PackageModel* BrowseView::model() const { return m_model; } void BrowseView::showVersions(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "BrowseView"); viewGroup.writeEntry("ShowApplicationVersions", enabled); packageView->header()->setSectionHidden(PackageModel::VersionCol, !enabled); packageDetails->hidePackageVersion(enabled); } void BrowseView::showArchs(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "BrowseView"); viewGroup.writeEntry("ShowApplicationArchitectures", enabled); packageView->header()->setSectionHidden(PackageModel::ArchCol, !enabled); packageDetails->hidePackageArch(enabled); } void BrowseView::showOrigins(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "BrowseView"); viewGroup.writeEntry("ShowApplicationOrigins", enabled); packageView->header()->setSectionHidden(PackageModel::OriginCol, !enabled); } void BrowseView::showSizes(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "BrowseView"); viewGroup.writeEntry("ShowPackageSizes", enabled); packageView->header()->setSectionHidden(PackageModel::SizeCol, !enabled); packageDetails->hidePackageArch(enabled); if (enabled) { m_model->fetchSizes(); } } void BrowseView::on_packageView_customContextMenuRequested(const QPoint &pos) { - KMenu *menu = new KMenu(this); + auto menu = new KMenu(this); menu->addAction(m_showPackageVersion); menu->addAction(m_showPackageArch); menu->addAction(m_showPackageOrigin); menu->addAction(m_showPackageSizes); menu->exec(packageView->viewport()->mapToGlobal(pos)); menu->deleteLater(); } void BrowseView::on_packageView_clicked(const QModelIndex &index) { if (index.column() == PackageModel::ActionCol) { return; } QModelIndex origIndex = m_proxy->mapToSource(index); packageDetails->setPackage(origIndex); } void BrowseView::ensureVisible(const QModelIndex &index) { QModelIndex proxIndex = m_proxy->mapFromSource(index); packageView->scrollTo(proxIndex); } void BrowseView::showInstalledPanel(bool visible) { installedF->setVisible(visible); } ApplicationSortFilterModel* BrowseView::proxy() const { return m_proxy; } KPixmapSequenceOverlayPainter* BrowseView::busyCursor() const { return m_busySeq; } void BrowseView::setCategoryModel(QAbstractItemModel *model) { categoryView->setModel(model); } void BrowseView::setParentCategory(const QModelIndex &index) { categoryView->setRootIndex(index); // Make sure the last item is not selected categoryView->selectionModel()->clearSelection(); categoryView->horizontalScrollBar()->setValue(0); // Display the category view if the index has child items categoryF->setVisible(categoryView->model()->rowCount(index)); } bool BrowseView::goBack() { packageDetails->hide(); QModelIndex index = categoryView->rootIndex(); if (index.parent().isValid()) { index = index.parent(); // if it's valid we need to know if it wasn't a PK root category if (index.data(CategoryModel::GroupRole).type() == QVariant::String) { QString category = index.data(CategoryModel::GroupRole).toString(); if (!category.startsWith('@')) { return true; } } setParentCategory(index); emit categoryActivated(index); return false; } return true; } void BrowseView::on_categoryMvLeft_clicked() { categoryView->horizontalScrollBar()->setValue(categoryView->horizontalScrollBar()->value() - 1); } void BrowseView::on_categoryMvRight_clicked() { categoryView->horizontalScrollBar()->setValue(categoryView->horizontalScrollBar()->value() + 1); } void BrowseView::cleanUi() { packageDetails->hide(); categoryF->setVisible(false); } bool BrowseView::isShowingSizes() const { return m_showPackageSizes->isChecked(); } void BrowseView::on_exportInstalledPB_clicked() { // We will assume the installed model // is populated since the user is seeing it. QString fileName; fileName = KFileDialog::getSaveFileName(QUrl(), "*.catalog", this, QString(), KFileDialog::ConfirmOverwrite); if (fileName.isEmpty()) { return; } QFile file(fileName); file.open(QIODevice::WriteOnly); QTextStream out(&file); out << "[PackageKit Catalog]\n\n"; out << "InstallPackages(" << Daemon::global()->distroID() << ")="; QStringList packages; for (int i = 0; i < m_model->rowCount(); i++) { packages << m_model->data(m_model->index(i, 0), PackageModel::PackageName).toString(); } out << packages.join(";"); } void BrowseView::on_importInstalledPB_clicked() { QString fileName; fileName = KFileDialog::getOpenFileName(QUrl(), "*.catalog", this); if (fileName.isEmpty()) { return; } // send a DBus message to install this catalog QDBusMessage message; message = QDBusMessage::createMethodCall("org.freedesktop.PackageKit", "/org/freedesktop/PackageKit", "org.freedesktop.PackageKit.Modify", "InstallCatalogs"); message << static_cast(effectiveWinId()); message << (QStringList() << fileName); message << QString(); // This call must block otherwise this application closes before // smarticon is activated QDBusMessage reply = QDBusConnection::sessionBus().call(message, QDBus::Block); } void BrowseView::disableExportInstalledPB() { exportInstalledPB->setEnabled(false); } void BrowseView::enableExportInstalledPB() { exportInstalledPB->setEnabled(true); } #include "BrowseView.moc" diff --git a/ApperKCM/CategoryModel.cpp b/ApperKCM/CategoryModel.cpp index 5ccad39..83981c5 100644 --- a/ApperKCM/CategoryModel.cpp +++ b/ApperKCM/CategoryModel.cpp @@ -1,418 +1,418 @@ /*************************************************************************** * Copyright (C) 2010-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "CategoryModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PackageKit; CategoryModel::CategoryModel(QObject *parent) : QStandardItemModel(parent) { QStandardItem *item; item = new QStandardItem(i18n("Installed Software")); item->setDragEnabled(false); item->setData(Transaction::RoleGetPackages, SearchRole); item->setData(i18n("Lists"), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(0, KCategorizedSortFilterProxyModel::CategorySortRole); item->setIcon(QIcon::fromTheme("dialog-ok-apply")); appendRow(item); item = new QStandardItem(i18n("Updates")); item->setDragEnabled(false); item->setData(Transaction::RoleGetUpdates, SearchRole); item->setData(i18n("Lists"), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(0, KCategorizedSortFilterProxyModel::CategorySortRole); item->setIcon(QIcon::fromTheme("system-software-update")); appendRow(item); #ifdef HAVE_APPSTREAM // Get the groups #ifdef AS_CATEGORIES_PATH fillWithServiceGroups(); #else fillWithStandardGroups(); #endif // AS_CATEGORIES_PATH // category("", // "servers", // "Servers", // "const QString &summary", // "computer"); // category("servers", // "@coomputer", // "Lighttpd", // "const QString &summary", // "emblem-new"); // category("servers", // "@coomputer2", // "Apache", // "const QString &summary", // "dialog-cancel"); #else #endif //HAVE_APPSTREAM QTimer::singleShot(0, this, SIGNAL(finished())); } CategoryModel::~CategoryModel() { } void CategoryModel::setRoles(Transaction::Roles roles) { m_roles = roles; removeRows(2, rowCount() - 2); QDBusPendingReply > transactions = Daemon::getTransactionList(); transactions.waitForFinished(); if (m_roles & Transaction::RoleGetCategories && transactions.value().isEmpty()) { Transaction *trans = Daemon::getCategories(); connect(trans, SIGNAL(category(QString,QString,QString,QString,QString)), this, SLOT(category(QString,QString,QString,QString,QString))); connect(trans, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SIGNAL(finished())); } else { fillWithStandardGroups(); } } QModelIndex CategoryModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { return QStandardItemModel::index(row, column, parent); } return QStandardItemModel::index(row, column, m_rootIndex); } int CategoryModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return QStandardItemModel::rowCount(parent); } return QStandardItemModel::rowCount(m_rootIndex); } void CategoryModel::setRootIndex(const QModelIndex &index) { m_rootIndex = index; reset(); emit finished(); } bool CategoryModel::setParentIndex() { if (m_rootIndex.isValid()) { setRootIndex(m_rootIndex.parent()); // Return the future parent so that Back button can be disabled return m_rootIndex.parent().isValid(); } // if there is no higher level return false return false; } bool CategoryModel::hasParent() const { return m_rootIndex.isValid(); } void CategoryModel::category(const QString &parentId, const QString &categoryId, const QString &name, const QString &summary, const QString &icon) { kDebug() << parentId << categoryId << name << summary << icon; QStandardItem *item = new QStandardItem(name); item->setDragEnabled(false); item->setData(Transaction::RoleSearchGroup, SearchRole); item->setData(categoryId, GroupRole); item->setData(i18n("Categories"), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(2, KCategorizedSortFilterProxyModel::CategorySortRole); item->setToolTip(summary); item->setIcon(QIcon("/usr/share/pixmaps/comps/" + icon + ".png")); if (parentId.isEmpty()) { appendRow(item); } else { QStandardItem *parent = findCategory(parentId); if (parent) { item->setData(parent->text(), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(2, KCategorizedSortFilterProxyModel::CategorySortRole); parent->appendRow(item); } else { appendRow(item); } } // This is a MUST since the spacing needs to be fixed emit finished(); } QStandardItem* CategoryModel::findCategory(const QString &categoryId, const QModelIndex &parent) const { QStandardItem *ret = 0; for (int i = 0; i < rowCount(parent); i++) { QModelIndex group = index(i, 0, parent); if (group.data(SearchRole).toUInt() == Transaction::RoleSearchGroup && group.data(GroupRole).toString() == categoryId) { ret = itemFromIndex(group); } else if (hasChildren(group)) { ret = findCategory(categoryId, group); } if (ret) { break; } } return ret; } void CategoryModel::fillWithStandardGroups() { // Get the groups m_groups = Daemon::global()->groups(); kDebug(); QStandardItem *item; for (int i = 1; i < 64; ++i) { if (m_groups & i) { Transaction::Group group; group = static_cast(i); if (group != Transaction::GroupUnknown) { item = new QStandardItem(PkStrings::groups(group)); item->setDragEnabled(false); item->setData(Transaction::RoleSearchGroup, SearchRole); item->setData(group, GroupRole); item->setData(i18n("Groups"), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(1, KCategorizedSortFilterProxyModel::CategorySortRole); item->setIcon(PkIcons::groupsIcon(group)); if (!(m_roles & Transaction::RoleSearchGroup)) { item->setSelectable(false); } appendRow(item); } } } emit finished(); } void CategoryModel::fillWithServiceGroups() { #ifdef AS_CATEGORIES_PATH - KGlobal::locale()->insertCatalog("gnome-menus"); + KLocale::global()->insertCatalog("gnome-menus"); QFile file(QString(AS_CATEGORIES_PATH) + "/categories.xml"); if (!file.open(QIODevice::ReadOnly)) { kDebug() << "Failed to open file"; fillWithStandardGroups(); return; } QXmlStreamReader xml(&file); while(xml.readNextStartElement() && !xml.hasError()) { // Read next element. if(xml.tokenType() == QXmlStreamReader::StartDocument) { // kDebug() << "StartDocument"; continue; } if(xml.name() == "Menu") { parseMenu(xml, QString()); } } #endif //AS_CATEGORIES_PATH } void CategoryModel::parseMenu(QXmlStreamReader &xml, const QString &parentIcon, QStandardItem *parent) { QString icon = parentIcon; QStandardItem *item = 0; while(!xml.atEnd() && !(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == QLatin1String("Menu"))) { if(xml.tokenType() == QXmlStreamReader::StartElement) { if (xml.name() == QLatin1String("Menu")) { xml.readNext(); parseMenu(xml, icon, item); } else if (xml.name() == QLatin1String("Name")) { QString name = xml.readElementText(); if (!item) { item = new QStandardItem(i18n(name.toUtf8().data())); item->setDragEnabled(false); } else if (item->text().isEmpty()) { item->setText(i18n(name.toUtf8().data())); } } else if (xml.name() == QLatin1String("Icon")) { if (!item) { item = new QStandardItem; item->setDragEnabled(false); } // only sets the icon if it wasn't set, // the .directory might have a better one QString _icon; _icon = xml.readElementText(); if (item->icon().isNull()) { item->setIcon(PkIcons::getIcon(_icon, icon)); icon = _icon; } } else if (xml.name() == QLatin1String("Categories")) { QList categories; categories = parseCategories(xml); if (!categories.isEmpty()) { if (!item) { item = new QStandardItem; item->setDragEnabled(false); } // If we only have one category inside get the first item if (categories.size() == 1) { item->setData(qVariantFromValue(categories.first()), CategoryRole); } else { CategoryMatcher parser(CategoryMatcher::And); parser.setChild(categories); item->setData(qVariantFromValue(parser), CategoryRole); } item->setData(Transaction::RoleResolve, SearchRole); } } else if (xml.name() == QLatin1String("Directory")) { if (!item) { item = new QStandardItem; item->setDragEnabled(false); } QString directory = xml.readElementText(); const KDesktopFile desktopFile(directory); const KConfigGroup config = desktopFile.desktopGroup(); QString _icon = config.readEntry("Icon"); QString _name = config.readEntry("Name"); if (!_icon.isEmpty()) { item->setIcon(PkIcons::getIcon(_icon, icon)); icon = _icon; } if (!_name.isEmpty()) { item->setText(_name); } } else if (xml.name() == QLatin1String("PkGroups")) { if (!item) { item = new QStandardItem; item->setDragEnabled(false); } QString group = xml.readElementText(); Transaction::Group groupEnum; int groupInt = Daemon::enumFromString(group, "Group"); groupEnum = static_cast(groupInt); if (groupEnum != Transaction::GroupUnknown && m_groups & groupEnum) { item->setData(Transaction::RoleSearchGroup, SearchRole); item->setData(groupEnum, GroupRole); } } } // next... xml.readNext(); } if (item && (!item->data(GroupRole).isNull() || !item->data(CategoryRole).isNull())) { if (item->data(CategoryRole).isNull()) { // Set the group name to get it translated Transaction::Group group; group = item->data(GroupRole).value(); item->setText(PkStrings::groups(group)); } item->setData(i18n("Categories"), KCategorizedSortFilterProxyModel::CategoryDisplayRole); item->setData(1, KCategorizedSortFilterProxyModel::CategorySortRole); if (parent) { parent->appendRow(item); } else { appendRow(item); } } } QList CategoryModel::parseCategories(QXmlStreamReader &xml) { QString token = xml.name().toString(); QList ret; while(!xml.atEnd() && !(xml.readNext() == QXmlStreamReader::EndElement && xml.name() == token)) { if(xml.tokenType() == QXmlStreamReader::StartElement) { // Where the categories where AND if (xml.name() == QLatin1String("And")) { // We are going to read the next element to save the token name QList parsers; parsers = parseCategories(xml); if (!parsers.isEmpty()) { CategoryMatcher opAND(CategoryMatcher::And); opAND.setChild(parsers); ret << opAND; } } else if (xml.name() == QLatin1String("Or")) { // Where the categories where OR QList parsers; parsers = parseCategories(xml); if (!parsers.isEmpty()) { CategoryMatcher opOR(CategoryMatcher::Or); opOR.setChild(parsers); ret << opOR; } } else if (xml.name() == QLatin1String("Not")) { // USED to negate the categories inside it QList parsers; parsers = parseCategories(xml); if (!parsers.isEmpty()) { CategoryMatcher opNot(CategoryMatcher::Not); opNot.setChild(parsers); ret << opNot; } } else if (xml.name() == QLatin1String("Category")) { // Found the real category, if the join was not means // that applications in this category should NOT be displayed QString name = xml.readElementText(); if (!name.isEmpty()){ ret << CategoryMatcher(CategoryMatcher::Term, name); } } } } return ret; } diff --git a/ApperKCM/PackageDetails.cpp b/ApperKCM/PackageDetails.cpp index 8a80f13..90da999 100644 --- a/ApperKCM/PackageDetails.cpp +++ b/ApperKCM/PackageDetails.cpp @@ -1,804 +1,801 @@ /*************************************************************************** * Copyright (C) 2009-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PackageDetails.h" #include "ui_PackageDetails.h" #include "ScreenShotViewer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_APPSTREAM #include #endif #include "GraphicsOpacityDropShadowEffect.h" #define BLUR_RADIUS 15 #define FINAL_HEIGHT 210 using namespace PackageKit; Q_DECLARE_METATYPE(KPixmapSequenceOverlayPainter**) PackageDetails::PackageDetails(QWidget *parent) : QWidget(parent), ui(new Ui::PackageDetails), m_busySeq(0), m_display(false), m_hideVersion(false), m_hideArch(false), m_transaction(0), m_hasDetails(false), m_hasFileList(false) { ui->setupUi(this); ui->hideTB->setIcon(QIcon::fromTheme("window-close")); connect(ui->hideTB, SIGNAL(clicked()), this, SLOT(hide())); - KMenu *menu = new KMenu(i18n("Display"), this); + auto menu = new QMenu(i18n("Display"), this); m_actionGroup = new QActionGroup(this); // we check to see which roles are supported by the backend // if so we ask for information and create the containers descriptionAction = menu->addAction(i18n("Description")); descriptionAction->setCheckable(true); descriptionAction->setData(PackageKit::Transaction::RoleGetDetails); m_actionGroup->addAction(descriptionAction); ui->descriptionW->setWidgetResizable(true); dependsOnAction = menu->addAction(i18n("Depends On")); dependsOnAction->setCheckable(true); dependsOnAction->setData(PackageKit::Transaction::RoleDependsOn); m_actionGroup->addAction(dependsOnAction); // Sets a transparent background QWidget *dependsViewport = ui->dependsOnLV->viewport(); QPalette dependsPalette = dependsViewport->palette(); dependsPalette.setColor(dependsViewport->backgroundRole(), Qt::transparent); dependsPalette.setColor(dependsViewport->foregroundRole(), dependsPalette.color(QPalette::WindowText)); dependsViewport->setPalette(dependsPalette); m_dependsModel = new PackageModel(this); m_dependsProxy = new QSortFilterProxyModel(this); m_dependsProxy->setDynamicSortFilter(true); m_dependsProxy->setSortRole(PackageModel::SortRole); m_dependsProxy->setSourceModel(m_dependsModel); ui->dependsOnLV->setModel(m_dependsProxy); ui->dependsOnLV->sortByColumn(0, Qt::AscendingOrder); ui->dependsOnLV->header()->setDefaultAlignment(Qt::AlignCenter); ui->dependsOnLV->header()->setResizeMode(PackageModel::NameCol, QHeaderView::ResizeToContents); ui->dependsOnLV->header()->setResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents); ui->dependsOnLV->header()->setResizeMode(PackageModel::ArchCol, QHeaderView::Stretch); ui->dependsOnLV->header()->hideSection(PackageModel::ActionCol); ui->dependsOnLV->header()->hideSection(PackageModel::CurrentVersionCol); ui->dependsOnLV->header()->hideSection(PackageModel::OriginCol); ui->dependsOnLV->header()->hideSection(PackageModel::SizeCol); requiredByAction = menu->addAction(i18n("Required By")); requiredByAction->setCheckable(true); requiredByAction->setData(PackageKit::Transaction::RoleRequiredBy); m_actionGroup->addAction(requiredByAction); // Sets a transparent background QWidget *requiredViewport = ui->requiredByLV->viewport(); QPalette requiredPalette = requiredViewport->palette(); requiredPalette.setColor(requiredViewport->backgroundRole(), Qt::transparent); requiredPalette.setColor(requiredViewport->foregroundRole(), requiredPalette.color(QPalette::WindowText)); requiredViewport->setPalette(requiredPalette); m_requiresModel = new PackageModel(this); m_requiresProxy = new QSortFilterProxyModel(this); m_requiresProxy->setDynamicSortFilter(true); m_requiresProxy->setSortRole(PackageModel::SortRole); m_requiresProxy->setSourceModel(m_requiresModel); ui->requiredByLV->setModel(m_requiresProxy); ui->requiredByLV->sortByColumn(0, Qt::AscendingOrder); ui->requiredByLV->header()->setDefaultAlignment(Qt::AlignCenter); ui->requiredByLV->header()->setResizeMode(PackageModel::NameCol, QHeaderView::ResizeToContents); ui->requiredByLV->header()->setResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents); ui->requiredByLV->header()->setResizeMode(PackageModel::ArchCol, QHeaderView::Stretch); ui->requiredByLV->header()->hideSection(PackageModel::ActionCol); ui->requiredByLV->header()->hideSection(PackageModel::CurrentVersionCol); ui->requiredByLV->header()->hideSection(PackageModel::OriginCol); ui->requiredByLV->header()->hideSection(PackageModel::SizeCol); fileListAction = menu->addAction(i18n("File List")); fileListAction->setCheckable(true); fileListAction->setData(PackageKit::Transaction::RoleGetFiles); m_actionGroup->addAction(fileListAction); // Sets a transparent background QWidget *actionsViewport = ui->filesPTE->viewport(); QPalette palette = actionsViewport->palette(); palette.setColor(actionsViewport->backgroundRole(), Qt::transparent); palette.setColor(actionsViewport->foregroundRole(), palette.color(QPalette::WindowText)); actionsViewport->setPalette(palette); // Set the menu ui->menuTB->setMenu(menu); ui->menuTB->setIcon(QIcon::fromTheme("help-about")); connect(m_actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(actionActivated(QAction*))); m_busySeq = new KPixmapSequenceOverlayPainter(this); m_busySeq->setSequence(KPixmapSequence("process-working", KIconLoader::SizeSmallMedium)); m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_busySeq->setWidget(ui->stackedWidget); // Setup the opacit effect that makes the descriptio transparent // after finished it checks in display() to see if it shouldn't show // up again. The property animation is always the same, the only different thing // is the Forward or Backward property QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(ui->stackedWidget); effect->setOpacity(0); ui->stackedWidget->setGraphicsEffect(effect); m_fadeStacked = new QPropertyAnimation(effect, "opacity", this); m_fadeStacked->setDuration(500); m_fadeStacked->setStartValue(qreal(0)); m_fadeStacked->setEndValue(qreal(1)); connect(m_fadeStacked, SIGNAL(finished()), this, SLOT(display())); // It's is impossible due to some limitation in Qt to set two effects on the same // Widget m_fadeScreenshot = new QPropertyAnimation(effect, "opacity", this); GraphicsOpacityDropShadowEffect *shadow = new GraphicsOpacityDropShadowEffect(ui->screenshotL); shadow->setOpacity(0); shadow->setBlurRadius(BLUR_RADIUS); shadow->setOffset(2); shadow->setColor(QApplication::palette().dark().color()); ui->screenshotL->setGraphicsEffect(shadow); m_fadeScreenshot = new QPropertyAnimation(shadow, "opacity", this); m_fadeScreenshot->setDuration(500); m_fadeScreenshot->setStartValue(qreal(0)); m_fadeScreenshot->setEndValue(qreal(1)); connect(m_fadeScreenshot, SIGNAL(finished()), this, SLOT(display())); // This pannel expanding QPropertyAnimation *anim1 = new QPropertyAnimation(this, "maximumSize", this); anim1->setDuration(500); anim1->setEasingCurve(QEasingCurve::OutQuart); anim1->setStartValue(QSize(QWIDGETSIZE_MAX, 0)); anim1->setEndValue(QSize(QWIDGETSIZE_MAX, FINAL_HEIGHT)); QPropertyAnimation *anim2 = new QPropertyAnimation(this, "minimumSize", this); anim2->setDuration(500); anim2->setEasingCurve(QEasingCurve::OutQuart); anim2->setStartValue(QSize(QWIDGETSIZE_MAX, 0)); anim2->setEndValue(QSize(QWIDGETSIZE_MAX, FINAL_HEIGHT)); m_expandPanel = new QParallelAnimationGroup(this); m_expandPanel->addAnimation(anim1); m_expandPanel->addAnimation(anim2); connect(m_expandPanel, SIGNAL(finished()), this, SLOT(display())); } void PackageDetails::init(PackageKit::Transaction::Roles roles) { kDebug(); bool setChecked = true; if (roles & PackageKit::Transaction::RoleGetDetails) { descriptionAction->setEnabled(true); descriptionAction->setChecked(setChecked); setChecked = false; } else { descriptionAction->setEnabled(false); descriptionAction->setChecked(false); } if (roles & PackageKit::Transaction::RoleDependsOn) { dependsOnAction->setEnabled(true); dependsOnAction->setChecked(setChecked); setChecked = false; } else { dependsOnAction->setEnabled(false); dependsOnAction->setChecked(false); } if (roles & PackageKit::Transaction::RoleRequiredBy) { requiredByAction->setEnabled(true); requiredByAction->setChecked(setChecked); setChecked = false; } else { requiredByAction->setEnabled(false); requiredByAction->setChecked(false); } if (roles & PackageKit::Transaction::RoleGetFiles) { fileListAction->setEnabled(true); fileListAction->setChecked(setChecked); setChecked = false; } else { fileListAction->setEnabled(false); fileListAction->setChecked(false); } } PackageDetails::~PackageDetails() { } void PackageDetails::setPackage(const QModelIndex &index) { kDebug() << index; QString appId = index.data(PackageModel::ApplicationId).toString(); QString packageID = index.data(PackageModel::IdRole).toString(); // if it's the same package and the same application, return if (packageID == m_packageID && appId == m_appId) { return; } else if (maximumSize().height() == 0) { // Expand the panel m_display = true; m_expandPanel->setDirection(QAbstractAnimation::Forward); m_expandPanel->start(); } else { // Hide the old description fadeOut(PackageDetails::FadeScreenshot | PackageDetails::FadeStacked); } m_index = index; m_appId = appId; m_packageID = packageID; m_hasDetails = false; m_hasFileList = false; m_hasRequires = false; m_hasDepends = false; kDebug() << "appId" << appId << "m_package" << m_packageID; QString pkgIconPath = index.data(PackageModel::IconRole).toString(); m_currentIcon = PkIcons::getIcon(pkgIconPath, QString()).pixmap(64, 64); m_appName = index.data(PackageModel::NameRole).toString(); m_currentScreenshot = thumbnail(Transaction::packageName(m_packageID)); kDebug() << "current screenshot" << m_currentScreenshot; if (!m_currentScreenshot.isNull()) { if (m_screenshotPath.contains(m_currentScreenshot)) { display(); } else { - KTemporaryFile *tempFile = new KTemporaryFile; - tempFile->setPrefix("appget"); - tempFile->setSuffix(".png"); + auto tempFile = new QTemporaryFile; tempFile->open(); KIO::FileCopyJob *job = KIO::file_copy(QUrl(m_currentScreenshot), QUrl(tempFile->fileName()), -1, KIO::Overwrite | KIO::HideProgressInfo); - connect(job, SIGNAL(result(KJob*)), - this, SLOT(resultJob(KJob*))); + connect(job, &KIO::FileCopyJob::result, this, &PackageDetails::resultJob); } } if (m_actionGroup->checkedAction()) { actionActivated(m_actionGroup->checkedAction()); } } void PackageDetails::on_screenshotL_clicked() { QString url; url = screenshot(Transaction::packageName(m_packageID)); if (!url.isNull()) { ScreenShotViewer *view = new ScreenShotViewer(url); view->setWindowTitle(m_appName); view->show(); } } void PackageDetails::hidePackageVersion(bool hide) { m_hideVersion = hide; } void PackageDetails::hidePackageArch(bool hide) { m_hideArch = hide; } void PackageDetails::actionActivated(QAction *action) { // don't fade the screenshot // if the package changed setPackage() fades both fadeOut(FadeStacked); kDebug(); // disconnect the transaction // so that we don't get old data if (m_transaction) { disconnect(m_transaction, SIGNAL(details(PackageKit::Details)), this, SLOT(description(PackageKit::Details))); disconnect(m_transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_dependsModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); disconnect(m_transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_requiresModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); disconnect(m_transaction, SIGNAL(files(QString,QStringList)), this, SLOT(files(QString,QStringList))); disconnect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(finished())); m_transaction = 0; } // Check to see if we don't already have the required data uint role = action->data().toUInt(); switch (role) { case PackageKit::Transaction::RoleGetDetails: if (m_hasDetails) { description(m_details); display(); return; } break; case PackageKit::Transaction::RoleDependsOn: if (m_hasDepends) { display(); return; } break; case PackageKit::Transaction::RoleRequiredBy: if (m_hasRequires) { display(); return; } break; case PackageKit::Transaction::RoleGetFiles: if (m_hasFileList) { display(); return; } break; } // we don't have the data kDebug() << "New transaction"; switch (role) { case PackageKit::Transaction::RoleGetDetails: m_transaction = Daemon::getDetails(m_packageID); connect(m_transaction, SIGNAL(details(PackageKit::Details)), SLOT(description(PackageKit::Details))); break; case PackageKit::Transaction::RoleDependsOn: m_dependsModel->clear(); m_transaction = Daemon::dependsOn(m_packageID, PackageKit::Transaction::FilterNone, false); connect(m_transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_dependsModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_dependsModel, SLOT(finished())); break; case PackageKit::Transaction::RoleRequiredBy: m_requiresModel->clear(); m_transaction = Daemon::requiredBy(m_packageID, PackageKit::Transaction::FilterNone, false); connect(m_transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_requiresModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_requiresModel, SLOT(finished())); break; case PackageKit::Transaction::RoleGetFiles: m_currentFileList.clear(); m_transaction = Daemon::getFiles(m_packageID); connect(m_transaction, SIGNAL(files(QString,QStringList)), this, SLOT(files(QString,QStringList))); break; default: qWarning() << Q_FUNC_INFO << "Oops, unhandled role, please report" << role; return; } connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(finished())); kDebug() <<"transaction running"; m_busySeq->start(); } void PackageDetails::resultJob(KJob *job) { KIO::FileCopyJob *fJob = qobject_cast(job); if (!fJob->error()) { m_screenshotPath[fJob->srcUrl().url()] = fJob->destUrl().toLocalFile(); display(); } } void PackageDetails::hide() { m_display = false; // Clean the old description otherwise if the user selects the same // package the pannel won't expand m_packageID.clear(); m_appId.clear(); if (maximumSize().height() == FINAL_HEIGHT) { if (m_fadeStacked->currentValue().toReal() == 0 && m_fadeScreenshot->currentValue().toReal() == 0) { // Screen shot and description faded let's shrink the pannel m_expandPanel->setDirection(QAbstractAnimation::Backward); m_expandPanel->start(); } else { // Hide current description fadeOut(PackageDetails::FadeScreenshot | PackageDetails::FadeStacked); } } } void PackageDetails::fadeOut(FadeWidgets widgets) { // Fade out only if needed if ((widgets & FadeStacked) && m_fadeStacked->currentValue().toReal() != 0) { m_fadeStacked->setDirection(QAbstractAnimation::Backward); m_fadeStacked->start(); } // Fade out the screenshot only if needed if ((widgets & FadeScreenshot) && m_fadeScreenshot->currentValue().toReal() != 0) { ui->screenshotL->unsetCursor(); m_fadeScreenshot->setDirection(QAbstractAnimation::Backward); m_fadeScreenshot->start(); } } void PackageDetails::display() { // If we shouldn't be showing hide the pannel if (!m_display) { hide(); } else if (maximumSize().height() == FINAL_HEIGHT) { emit ensureVisible(m_index); // Check to see if the stacked widget is transparent if (m_fadeStacked->currentValue().toReal() == 0 && m_actionGroup->checkedAction()) { bool fadeIn = false; switch (m_actionGroup->checkedAction()->data().toUInt()) { case PackageKit::Transaction::RoleGetDetails: if (m_hasDetails) { setupDescription(); fadeIn = true; } break; case PackageKit::Transaction::RoleDependsOn: if (m_hasDepends) { if (ui->stackedWidget->currentWidget() != ui->pageDepends) { ui->stackedWidget->setCurrentWidget(ui->pageDepends); } fadeIn = true; } break; case PackageKit::Transaction::RoleRequiredBy: if (m_hasRequires) { if (ui->stackedWidget->currentWidget() != ui->pageRequired) { ui->stackedWidget->setCurrentWidget(ui->pageRequired); } fadeIn = true; } break; case PackageKit::Transaction::RoleGetFiles: if (m_hasFileList) { ui->filesPTE->clear(); if (m_currentFileList.isEmpty()) { ui->filesPTE->insertPlainText(i18n("No files were found.")); } else { m_currentFileList.sort(); ui->filesPTE->insertPlainText(m_currentFileList.join("\n")); } if (ui->stackedWidget->currentWidget() != ui->pageFiles) { ui->stackedWidget->setCurrentWidget(ui->pageFiles); } ui->filesPTE->verticalScrollBar()->setValue(0); fadeIn = true; } break; } if (fadeIn) { // Fade In m_fadeStacked->setDirection(QAbstractAnimation::Forward); m_fadeStacked->start(); } } // Check to see if we have a screen shot and if we are // transparent, and make sure the details are going // to be shown if (m_fadeScreenshot->currentValue().toReal() == 0 && m_screenshotPath.contains(m_currentScreenshot) && m_fadeStacked->direction() == QAbstractAnimation::Forward) { QPixmap pixmap; pixmap = QPixmap(m_screenshotPath[m_currentScreenshot]) .scaled(160,120, Qt::KeepAspectRatio, Qt::SmoothTransformation); ui->screenshotL->setPixmap(pixmap); ui->screenshotL->setCursor(Qt::PointingHandCursor); // Fade In m_fadeScreenshot->setDirection(QAbstractAnimation::Forward); m_fadeScreenshot->start(); } } } void PackageDetails::setupDescription() { if (ui->stackedWidget->currentWidget() != ui->pageDescription) { ui->stackedWidget->setCurrentWidget(ui->pageDescription); } if (!m_hasDetails) { // Oops we don't have any details ui->descriptionL->setText(i18n("Could not fetch software details")); ui->descriptionL->show(); // Hide stuff so we don't display outdated data ui->homepageL->hide(); ui->pathL->hide(); ui->licenseL->hide(); ui->sizeL->hide(); ui->iconL->clear(); } if (!m_detailsDescription.isEmpty()) { ui->descriptionL->setText(m_detailsDescription.replace('\n', "
")); ui->descriptionL->show(); } else { ui->descriptionL->clear(); } if (!m_details.url().isEmpty()) { ui->homepageL->setText("" + m_details.url() + ""); ui->homepageL->show(); } else { ui->homepageL->hide(); } // Let's try to find the application's path in human user // readable easiest form :D KService::Ptr service = KService::serviceByDesktopName(m_appId); QVector > ret; if (service) { ret = locateApplication(QString(), service->menuId()); } if (ret.isEmpty()) { ui->pathL->hide(); } else { QString path; path.append(QString("") .arg(KIconLoader::global()->iconPath("kde", KIconLoader::Small))); path.append(QString(" %1  %3") .arg(QString::fromUtf8("âžœ")) .arg(KIconLoader::global()->iconPath("applications-other", KIconLoader::Small)) .arg(i18n("Applications"))); for (int i = 0; i < ret.size(); i++) { path.append(QString(" %1  %3") .arg(QString::fromUtf8("âžœ")) .arg(KIconLoader::global()->iconPath(ret.at(i).second, KIconLoader::Small)) .arg(ret.at(i).first)); } ui->pathL->setText(path); ui->pathL->show(); } // if (details->group() != Package::UnknownGroup) { // // description += "" + i18nc("Group of the package", "Group") + ":" // // + PkStrings::groups(details->group()) // // + ""; // } if (!m_details.license().isEmpty() && m_details.license() != "unknown") { // We have a license, check if we have and should show show package version if (!m_hideVersion && !Transaction::packageVersion(m_details.packageId()).isEmpty()) { ui->licenseL->setText(Transaction::packageVersion(m_details.packageId()) + " - " + m_details.license()); } else { ui->licenseL->setText(m_details.license()); } ui->licenseL->show(); } else if (!m_hideVersion) { ui->licenseL->setText(Transaction::packageVersion(m_details.packageId())); ui->licenseL->show(); } else { ui->licenseL->hide(); } if (m_details.size() > 0) { - QString size = KGlobal::locale()->formatByteSize(m_details.size()); + QString size = KLocale::global()->formatByteSize(m_details.size()); if (!m_hideArch && !Transaction::packageArch(m_details.packageId()).isEmpty()) { ui->sizeL->setText(size % QLatin1String(" (") % Transaction::packageArch(m_details.packageId()) % QLatin1Char(')')); } else { ui->sizeL->setText(size); } ui->sizeL->show(); } else if (!m_hideArch && !Transaction::packageArch(m_details.packageId()).isEmpty()) { ui->sizeL->setText(Transaction::packageArch(m_details.packageId())); } else { ui->sizeL->hide(); } if (m_currentIcon.isNull()) { ui->iconL->clear(); } else { ui->iconL->setPixmap(m_currentIcon); } } QVector > PackageDetails::locateApplication(const QString &_relPath, const QString &menuId) const { QVector > ret; KServiceGroup::Ptr root = KServiceGroup::group(_relPath); if (!root || !root->isValid()) { return ret; } KServiceGroup::List list = root->entries(false /* sorted */, true /* exclude no display entries */, false /* allow separators */); //! TODO: Port to KF5 properly Q_UNUSED(menuId) #if 0 for (KServiceGroup::List::ConstIterator it = list.begin(); it != list.end(); it++) { KSycocaEntry::Ptr = (*it); if (p->isType(KST_KService)) { KService *service = static_cast(p.get()); if (service->noDisplay()) { continue; } // kDebug() << menuId << service->menuId(); if (service->menuId() == menuId) { QPair pair; pair.first = service->name(); pair.second = service->icon(); ret << pair; // kDebug() << "FOUND!"; return ret; } } else if (p->isType(KST_KServiceGroup)) { KServiceGroup *serviceGroup = static_cast(p.get()); if (serviceGroup->noDisplay() || serviceGroup->childCount() == 0) { continue; } QVector > found; found = locateApplication(serviceGroup->relPath(), menuId); if (!found.isEmpty()) { QPair pair; pair.first = serviceGroup->caption(); pair.second = serviceGroup->icon(); ret << pair; ret << found; return ret; } } else { kWarning(250) << "KServiceGroup: Unexpected object in list!"; continue; } } #endif return ret; } QString PackageDetails::thumbnail(const QString &pkgName) const { #ifndef HAVE_APPSTREAM Q_UNUSED(pkgName) return QString(); #else return AppStream::instance()->thumbnail(pkgName); #endif } QString PackageDetails::screenshot(const QString &pkgName) const { #ifndef HAVE_APPSTREAM Q_UNUSED(pkgName) return QString(); #else return AppStream::instance()->screenshot(pkgName); #endif } void PackageDetails::description(const PackageKit::Details &details) { kDebug() << details; m_details = details; m_detailsDescription = details.description(); m_hasDetails = true; #ifdef HAVE_APPSTREAM // check if we have application details from Appstream data // FIXME: The whole AppStream handling sucks badly, since it was added later // and on to of the package-based model. So we can't respect the "multiple apps // in one package" case here. QList apps; apps = AppStream::instance()->applications(Transaction::packageName(m_packageID)); foreach (const AppStream::Application &app, apps) { if (!app.description.isEmpty()) { m_detailsDescription = app.description; break; } } #endif } void PackageDetails::finished() { if (m_busySeq) { m_busySeq->stop(); } m_transaction = 0; PackageKit::Transaction *transaction; transaction = qobject_cast(sender()); kDebug(); if (transaction) { kDebug() << transaction->role() << PackageKit::Transaction::RoleGetDetails; if (transaction->role() == PackageKit::Transaction::RoleGetDetails) { m_hasDetails = true; } else if (transaction->role() == PackageKit::Transaction::RoleGetFiles) { m_hasFileList = true; } else if (transaction->role() == PackageKit::Transaction::RoleRequiredBy) { m_hasRequires = true; } else if (transaction->role() == PackageKit::Transaction::RoleDependsOn) { m_hasDepends = true; } else { return; } display(); } } void PackageDetails::files(const QString &packageID, const QStringList &files) { Q_UNUSED(packageID) m_currentFileList = files; } #include "PackageDetails.moc" diff --git a/ApperKCM/Settings/Settings.cpp b/ApperKCM/Settings/Settings.cpp index 1a4f807..8a02571 100644 --- a/ApperKCM/Settings/Settings.cpp +++ b/ApperKCM/Settings/Settings.cpp @@ -1,341 +1,341 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Settings.h" #include "ui_Settings.h" #include "OriginModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PackageKit; Settings::Settings(Transaction::Roles roles, QWidget *parent) : QWidget(parent), ui(new Ui::Settings), m_roles(roles) { ui->setupUi(this); QAction *action = new QAction(i18n("Refresh Cache"), this); connect(action, SIGNAL(triggered()), SIGNAL(refreshCache())); connect(action, SIGNAL(triggered()), ui->messageWidget, SLOT(animatedHide())); ui->messageWidget->addAction(action); ui->messageWidget->setText(i18n("A repository was changed, it's highly recommended to refresh the cache")); ui->messageWidget->hide(); if (!(m_roles & Transaction::RoleRefreshCache)) { ui->intervalL->setEnabled(false); ui->intervalCB->setEnabled(false); } if (!(m_roles & Transaction::RoleGetDistroUpgrades)) { ui->distroIntervalCB->setEnabled(false); } m_originModel = new OriginModel(this); connect(m_originModel, SIGNAL(refreshRepoList()), SLOT(refreshRepoModel())); connect(m_originModel, SIGNAL(refreshRepoList()), ui->messageWidget, SLOT(animatedShow())); QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); proxy->setDynamicSortFilter(true); proxy->setSourceModel(m_originModel); ui->originTV->setModel(proxy); ui->originTV->header()->setDefaultAlignment(Qt::AlignCenter); // This is needed to keep the oring right ui->originTV->header()->setSortIndicator(0, Qt::AscendingOrder); proxy->sort(0); if (!(m_roles & Transaction::RoleGetRepoList)) { // Disables the group box ui->originTV->setEnabled(false); ui->showOriginsCB->setEnabled(false); } ui->distroIntervalCB->addItem(i18nc("Inform about distribution upgrades", "Never"), Enum::DistroNever); ui->distroIntervalCB->addItem(i18nc("Inform about distribution upgrades", "Only stable"), Enum::DistroStable); // Ignore unstable distros upgrades for now #ifndef false ui->distroIntervalCB->addItem(i18nc("Inform about distribution upgrades", "Stable and development"), Enum::DistroDevelopment); #endif ui->intervalCB->addItem(i18nc("Hourly refresh the package cache", "Hourly"), Enum::Hourly); ui->intervalCB->addItem(i18nc("Daily refresh the package cache", "Daily"), Enum::Daily); ui->intervalCB->addItem(i18nc("Weekly refresh the package cache", "Weekly"), Enum::Weekly); ui->intervalCB->addItem(i18nc("Monthly refresh the package cache", "Monthly"), Enum::Monthly); ui->intervalCB->addItem(i18nc("Never refresh package cache", "Never"), Enum::Never); ui->autoCB->addItem(i18nc("No updates will be automatically installed", "None"), Enum::None); ui->autoCB->addItem(i18n("Download only"), Enum::DownloadOnly); ui->autoCB->addItem(i18n("Security only"), Enum::Security); ui->autoCB->addItem(i18n("All updates"), Enum::All); connect(ui->autoConfirmCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); connect(ui->appLauncherCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); connect(ui->distroIntervalCB, SIGNAL(currentIndexChanged(int)), this, SLOT(checkChanges())); connect(ui->intervalCB, SIGNAL(currentIndexChanged(int)), this, SLOT(checkChanges())); connect(ui->checkUpdatesBatteryCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); connect(ui->checkUpdatesMobileCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); connect(ui->autoCB, SIGNAL(currentIndexChanged(int)), this, SLOT(checkChanges())); connect(ui->installUpdatesBatteryCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); connect(ui->installUpdatesMobileCB, SIGNAL(stateChanged(int)), this, SLOT(checkChanges())); // Setup the busy cursor m_busySeq = new KPixmapSequenceOverlayPainter(this); m_busySeq->setSequence(KPixmapSequence("process-working", KIconLoader::SizeSmallMedium)); m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_busySeq->setWidget(ui->originTV->viewport()); #ifndef EDIT_ORIGNS_DESKTOP_NAME ui->editOriginsPB->hide(); #endif //EDIT_ORIGNS_DESKTOP_NAME } Settings::~Settings() { delete ui; } void Settings::on_editOriginsPB_clicked() { #ifdef EDIT_ORIGNS_DESKTOP_NAME KToolInvocation::startServiceByDesktopName(EDIT_ORIGNS_DESKTOP_NAME); #endif //EDIT_ORIGNS_DESKTOP_NAME } void Settings::refreshRepoModel() { on_showOriginsCB_stateChanged(ui->showOriginsCB->checkState()); } // TODO update the repo list connecting to repo changed signal void Settings::on_showOriginsCB_stateChanged(int state) { Transaction *transaction; transaction = Daemon::getRepoList(state == Qt::Checked ? Transaction::FilterNone : Transaction::FilterNotDevel); connect(transaction, SIGNAL(repoDetail(QString,QString,bool)), m_originModel, SLOT(addOriginItem(QString,QString,bool))); connect(transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_originModel, SLOT(finished())); connect(transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_busySeq, SLOT(stop())); connect(transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(checkChanges())); m_busySeq->start(); KConfig config("apper"); KConfigGroup originsDialog(&config, "originsDialog"); bool showDevel = originsDialog.readEntry("showDevel", false); if (showDevel != ui->showOriginsCB->isChecked()) { originsDialog.writeEntry("showDevel", ui->showOriginsCB->isChecked()); } } bool Settings::hasChanges() const { KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); KConfigGroup transaction(&config, "Transaction"); KConfigGroup checkUpdateGroup(&config, "CheckUpdate"); if (ui->distroIntervalCB->itemData(ui->distroIntervalCB->currentIndex()).toUInt() != static_cast(checkUpdateGroup.readEntry(CFG_DISTRO_UPGRADE, Enum::DistroUpgradeDefault)) || ui->intervalCB->itemData(ui->intervalCB->currentIndex()).toUInt() != static_cast(checkUpdateGroup.readEntry(CFG_INTERVAL, Enum::TimeIntervalDefault)) || ui->checkUpdatesBatteryCB->isChecked() != checkUpdateGroup.readEntry(CFG_CHECK_UP_BATTERY, DEFAULT_CHECK_UP_BATTERY) || ui->checkUpdatesMobileCB->isChecked() != checkUpdateGroup.readEntry(CFG_CHECK_UP_MOBILE, DEFAULT_CHECK_UP_MOBILE) || ui->autoCB->itemData(ui->autoCB->currentIndex()).toUInt() != static_cast(checkUpdateGroup.readEntry(CFG_AUTO_UP, Enum::AutoUpdateDefault)) || ui->installUpdatesBatteryCB->isChecked() != checkUpdateGroup.readEntry(CFG_INSTALL_UP_BATTERY, DEFAULT_INSTALL_UP_BATTERY) || ui->installUpdatesMobileCB->isChecked() != checkUpdateGroup.readEntry(CFG_INSTALL_UP_MOBILE, DEFAULT_INSTALL_UP_MOBILE) || ui->autoConfirmCB->isChecked() != !requirementsDialog.readEntry("autoConfirm", false) || ui->appLauncherCB->isChecked() != transaction.readEntry("ShowApplicationLauncher", true)) { return true; } return false; } void Settings::checkChanges() { emit changed(hasChanges()); // Check if interval update is never bool enabled = ui->intervalCB->itemData(ui->intervalCB->currentIndex()).toUInt() != Enum::Never; ui->checkUpdatesBatteryCB->setEnabled(enabled); ui->checkUpdatesMobileCB->setEnabled(enabled); ui->autoInsL->setEnabled(enabled); ui->autoCB->setEnabled(enabled); if (enabled) { enabled = ui->autoCB->itemData(ui->autoCB->currentIndex()).toUInt() != Enum::None; } ui->installUpdatesMobileCB->setEnabled(enabled); ui->installUpdatesBatteryCB->setEnabled(enabled); } void Settings::load() { KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); ui->autoConfirmCB->setChecked(!requirementsDialog.readEntry("autoConfirm", false)); KConfigGroup transaction(&config, "Transaction"); ui->appLauncherCB->setChecked(transaction.readEntry("ShowApplicationLauncher", true)); KConfigGroup checkUpdateGroup(&config, "CheckUpdate"); uint distroUpgrade = checkUpdateGroup.readEntry(CFG_DISTRO_UPGRADE, Enum::DistroUpgradeDefault); int ret = ui->distroIntervalCB->findData(distroUpgrade); if (ret == -1) { ui->distroIntervalCB->setCurrentIndex(ui->distroIntervalCB->findData(Enum::DistroUpgradeDefault)); } else { ui->distroIntervalCB->setCurrentIndex(ret); } uint interval = checkUpdateGroup.readEntry(CFG_INTERVAL, Enum::TimeIntervalDefault); ret = ui->intervalCB->findData(interval); if (ret == -1) { // this is if someone change the file by hand... - ui->intervalCB->addItem(KGlobal::locale()->prettyFormatDuration(interval * 1000), interval); + ui->intervalCB->addItem(KLocale::global()->prettyFormatDuration(interval * 1000), interval); ui->intervalCB->setCurrentIndex(ui->intervalCB->count() - 1); } else { ui->intervalCB->setCurrentIndex(ret); } ui->checkUpdatesBatteryCB->setChecked(checkUpdateGroup.readEntry(CFG_CHECK_UP_BATTERY, DEFAULT_CHECK_UP_BATTERY)); ui->checkUpdatesMobileCB->setChecked(checkUpdateGroup.readEntry(CFG_CHECK_UP_MOBILE, DEFAULT_CHECK_UP_MOBILE)); uint autoUpdate = checkUpdateGroup.readEntry(CFG_AUTO_UP, Enum::AutoUpdateDefault); ret = ui->autoCB->findData(autoUpdate); if (ret == -1) { // this is if someone change the file by hand... ui->autoCB->setCurrentIndex(ui->autoCB->findData(Enum::AutoUpdateDefault)); } else { ui->autoCB->setCurrentIndex(ret); } ui->installUpdatesBatteryCB->setChecked(checkUpdateGroup.readEntry(CFG_INSTALL_UP_BATTERY, DEFAULT_INSTALL_UP_BATTERY)); ui->installUpdatesMobileCB->setChecked(checkUpdateGroup.readEntry(CFG_INSTALL_UP_MOBILE, DEFAULT_INSTALL_UP_MOBILE)); // Load origns list if (m_roles & Transaction::RoleGetRepoList) { KConfigGroup originsDialog(&config, "originsDialog"); bool showDevel = originsDialog.readEntry("showDevel", false); ui->showOriginsCB->setChecked(showDevel); refreshRepoModel(); ui->originTV->setEnabled(true); } else { ui->originTV->setEnabled(false); } // hide battery options if we are on a desktop computer const QList listBattery = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString()); bool notFound = true; foreach (const Solid::Device &device, listBattery) { const Solid::Battery *battery = device.as(); if (battery && battery->type() == Solid::Battery::PrimaryBattery) { notFound = false; break; } } if (notFound) { ui->checkUpdatesBatteryCB->hide(); ui->installUpdatesBatteryCB->hide(); } } void Settings::save() { KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); requirementsDialog.writeEntry("autoConfirm", !ui->autoConfirmCB->isChecked()); KConfigGroup transaction(&config, "Transaction"); transaction.writeEntry("ShowApplicationLauncher", ui->appLauncherCB->isChecked()); KConfigGroup checkUpdateGroup(&config, "CheckUpdate"); checkUpdateGroup.writeEntry("distroUpgrade", ui->distroIntervalCB->itemData(ui->distroIntervalCB->currentIndex()).toUInt()); checkUpdateGroup.writeEntry("interval", ui->intervalCB->itemData(ui->intervalCB->currentIndex()).toUInt()); checkUpdateGroup.writeEntry("checkUpdatesOnBattery", ui->checkUpdatesBatteryCB->isChecked()); checkUpdateGroup.writeEntry("checkUpdatesOnMobile", ui->checkUpdatesMobileCB->isChecked()); checkUpdateGroup.writeEntry("autoUpdate", ui->autoCB->itemData(ui->autoCB->currentIndex()).toUInt()); checkUpdateGroup.writeEntry("installUpdatesOnBattery", ui->installUpdatesBatteryCB->isChecked()); checkUpdateGroup.writeEntry("installUpdatesOnMobile", ui->installUpdatesMobileCB->isChecked()); } void Settings::defaults() { ui->autoConfirmCB->setChecked(true); ui->appLauncherCB->setChecked(true); ui->distroIntervalCB->setCurrentIndex(ui->distroIntervalCB->findData(Enum::DistroUpgradeDefault)); ui->intervalCB->setCurrentIndex(ui->intervalCB->findData(Enum::TimeIntervalDefault)); ui->autoCB->setCurrentIndex(ui->autoCB->findData(Enum::AutoUpdateDefault) ); checkChanges(); } void Settings::showGeneralSettings() { ui->stackedWidget->setCurrentIndex(0); } void Settings::showRepoSettings() { ui->stackedWidget->setCurrentIndex(1); } #include "Settings.moc" diff --git a/ApperKCM/TransactionHistory.cpp b/ApperKCM/TransactionHistory.cpp index be2c234..a44d103 100644 --- a/ApperKCM/TransactionHistory.cpp +++ b/ApperKCM/TransactionHistory.cpp @@ -1,89 +1,89 @@ /*************************************************************************** * Copyright (C) 2009-2010 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "TransactionHistory.h" #include "TransactionFilterModel.h" #include "TransactionModel.h" #include #include #include #include #include #include #include #include TransactionHistory::TransactionHistory(QWidget *parent) : QWidget(parent) { setupUi(this); m_transactionModel = new TransactionModel(this); m_proxyModel = new TransactionFilterModel(this); m_proxyModel->setSourceModel(m_transactionModel); m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_proxyModel->setFilterKeyColumn(-1); treeView->setModel(m_proxyModel); treeView->header()->setResizeMode(QHeaderView::ResizeToContents); // Get the data refreshList(); } TransactionHistory::~TransactionHistory() { } void TransactionHistory::setFilterRegExp(const QString ®exp) { m_proxyModel->setFilterRegExp(regexp); } void TransactionHistory::on_treeView_customContextMenuRequested(const QPoint &pos) { KMenu *menu = new KMenu(this); QAction *action; action = menu->addAction(i18n("Refresh transactions list")); connect(action, SIGNAL(triggered(bool)), this, SLOT(refreshList())); menu->exec(treeView->viewport()->mapToGlobal(pos)); delete menu; } void TransactionHistory::refreshList() { // Refresh transaction list m_transactionModel->clear(); Transaction *transaction = Daemon::getOldTransactions(0); connect(transaction, SIGNAL(transaction(PackageKit::Transaction*)), m_transactionModel, SLOT(addTransaction(PackageKit::Transaction*))); // Refresh time QString text; uint time = Daemon::global()->getTimeSinceAction(Transaction::RoleRefreshCache) * 1000; - text = i18n("Time since last cache refresh: %1", KGlobal::locale()->prettyFormatDuration(time)); + text = i18n("Time since last cache refresh: %1", KLocale::global()->prettyFormatDuration(time)); timeCacheLabel->setText(text); } #include "TransactionHistory.moc" diff --git a/ApperKCM/TransactionModel.cpp b/ApperKCM/TransactionModel.cpp index 456df71..6e95a47 100644 --- a/ApperKCM/TransactionModel.cpp +++ b/ApperKCM/TransactionModel.cpp @@ -1,151 +1,151 @@ /*************************************************************************** * Copyright (C) 2009-2010 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "TransactionModel.h" #include #include #include #include #include #include using namespace PackageKit; TransactionModel::TransactionModel(QObject *parent) : QStandardItemModel(parent) { setSortRole(Qt::DisplayRole); clear(); } void TransactionModel::clear() { QStandardItemModel::clear(); setHorizontalHeaderItem(0, new QStandardItem(i18n("Date"))); setHorizontalHeaderItem(1, new QStandardItem(i18n("Action"))); setHorizontalHeaderItem(2, new QStandardItem(i18n("Details"))); setHorizontalHeaderItem(3, new QStandardItem(i18nc("Machine user who issued the transaction", "Username"))); setHorizontalHeaderItem(4, new QStandardItem(i18n("Application"))); } void TransactionModel::addTransaction(PackageKit::Transaction *trans) { QStandardItem *dateI = new QStandardItem; QStandardItem *roleI = new QStandardItem; QStandardItem *detailsI = new QStandardItem; QStandardItem *userI = new QStandardItem; QStandardItem *appI = new QStandardItem; - dateI->setText(KGlobal::locale()->formatDate(trans->timespec().date())); + dateI->setText(KLocale::global()->formatDate(trans->timespec().date())); // this is for the filterSort model dateI->setData(trans->timespec(), Qt::UserRole); dateI->setEditable(false); roleI->setText(PkStrings::actionPast(trans->role())); roleI->setIcon(PkIcons::actionIcon(trans->role())); roleI->setEditable(false); detailsI->setText(getDetailsLocalized(trans->data())); detailsI->setEditable(false); KUser user(trans->uid()); QString display; if (!user.property(KUser::FullName).toString().isEmpty()) { display = user.property(KUser::FullName).toString() + " (" + user.loginName() + ')'; } else { display = user.loginName(); } userI->setText(display); userI->setEditable(false); appI->setText(trans->cmdline()); appI->setEditable(false); QList line; line << dateI << roleI << detailsI << userI << appI; appendRow(line); delete trans; } QString TransactionModel::getDetailsLocalized(const QString &data) const { QStringList lines = data.split('\n'); QStringList ret; QString text; text = getTypeLine(lines, Transaction::StatusInstall); if (!text.isNull()) { ret << text; } text = getTypeLine(lines, Transaction::StatusRemove); if (!text.isNull()) { ret << text; } text = getTypeLine(lines, Transaction::StatusUpdate); if (!text.isNull()) { ret << text; } return ret.join("\n"); } QString TransactionModel::getTypeLine(const QStringList &lines, Transaction::Status status) const { QStringList text; foreach(const QString &line, lines) { QStringList sections = line.split('\t'); if (sections.size() > 1) { switch (status) { case Transaction::StatusInstall: if (sections.at(0) != "installing") { continue; } break; case Transaction::StatusRemove: if (sections.at(0) != "removing") { continue; } break; case Transaction::StatusUpdate: if (sections.at(0) != "updating") { continue; } break; default: continue; } QStringList packageData = sections.at(1).split(';'); if (packageData.size()) { text << packageData.at(0); } } } if (text.size()) { // TODO make the status BOLD return PkStrings::statusPast(status) + ": " + text.join(", "); } else { return QString(); } } diff --git a/ApperKCM/Updater/UpdateDetails.cpp b/ApperKCM/Updater/UpdateDetails.cpp index 53fa38c..ac652eb 100644 --- a/ApperKCM/Updater/UpdateDetails.cpp +++ b/ApperKCM/Updater/UpdateDetails.cpp @@ -1,344 +1,344 @@ /*************************************************************************** * Copyright (C) 2009-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "UpdateDetails.h" #include #include #include #include #include #include #include #include #include #include #include #include #define FINAL_HEIGHT 160 UpdateDetails::UpdateDetails(QWidget *parent) : QWidget(parent), m_show(false), m_transaction(0) { setupUi(this); hideTB->setIcon(QIcon::fromTheme("window-close")); connect(hideTB, SIGNAL(clicked()), this, SLOT(hide())); m_busySeq = new KPixmapSequenceOverlayPainter(this); m_busySeq->setSequence(KPixmapSequence("process-working", KIconLoader::SizeSmallMedium)); m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_busySeq->setWidget(this); QWidget *actionsViewport = descriptionKTB->viewport(); QPalette palette = actionsViewport->palette(); palette.setColor(actionsViewport->backgroundRole(), Qt::transparent); palette.setColor(actionsViewport->foregroundRole(), palette.color(QPalette::WindowText)); actionsViewport->setPalette(palette); QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(descriptionKTB); effect->setOpacity(0); descriptionKTB->setGraphicsEffect(effect); m_fadeDetails = new QPropertyAnimation(effect, "opacity", this); m_fadeDetails->setDuration(500); m_fadeDetails->setStartValue(qreal(0)); m_fadeDetails->setEndValue(qreal(1)); connect(m_fadeDetails, SIGNAL(finished()), this, SLOT(display())); QPropertyAnimation *anim1 = new QPropertyAnimation(this, "maximumSize", this); anim1->setDuration(500); anim1->setEasingCurve(QEasingCurve::OutQuart); anim1->setStartValue(QSize(QWIDGETSIZE_MAX, 0)); anim1->setEndValue(QSize(QWIDGETSIZE_MAX, FINAL_HEIGHT)); QPropertyAnimation *anim2 = new QPropertyAnimation(this, "minimumSize", this); anim2->setDuration(500); anim2->setEasingCurve(QEasingCurve::OutQuart); anim2->setStartValue(QSize(QWIDGETSIZE_MAX, 0)); anim2->setEndValue(QSize(QWIDGETSIZE_MAX, FINAL_HEIGHT)); m_expandPanel = new QParallelAnimationGroup(this); m_expandPanel->addAnimation(anim1); m_expandPanel->addAnimation(anim2); connect(m_expandPanel, SIGNAL(finished()), this, SLOT(display())); } UpdateDetails::~UpdateDetails() { } void UpdateDetails::setPackage(const QString &packageId, Transaction::Info updateInfo) { if (m_packageId == packageId) { return; } m_show = true; m_packageId = packageId; m_updateInfo = updateInfo; m_currentDescription.clear(); if (m_transaction) { disconnect(m_transaction, SIGNAL(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime)), this, SLOT(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime))); disconnect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(display())); } m_transaction = Daemon::getUpdateDetail(m_packageId); connect(m_transaction, SIGNAL(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime)), this, SLOT(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime))); connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(display())); if (maximumSize().height() == 0) { // Expand the panel m_expandPanel->setDirection(QAbstractAnimation::Forward); m_expandPanel->start(); } else if (m_fadeDetails->currentValue().toReal() != 0) { // Hide the old description m_fadeDetails->setDirection(QAbstractAnimation::Backward); m_fadeDetails->start(); } m_busySeq->start(); } void UpdateDetails::hide() { m_show = false; m_packageId.clear(); if (maximumSize().height() == FINAL_HEIGHT && m_fadeDetails->currentValue().toReal() == 1) { m_fadeDetails->setDirection(QAbstractAnimation::Backward); m_fadeDetails->start(); } else if (maximumSize().height() == FINAL_HEIGHT && m_fadeDetails->currentValue().toReal() == 0) { m_expandPanel->setDirection(QAbstractAnimation::Backward); m_expandPanel->start(); } } void UpdateDetails::display() { kDebug() << sender(); // set transaction to 0 as if PK crashes // UpdateDetails won't be emmited m_transaction = 0; if (!m_show) { hide(); return; } if (maximumSize().height() == FINAL_HEIGHT && !m_currentDescription.isEmpty() && m_fadeDetails->currentValue().toReal() == 0) { descriptionKTB->setHtml(m_currentDescription); m_fadeDetails->setDirection(QAbstractAnimation::Forward); m_fadeDetails->start(); } else if (m_currentDescription.isEmpty()) { updateDetailFinished(); } } void UpdateDetails::updateDetail(const QString &packageID, const QStringList &updates, const QStringList &obsoletes, const QStringList &vendorUrls, const QStringList &bugzillaUrls, const QStringList &cveUrls, PackageKit::Transaction::Restart restart, const QString &updateText, const QString &changelog, PackageKit::Transaction::UpdateState state, const QDateTime &issued, const QDateTime &updated) { //format and show description QString description; // update type (ie Security Update) if (m_updateInfo == Transaction::InfoEnhancement) { description += "

" + i18n("This update will add new features and expand functionality.") + "

"; } else if (m_updateInfo == Transaction::InfoBugfix) { description += "

" + i18n("This update will fix bugs and other non-critical problems.") + "

"; } else if (m_updateInfo == Transaction::InfoImportant) { description += "

" + i18n("This update is important as it may solve critical problems.") + "

"; } else if (m_updateInfo == Transaction::InfoSecurity) { description += "

" + i18n("This update is needed to fix a security vulnerability with this package.") + "

"; } else if (m_updateInfo == Transaction::InfoBlocked) { description += "

" + i18n("This update is blocked.") + "

"; } // Issued and Updated if (!issued.isNull() && !updated.isNull()) { description += "

" + i18n("This notification was issued on %1 and last updated on %2.", - KGlobal::locale()->formatDateTime(issued, KLocale::ShortDate), - KGlobal::locale()->formatDateTime(updated, KLocale::ShortDate)) + + KLocale::global()->formatDateTime(issued, KLocale::ShortDate), + KLocale::global()->formatDateTime(updated, KLocale::ShortDate)) + "

"; } else if (!issued.isNull()) { description += "

" + i18n("This notification was issued on %1.", - KGlobal::locale()->formatDateTime(issued, KLocale::ShortDate)) + + KLocale::global()->formatDateTime(issued, KLocale::ShortDate)) + "

"; } // Description if (!updateText.isEmpty()) { QString _updateText = updateText; _updateText.replace('\n', "
"); _updateText.replace(' ', " "); description += "

" + _updateText + "

"; } // links // Vendor if (!vendorUrls.isEmpty()) { description += "

" + i18np("For more information about this update please visit this website:", "For more information about this update please visit these websites:", vendorUrls.size()) + "
" + getLinkList(vendorUrls) + "

"; } // Bugzilla if (!bugzillaUrls.isEmpty()) { description += "

" + i18np("For more information about bugs fixed by this update please visit this website:", "For more information about bugs fixed by this update please visit these websites:", bugzillaUrls.size()) + "
" + getLinkList(bugzillaUrls) + "

"; } // CVE if (!cveUrls.isEmpty()) { description += "

" + i18np("For more information about this security update please visit this website:", "For more information about this security update please visit these websites:", cveUrls.size()) + "
" + getLinkList(cveUrls) + "

"; } // Notice (about the need for a reboot) if (restart == Transaction::RestartSystem) { description += "

" + i18n("The computer will have to be restarted after the update for the changes to take effect.") + "

"; } else if (restart == Transaction::RestartSession) { description += "

" + i18n("You will need to log out and back in after the update for the changes to take effect.") + "

"; } // State if (state == Transaction::UpdateStateUnstable) { description += "

" + i18n("The classification of this update is unstable which means it is not designed for production use.") + "

"; } else if (state == Transaction::UpdateStateTesting) { description += "

" + i18n("This is a test update, and is not designed for normal use. Please report any problems or regressions you encounter.") + "

"; } // only show changelog if we didn't have any update text if (updateText.isEmpty() && !changelog.isEmpty()) { QString _changelog = changelog; _changelog.replace('\n', "
"); _changelog.replace(' ', " "); description += "

" + i18n("The developer logs will be shown as no description is available for this update:") + "
" + _changelog + "

"; } // Updates (lists of packages that are updated) if (!updates.isEmpty()) { description += "

" + i18n("Updates:") + "
"; QStringList _updates; foreach (const QString &pid, updates) { _updates += QString::fromUtf8("\xE2\x80\xA2 ") + Transaction::packageName(pid) + " - " + Transaction::packageVersion(pid); } description += _updates.join("
") + "

"; } // Obsoletes (lists of packages that are obsoleted) if (obsoletes.size()) { description += "

" + i18n("Obsoletes:") + "
"; QStringList _obsoletes; foreach (const QString &pid, obsoletes) { _obsoletes += QString::fromUtf8("\xE2\x80\xA2 ") + Transaction::packageName(pid) + " - " + Transaction::packageVersion(pid); } description += _obsoletes.join("
/") + "

"; } // Repository (this is the repository the package comes from) if (!Transaction::packageData(packageID).isEmpty()) { description += "

" + i18n("Repository: %1", Transaction::packageData(packageID)) + "

"; } m_currentDescription = description; m_busySeq->stop(); } QString UpdateDetails::getLinkList(const QStringList &urls) const { QString ret; foreach (const QString &url, urls) { if (!ret.isEmpty()) { ret += "
"; } ret += QString::fromUtf8(" \xE2\x80\xA2 ") % url % QLatin1String(""); } return ret; } void UpdateDetails::updateDetailFinished() { if (descriptionKTB->document()->toPlainText().isEmpty()) { descriptionKTB->setPlainText(i18n("No update description was found.")); } } #include "UpdateDetails.moc" diff --git a/ApperKCM/Updater/UpdateDetails.ui b/ApperKCM/Updater/UpdateDetails.ui index 03efc48..a54652d 100644 --- a/ApperKCM/Updater/UpdateDetails.ui +++ b/ApperKCM/Updater/UpdateDetails.ui @@ -1,67 +1,69 @@ UpdateDetails 0 0 627 378 - + + 0 + + + 0 + + + 0 + + 0 Hide Qt::ToolButtonTextBesideIcon true - + QFrame::NoFrame QFrame::Plain Qt::ScrollBarAlwaysOff Qt::Vertical 20 40 - - - KTextBrowser - QTextBrowser -
ktextbrowser.h
-
-
diff --git a/ApperKCM/Updater/Updater.cpp b/ApperKCM/Updater/Updater.cpp index 65ee8b8..fecfe46 100644 --- a/ApperKCM/Updater/Updater.cpp +++ b/ApperKCM/Updater/Updater.cpp @@ -1,359 +1,359 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Updater.h" #include "ui_Updater.h" #include "UpdateDetails.h" #include "DistroUpgrade.h" #include "CheckableHeader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Updater::Updater(Transaction::Roles roles, QWidget *parent) : QWidget(parent), ui(new Ui::Updater), m_roles(roles), m_selected(true), m_updatesT(0) { ui->setupUi(this); updatePallete(); connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(updatePallete())); m_updatesModel = new PackageModel(this); m_updatesModel->setCheckable(true); ApplicationSortFilterModel *proxyModel = new ApplicationSortFilterModel(this); proxyModel->setSourceModel(m_updatesModel); ui->packageView->setModel(proxyModel); m_delegate = new ApplicationsDelegate(ui->packageView); m_delegate->setCheckable(true); ui->packageView->setItemDelegate(m_delegate); ui->packageView->sortByColumn(PackageModel::NameCol, Qt::AscendingOrder); connect(m_updatesModel, SIGNAL(changed(bool)), this, SLOT(checkEnableUpdateButton())); //initialize the model, delegate, client and connect it's signals m_header = new CheckableHeader(Qt::Horizontal, this); connect(m_header, SIGNAL(toggled(bool)), m_updatesModel, SLOT(setAllChecked(bool))); m_header->setCheckBoxVisible(false); m_header->setDefaultAlignment(Qt::AlignCenter); ui->packageView->setHeaderHidden(false); ui->packageView->setHeader(m_header); // This must be set AFTER the model is set, otherwise it doesn't work m_header->setResizeMode(PackageModel::NameCol, QHeaderView::Stretch); m_header->setResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents); m_header->setResizeMode(PackageModel::CurrentVersionCol, QHeaderView::ResizeToContents); m_header->setResizeMode(PackageModel::ArchCol, QHeaderView::ResizeToContents); m_header->setResizeMode(PackageModel::OriginCol, QHeaderView::ResizeToContents); m_header->setResizeMode(PackageModel::SizeCol, QHeaderView::ResizeToContents); m_header->setStretchLastSection(false); // Setup the busy cursor m_busySeq = new KPixmapSequenceOverlayPainter(this); m_busySeq->setSequence(KPixmapSequence("process-working", KIconLoader::SizeSmallMedium)); m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_busySeq->setWidget(ui->packageView->viewport()); // hide distro Upgrade container and line ui->distroUpgrade->hide(); KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); // versions ui->packageView->header()->setSectionHidden(PackageModel::VersionCol, true); m_showPackageVersion = new QAction(i18n("Show Versions"), this); m_showPackageVersion->setCheckable(true); connect(m_showPackageVersion, SIGNAL(toggled(bool)), this, SLOT(showVersions(bool))); m_showPackageVersion->setChecked(viewGroup.readEntry("ShowVersions", true)); // versions ui->packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, true); m_showPackageCurrentVersion = new QAction(i18n("Show Current Versions"), this); m_showPackageCurrentVersion->setCheckable(true); connect(m_showPackageCurrentVersion, SIGNAL(toggled(bool)), this, SLOT(showCurrentVersions(bool))); m_showPackageCurrentVersion->setChecked(viewGroup.readEntry("ShowCurrentVersions", false)); // Arch ui->packageView->header()->setSectionHidden(PackageModel::ArchCol, true); m_showPackageArch = new QAction(i18n("Show Architectures"), this); m_showPackageArch->setCheckable(true); connect(m_showPackageArch, SIGNAL(toggled(bool)), this, SLOT(showArchs(bool))); m_showPackageArch->setChecked(viewGroup.readEntry("ShowArchs", false)); // Origin ui->packageView->header()->setSectionHidden(PackageModel::OriginCol, true); m_showPackageOrigin = new QAction(i18n("Show Origins"), this); m_showPackageOrigin->setCheckable(true); connect(m_showPackageOrigin, SIGNAL(toggled(bool)), this, SLOT(showOrigins(bool))); m_showPackageOrigin->setChecked(viewGroup.readEntry("ShowOrigins", false)); // Sizes ui->packageView->header()->setSectionHidden(PackageModel::SizeCol, true); m_showPackageSize = new QAction(i18n("Show Sizes"), this); m_showPackageSize->setCheckable(true); connect(m_showPackageSize, SIGNAL(toggled(bool)), this, SLOT(showSizes(bool))); m_showPackageSize->setChecked(viewGroup.readEntry("ShowSizes", true)); } Updater::~Updater() { delete ui; } void Updater::showVersions(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); viewGroup.writeEntry("ShowVersions", enabled); ui->packageView->header()->setSectionHidden(PackageModel::VersionCol, !enabled); } void Updater::showCurrentVersions(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); viewGroup.writeEntry("ShowCurrentVersions", enabled); ui->packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, !enabled); if (enabled) { m_updatesModel->fetchCurrentVersions(); } } void Updater::showArchs(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); viewGroup.writeEntry("ShowArchs", enabled); ui->packageView->header()->setSectionHidden(PackageModel::ArchCol, !enabled); } void Updater::showOrigins(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); viewGroup.writeEntry("showOrigins", enabled); ui->packageView->header()->setSectionHidden(PackageModel::OriginCol, !enabled); } void Updater::showSizes(bool enabled) { KConfig config("apper"); KConfigGroup viewGroup(&config, "UpdateView"); viewGroup.writeEntry("ShowSizes", enabled); ui->packageView->header()->setSectionHidden(PackageModel::SizeCol, !enabled); if (enabled) { m_updatesModel->fetchSizes(); } } void Updater::updatePallete() { QPalette pal; pal.setColor(QPalette::Window, pal.base().color()); pal.setColor(QPalette::WindowText, pal.text().color()); ui->backgroundFrame->setPalette(pal); } void Updater::on_packageView_clicked(const QModelIndex &index) { QString pkgId = index.data(PackageModel::IdRole).toString(); Transaction::Info pkgInfo = index.data(PackageModel::InfoRole).value(); ui->updateDetails->setPackage(pkgId, pkgInfo); } //TODO: We should add some kind of configuration to let users show unstable distributions //That way, by default, users only see stable ones. void Updater::distroUpgrade(PackageKit::Transaction::DistroUpgrade type, const QString &name, const QString &description) { // TODO name should be used to do a upgrade to a different type Q_UNUSED(name) if (type != Transaction::DistroUpgradeStable) { // Ignore unstable distros upgrades for now return; } ui->distroUpgrade->setName(description); ui->distroUpgrade->animatedShow(); } bool Updater::hasChanges() const { return m_updatesModel->hasChanges(); } void Updater::checkEnableUpdateButton() { emit changed(hasChanges()); int selectedSize = m_updatesModel->selectedPackagesToInstall().size(); int updatesSize = m_updatesModel->rowCount(); if (selectedSize == 0) { m_header->setCheckState(Qt::Unchecked); } else if (selectedSize == updatesSize) { m_header->setCheckState(Qt::Checked); } else { m_header->setCheckState(Qt::PartiallyChecked); } unsigned long dwSize = m_updatesModel->downloadSize(); if (dwSize) { emit downloadSize(i18n("Estimated download size: %1", - KGlobal::locale()->formatByteSize(dwSize))); + KLocale::global()->formatByteSize(dwSize))); } else { emit downloadSize(QString()); } // if we don't have any upates let's disable the button m_header->setCheckBoxVisible(m_updatesModel->rowCount() != 0); ui->packageView->setHeaderHidden(m_updatesModel->rowCount() == 0); } void Updater::load() { // set focus on the updates view ui->packageView->setFocus(Qt::OtherFocusReason); emit downloadSize(QString()); // If the model already has some packages // let's just clear the selection if (m_updatesModel->rowCount()) { m_updatesModel->setAllChecked(false); } else { getUpdates(); } } void Updater::getUpdatesFinished() { m_updatesT = 0; m_updatesModel->clearSelectedNotPresent(); checkEnableUpdateButton(); if (m_updatesModel->rowCount() == 0) { // Set the info page ui->stackedWidget->setCurrentIndex(1); uint lastTime = Daemon::global()->getTimeSinceAction(Transaction::RoleRefreshCache); ui->titleL->setText(PkStrings::lastCacheRefreshTitle(lastTime)); ui->descriptionL->setText(PkStrings::lastCacheRefreshSubTitle(lastTime)); - ui->iconL->setPixmap(KIcon(PkIcons::lastCacheRefreshIconName(lastTime)).pixmap(128, 128)); + ui->iconL->setPixmap(QIcon::fromTheme(PkIcons::lastCacheRefreshIconName(lastTime)).pixmap(128, 128)); } } QStringList Updater::packagesToUpdate() const { return m_updatesModel->selectedPackagesToInstall(); } void Updater::getUpdates() { if (m_updatesT) { // There is a getUpdates running ignore this call return; } if (ui->stackedWidget->currentIndex() != 0) { ui->stackedWidget->setCurrentIndex(0); } // clears the model ui->packageView->setHeaderHidden(true); m_updatesModel->clear(); ui->updateDetails->hide(); m_updatesT = Daemon::getUpdates(); connect(m_updatesT, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), m_updatesModel, SLOT(addSelectedPackage(PackageKit::Transaction::Info,QString,QString))); connect(m_updatesT, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), this, SLOT(errorCode(PackageKit::Transaction::Error,QString))); connect(m_updatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_busySeq, SLOT(stop())); connect(m_updatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_updatesModel, SLOT(finished())); // This is required to estimate download size connect(m_updatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_updatesModel, SLOT(fetchSizes())); if (m_showPackageCurrentVersion->isChecked()) { connect(m_updatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), m_updatesModel, SLOT(fetchCurrentVersions())); } connect(m_updatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(getUpdatesFinished())); m_busySeq->start(); // Hide the distribution upgrade information ui->distroUpgrade->animatedHide(); if (m_roles & Transaction::RoleGetDistroUpgrades) { // Check for distribution Upgrades Transaction *t = Daemon::getDistroUpgrades(); connect(t, SIGNAL(distroUpgrade(PackageKit::Transaction::DistroUpgrade,QString,QString)), this, SLOT(distroUpgrade(PackageKit::Transaction::DistroUpgrade,QString,QString))); connect(t, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), t, SLOT(deleteLater())); } } void Updater::on_packageView_customContextMenuRequested(const QPoint &pos) { - KMenu *menu = new KMenu(this); + auto menu = new KMenu(this); menu->addAction(m_showPackageVersion); menu->addAction(m_showPackageCurrentVersion); menu->addAction(m_showPackageArch); menu->addAction(m_showPackageOrigin); menu->addAction(m_showPackageSize); QAction *action; action = menu->addAction(i18n("Check for new updates")); - action->setIcon(KIcon("view-refresh")); + action->setIcon(QIcon::fromTheme("view-refresh")); connect(action, SIGNAL(triggered(bool)), this, SIGNAL(refreshCache())); menu->exec(ui->packageView->viewport()->mapToGlobal(pos)); delete menu; } void Updater::errorCode(PackageKit::Transaction::Error error, const QString &details) { KMessageBox::detailedSorry(this, PkStrings::errorMessage(error), details, PkStrings::error(error), KMessageBox::Notify); } #include "Updater.moc" diff --git a/PkSession/PkSession.cpp b/PkSession/PkSession.cpp index e9427b7..0ffe060 100644 --- a/PkSession/PkSession.cpp +++ b/PkSession/PkSession.cpp @@ -1,98 +1,98 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PkSession.h" #include "PkInterface.h" #include #include #include #include #include #include #include #define MINUTE 60000 using namespace PackageKit; PkSession::PkSession(QObject* parent) : QObject(parent) { m_pkInterface = new PkInterface(this); connect(m_pkInterface, SIGNAL(close()), this, SLOT(prepareToClose())); - QString locale(KGlobal::locale()->language() % QLatin1Char('.') % KGlobal::locale()->encoding()); + QString locale(KLocale::global()->language() % QLatin1Char('.') % KLocale::global()->encoding()); Daemon::global()->setHints(QLatin1String("locale=") % locale); // this enables not quitting when closing a transaction ui qApp->setQuitOnLastWindowClosed(false); // create the close timer and connect it's signal m_closeT = new QTimer(this); connect(m_closeT, SIGNAL(timeout()), this, SLOT(close())); prepareToClose(); } void PkSession::prepareToClose() { if (isRunning()) { kDebug() << "Stoping Timer"; m_closeT->stop(); } else { kDebug() << "Starting Timer: " << MINUTE; m_closeT->start(MINUTE); } } bool PkSession::isRunning() { if (m_pkInterface && m_pkInterface->isRunning()) { kDebug() << m_pkInterface; return true; } return false; } void PkSession::close() { // This will run when the timer times out, we will check // again just to be sure. if (!isRunning()) { kDebug() << "Closed by Timer"; qApp->quit(); } } int PkSession::newInstance() { return 0; } PkSession::~PkSession() { } diff --git a/PkSession/SessionTask.cpp b/PkSession/SessionTask.cpp index 0d5783c..2b85fdd 100644 --- a/PkSession/SessionTask.cpp +++ b/PkSession/SessionTask.cpp @@ -1,661 +1,661 @@ /*************************************************************************** * Copyright (C) 2009-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "SessionTask.h" #include "ui_SessionTask.h" #include "IntroDialog.h" #include "InfoWidget.h" #include "ReviewChanges.h" #include "ApplicationLauncher.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PackageKit; SessionTask::SessionTask(uint xid, const QString &interaction, const QDBusMessage &message, QWidget *parent) : KDialog(parent), m_xid(xid), m_message(message), m_reviewChanges(0), m_pkTransaction(0), ui(new Ui::SessionTask) { ui->setupUi(KDialog::mainWidget()); setAttribute(Qt::WA_DeleteOnClose); m_model = new PackageModel(this); connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(updatePallete())); updatePallete(); - setWindowIcon(KIcon("system-software-install")); + setWindowIcon(QIcon::fromTheme("system-software-install")); setButtons(KDialog::Ok | KDialog::Cancel); setButtonText(KDialog::Ok, i18n("Continue")); - setButtonIcon(KDialog::Ok, KIcon("go-next")); + setButtonIcon(KDialog::Ok, QIcon::fromTheme("go-next")); enableButtonOk(false); - QString locale(KGlobal::locale()->language() % QLatin1Char('.') % KGlobal::locale()->encoding()); + QString locale(KLocale::global()->language() % QLatin1Char('.') % KLocale::global()->encoding()); Daemon::global()->setHints(QLatin1String("locale=") % locale); // Defaults to always m_interactions = ConfirmSearch | ConfirmDeps | ConfirmInstall | Progress | Finished | Warning; m_timeout = 0; parseInteraction(interaction); QString cmdline; uint pid; // TODO as we are running on the session it might // be useless to check the PID on the system if ((pid = getPidSession()) != UINT_MAX) { cmdline = getCmdLine(pid); } else if ((pid = getPidSystem()) != UINT_MAX) { cmdline = getCmdLine(pid); } if (!cmdline.isNull()) { setExec(cmdline); } setMinimumSize(QSize(430,280)); KConfig config("apper"); KConfigGroup configGroup(&config, "SessionInstaller"); restoreDialogSize(configGroup); } SessionTask::~SessionTask() { KConfig config("apper"); KConfigGroup configGroup(&config, "SessionInstaller"); saveDialogSize(configGroup); delete ui; } void SessionTask::addPackage(Transaction::Info info, const QString &packageID, const QString &summary) { m_model->addSelectedPackage(info, packageID, summary); } void SessionTask::searchFinished(PkTransaction::ExitStatus status) { if (m_pkTransaction) { // Disconnect so it can be connected to commitFinished latter disconnect(m_pkTransaction->transaction(), SIGNAL(finished(PkTransaction::ExitStatus)), this, SLOT(searchFinished(PkTransaction::ExitStatus))); } if (status == PkTransaction::Success) { m_model->finished(); if (m_model->rowCount() == 0) { notFound(); } else { searchSuccess(); } } else if (status == PkTransaction::Cancelled) { slotButtonClicked(KDialog::Cancel); } else { searchFailed(); } } void SessionTask::commitFinished(PkTransaction::ExitStatus status) { if (m_pkTransaction) { // Disconnect so it can be connected to something else latter disconnect(m_pkTransaction->transaction(), SIGNAL(finished(PkTransaction::ExitStatus)), this, SLOT(searchFinished(PkTransaction::ExitStatus))); } if (status == PkTransaction::Success) { if (!m_removePackages.isEmpty()) { removePackages(); } else { commitSuccess(); } } else if (status == PkTransaction::Cancelled) { slotButtonClicked(KDialog::Cancel); } else { commitFailed(); } } void SessionTask::updatePallete() { QPalette pal; pal.setColor(QPalette::Window, KGlobalSettings::activeTitleColor()); pal.setColor(QPalette::WindowText, KGlobalSettings::activeTextColor()); ui->backgroundFrame->setPalette(pal); } void SessionTask::setDialog(KDialog *dialog) { // Store the current values QWidget *widget = ui->stackedWidget->currentWidget(); if (qobject_cast(dialog)) { // TODO if there is a removal after instalation // this will break it, but we don't have // this case yet... commitSuccess(dialog->mainWidget()); } else { // Set the new ones setMainWidget(dialog->mainWidget()); setTitle(dialog->windowTitle()); // must come after connect(this, SIGNAL(okClicked()), dialog, SLOT(accept())); connect(this, SIGNAL(okClicked()), dialog->mainWidget(), SLOT(deleteLater())); connect(this, SIGNAL(okClicked()), dialog, SLOT(deleteLater())); // Make sure we see the last widget and title QSignalMapper *mapper = new QSignalMapper(this); mapper->setMapping(this, widget); connect(this, SIGNAL(okClicked()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(QWidget*)), this, SLOT(setMainWidget(QWidget*))); enableButtonOk(true); } } void SessionTask::setMainWidget(QWidget *widget) { if (widget != mainWidget()) { ui->stackedWidget->addWidget(widget); ui->stackedWidget->setCurrentWidget(widget); setTitle(widget->windowTitle()); } } QWidget* SessionTask::mainWidget() { return ui->stackedWidget->currentWidget(); } void SessionTask::setInfo(const QString &title, const QString &text, const QString &details) { InfoWidget *info = new InfoWidget(this); info->setWindowTitle(title); info->setDescription(text); info->setDetails(details); setMainWidget(info); setButtons(KDialog::Close); button(KDialog::Close)->setFocus(); if (qobject_cast(sender())) { // if we have a sender this method was caller by PkTransaction // be carefull because QSignalMapper from KDialog also calls this method sender()->disconnect(); sendErrorFinished(Failed, text); } } void SessionTask::setError(const QString &title, const QString &text, const QString &details) { InfoWidget *info = new InfoWidget(this); info->setWindowTitle(title); info->setDescription(text); - info->setIcon(KIcon("dialog-error")); + info->setIcon(QIcon::fromTheme("dialog-error")); info->setDetails(details); setMainWidget(info); setButtons(KDialog::Close); button(KDialog::Close)->setFocus(); if (qobject_cast(sender())) { // if we have a sender this method was caller by PkTransaction // be carefull because QSignalMapper from KDialog also calls this method sender()->disconnect(); sendErrorFinished(Failed, text); } } void SessionTask::setFinish(const QString &title, const QString &text, QWidget *widget) { InfoWidget *info = new InfoWidget(this); info->setWindowTitle(title); info->setDescription(text); - info->setIcon(KIcon("dialog-ok-apply")); + info->setIcon(QIcon::fromTheme("dialog-ok-apply")); info->addWidget(widget); setMainWidget(info); setButtons(KDialog::Close); button(KDialog::Close)->setFocus(); } void SessionTask::setTitle(const QString &title) { ui->titleL->setText(title); } void SessionTask::setExec(const QString &exec) { if (pathIsTrusted(exec)) { // Get from X11 the window title KWindowInfo info = KWindowSystem::windowInfo(m_xid, NET::WMVisibleName); parentTitle = info.visibleName(); } else { parentTitle = exec; } } bool SessionTask::pathIsTrusted(const QString &exec) { // special case the plugin helper -- it's trusted return exec == "/usr/libexec/gst-install-plugins-helper" || exec == "/usr/libexec/pk-gstreamer-install" || exec == "/usr/bin/gstreamer-codec-install" || exec == "/usr/lib/packagekit/pk-gstreamer-install" || exec == "/usr/bin/plasma-desktop" || exec == "/usr/bin/apper"; } QString SessionTask::getCmdLine(uint pid) { QFile file(QString("/proc/%1/cmdline").arg(pid)); QString line; if (file.open(QFile::ReadOnly)) { char buf[1024]; qint64 lineLength = file.readLine(buf, sizeof(buf)); if (lineLength != -1) { // the line is available in buf line = QString::fromLocal8Bit(buf); if (!line.contains("(deleted)")) { return line; } } } return QString(); } uint SessionTask::getPidSystem() { QDBusMessage msg; msg = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", "org.freedesktop.DBus", QLatin1String("GetConnectionUnixProcessID")); msg << m_message.service(); QDBusMessage reply = QDBusConnection::systemBus().call(msg); if (reply.type() != QDBusMessage::ReplyMessage) { kWarning() << "Message did not receive a reply"; } if (reply.arguments().size() == 1) { return reply.arguments().at(0).toUInt(); } return UINT_MAX; } uint SessionTask::getPidSession() { QDBusMessage msg; msg = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", "org.freedesktop.DBus", QLatin1String("GetConnectionUnixProcessID")); msg << m_message.service(); QDBusMessage reply = QDBusConnection::sessionBus().call(msg); if (reply.type() != QDBusMessage::ReplyMessage) { kWarning() << "Message did not receive a reply"; } if (reply.arguments().size() == 1) { return reply.arguments().at(0).toUInt(); } return UINT_MAX; } void SessionTask::search() { kDebug() << "virtual method called, falling back to commit()"; commit(); } void SessionTask::commit() { kDebug() << "virtual method called"; if (m_reviewChanges) { QStringList installPackages = m_reviewChanges->model()->selectedPackagesToInstall(); m_removePackages = m_reviewChanges->model()->selectedPackagesToRemove(); if (installPackages.isEmpty() && m_removePackages.isEmpty()) { setInfo(i18n("There are no packages to Install or Remove"), i18n("This action should not happen")); sendErrorFinished(Failed, "to install or remove due to empty lists"); } else if (!installPackages.isEmpty()) { // Install Packages PkTransaction *transaction = new PkTransaction(this); setTransaction(Transaction::RoleInstallPackages, transaction); connect(transaction, SIGNAL(finished(PkTransaction::ExitStatus)), this, SLOT(commitFinished(PkTransaction::ExitStatus)), Qt::UniqueConnection); transaction->installPackages(installPackages); } else { // Remove them removePackages(); } } } void SessionTask::removePackages() { // Remove Packages PkTransaction *transaction = new PkTransaction(this); setTransaction(Transaction::RoleRemovePackages, transaction); connect(transaction, SIGNAL(finished(PkTransaction::ExitStatus)), this, SLOT(commitFinished(PkTransaction::ExitStatus)), Qt::UniqueConnection); transaction->removePackages(m_removePackages); m_removePackages.clear(); } void SessionTask::notFound() { kDebug() << "virtual method called"; if (showWarning()) { setInfo(i18n("Could not find"), i18n("No packages were found that meet the request")); } sendErrorFinished(NoPackagesFound, "no package found"); } void SessionTask::searchFailed() { kDebug() << "virtual method called"; setInfo(i18n("Failed to find"), i18n("No packages were found that meet the request")); sendErrorFinished(Failed, "failed to search"); } void SessionTask::searchSuccess() { kDebug() << "virtual method called"; enableButtonOk(true); m_reviewChanges = new ReviewChanges(m_model, this); connect(m_reviewChanges, SIGNAL(hasSelectedPackages(bool)), this, SLOT(enableButtonOk(bool))); setMainWidget(m_reviewChanges); } void SessionTask::commitFailed() { kDebug() << "virtual method called"; // This should not be used to display stuff as the transaction should // emit error() or info() // setInfo(i18n("Failed to commit transaction"), // PkStrings::errorMessage(m_pkTransaction->error())); sendErrorFinished(Failed, i18n("Transaction did not finish with success")); } void SessionTask::commitSuccess(QWidget *widget) { kDebug() << "virtual method called"; setFinish(i18n("Task completed"), i18n("All operations were committed successfully"), widget); finishTaskOk(); } void SessionTask::slotButtonClicked(int button) { if (button == KDialog::Ok) { // kDebug() << mainWidget()->objectName(); if (qobject_cast(mainWidget())) { enableButtonOk(false); search(); } else if (qobject_cast(mainWidget())) { enableButtonOk(false); commit(); } else { emit okClicked(); } } else { KDialog::slotButtonClicked(button); sendErrorFinished(Cancelled, "Aborted by the user"); } } void SessionTask::sendErrorFinished(DBusError error, const QString &msg) { QString dbusError; switch (error) { case Failed: dbusError = "org.freedesktop.PackageKit.Failed"; break; case InternalError: dbusError = "org.freedesktop.PackageKit.InternalError"; break; case NoPackagesFound: dbusError = "org.freedesktop.PackageKit.NoPackagesFound"; break; case Forbidden: dbusError = "org.freedesktop.PackageKit.Forbidden"; break; case Cancelled: dbusError = "org.freedesktop.PackageKit.Cancelled"; break; } QDBusMessage reply; reply = m_message.createErrorReply(dbusError, msg); QDBusConnection::sessionBus().send(reply); } bool SessionTask::sendMessageFinished(const QDBusMessage &message) { emit finished(); return QDBusConnection::sessionBus().send(message); } uint SessionTask::parentWId() const { return m_xid; } void SessionTask::enableButtonOk(bool state) { KDialog::enableButtonOk(state); if (state) { // When enabling the Continue button put focus on it button(KDialog::Ok)->setFocus(); } } void SessionTask::parseInteraction(const QString &interaction) { QStringList interactions = interaction.split(','); // Enable or disable all options if (interactions.contains("always")) { m_interactions = ConfirmSearch | ConfirmDeps | ConfirmInstall | Progress | Finished | Warning; } else if (interactions.contains("never")) { m_interactions = 0; } // show custom options if (interactions.contains("show-confirm-search")) { m_interactions |= ConfirmSearch; } if (interactions.contains("show-confirm-deps")) { m_interactions |= ConfirmDeps; } if (interactions.contains("show-confirm-install")) { m_interactions |= ConfirmInstall; } if (interactions.contains("show-progress")) { m_interactions |= Progress; } if (interactions.contains("show-finished")) { m_interactions |= Finished; } if (interactions.contains("show-warning")) { m_interactions |= Warning; } // hide custom options if (interactions.contains("hide-confirm-search")) { m_interactions &= ~ConfirmSearch; } if (interactions.contains("hide-confirm-deps")) { m_interactions &= ~ConfirmDeps; } if (interactions.contains("hide-confirm-install")) { m_interactions &= ~ConfirmInstall; } if (interactions.contains("hide-progress")) { m_interactions &= ~Progress; } if (interactions.contains("hide-finished")) { m_interactions &= ~Finished; } if (interactions.contains("hide-warning")) { m_interactions &= ~Warning; } int index; QRegExp rx("^timeout=(\\d+)$"); index = interactions.indexOf(rx); if (index != -1) { if (rx.indexIn(interactions.at(index)) != -1) { m_timeout = rx.cap(1).toUInt(); } } } bool SessionTask::foundPackages() const { return m_model->rowCount(); } int SessionTask::foundPackagesSize() const { return m_model->rowCount(); } PackageModel *SessionTask::model() const { return m_model; } void SessionTask::setTransaction(Transaction::Role role, PkTransaction *t) { if (m_pkTransaction == 0) { m_pkTransaction = new PkTransactionWidget(this); m_pkTransaction->hideCancelButton(); ui->stackedWidget->addWidget(m_pkTransaction); connect(m_pkTransaction, SIGNAL(titleChanged(QString)), this, SLOT(setTitle(QString))); connect(this, SIGNAL(cancelClicked()), m_pkTransaction, SLOT(cancel())); connect(m_pkTransaction, SIGNAL(dialog(KDialog*)), this, SLOT(setDialog(KDialog*))); connect(m_pkTransaction, SIGNAL(sorry(QString,QString,QString)), this, SLOT(setInfo(QString,QString,QString))); connect(m_pkTransaction, SIGNAL(error(QString,QString,QString)), this, SLOT(setError(QString,QString,QString))); } if (t) { m_pkTransaction->setTransaction(t, role); // setTitle(m_pkTransaction->title()); } // avoid changing the current widget if (mainWidget() != m_pkTransaction) { ui->stackedWidget->setCurrentWidget(m_pkTransaction); } } void SessionTask::finishTaskOk() { sendMessageFinished(m_message.createReply()); } SessionTask::Interactions SessionTask::interactions() const { return m_interactions; } uint SessionTask::timeout() const { return m_timeout; } bool SessionTask::showConfirmSearch() const { return m_interactions & ConfirmSearch; } bool SessionTask::showConfirmDeps() const { return m_interactions & ConfirmDeps; } bool SessionTask::showConfirmInstall() const { return m_interactions & ConfirmInstall; } bool SessionTask::showProgress() const { return m_interactions & Progress; } bool SessionTask::showFinished() const { return m_interactions & Finished; } bool SessionTask::showWarning() const { return m_interactions & Warning; } #include "SessionTask.moc" diff --git a/apperd/CMakeLists.txt b/apperd/CMakeLists.txt index c488bcb..665b3c9 100644 --- a/apperd/CMakeLists.txt +++ b/apperd/CMakeLists.txt @@ -1,43 +1,41 @@ # CMakeLists for the kded component set(kded_apperd_SRCS DistroUpgrade.cpp DBusInterface.cpp TransactionJob.cpp TransactionWatcher.cpp RefreshCacheTask.cpp Updater.cpp RebootListener.cpp ApperdThread.cpp apperd.cpp ) qt5_add_dbus_adaptor(kded_apperd_SRCS org.kde.apperd.xml DBusInterface.h DBusInterface ) add_library(kded_apperd MODULE ${kded_apperd_SRCS}) target_link_libraries(kded_apperd KF5::WidgetsAddons KF5::KIOFileWidgets - KF5::KDELibs4Support - KF5::IconThemes KF5::Notifications KF5::DBusAddons ${PackageKitQt5_LIBRARIES} PW::KWorkspace apper_private ) if(DEBCONF_SUPPORT) target_link_libraries(kded_apperd DebconfKDE::Main) endif(DEBUCONF_SUPPORT) set_target_properties(kded_apperd PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}/apper) install(TARGETS kded_apperd DESTINATION ${CMAKE_INSTALL_QTPLUGINDIR}) install(FILES apperd.notifyrc DESTINATION ${CMAKE_INSTALL_DATADIR}/apperd) install(FILES apperd.desktop DESTINATION ${CMAKE_INSTALL_KSERVICES5DIR}/kded) diff --git a/apperd/DistroUpgrade.cpp b/apperd/DistroUpgrade.cpp index 69def76..8a38a39 100644 --- a/apperd/DistroUpgrade.cpp +++ b/apperd/DistroUpgrade.cpp @@ -1,179 +1,179 @@ /*************************************************************************** * Copyright (C) 2009-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "DistroUpgrade.h" #include #include #include #include -#include +#include #include DistroUpgrade::DistroUpgrade(QObject *parent) : QObject(parent), m_distroUpgradeProcess(0), m_transaction(0) { } DistroUpgrade::~DistroUpgrade() { } void DistroUpgrade::setConfig(const QVariantHash &configs) { m_configs = configs; } void DistroUpgrade::checkDistroUpgrades() { // Ignore check if the user disabled it if (m_configs[CFG_DISTRO_UPGRADE].toInt() == Enum::DistroNever) { return; } if (!m_transaction) { m_transaction = Daemon::getDistroUpgrades(); connect(m_transaction, SIGNAL(distroUpgrade(PackageKit::Transaction::DistroUpgrade,QString,QString)), this, SLOT(distroUpgrade(PackageKit::Transaction::DistroUpgrade,QString,QString))); connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(checkDistroFinished(PackageKit::Transaction::Exit,uint))); } } void DistroUpgrade::distroUpgrade(PackageKit::Transaction::DistroUpgrade type, const QString &name, const QString &description) { // TODO make use of the type switch (m_configs[CFG_DISTRO_UPGRADE].toInt()) { case Enum::DistroNever: return; case Enum::DistroStable: if (type != Transaction::DistroUpgradeStable) { // The user only wants to know about stable releases return; } default: break; } kDebug() << "Distro upgrade found!" << name << description; if (m_shownDistroUpgrades.contains(name)) { // ignore distro upgrade if the user already saw it return; } KNotification *notify = new KNotification("DistroUpgradeAvailable", 0, KNotification::Persistent); notify->setComponentName("apperd"); notify->setTitle(i18n("Distribution upgrade available")); notify->setText(description); QStringList actions; actions << i18n("Start upgrade now"); notify->setActions(actions); connect(notify, SIGNAL(activated(uint)), this, SLOT(handleDistroUpgradeAction(uint))); notify->sendEvent(); m_shownDistroUpgrades << name; } void DistroUpgrade::checkDistroFinished(Transaction::Exit status, uint enlapsed) { Q_UNUSED(status) Q_UNUSED(enlapsed) m_transaction = 0; } void DistroUpgrade::handleDistroUpgradeAction(uint action) { // get the sender cause there might be more than one - KNotification *notify = qobject_cast(sender()); + auto notify = qobject_cast(sender()); switch(action) { case 1: // Check to see if there isn't another process running if (m_distroUpgradeProcess) { // if so we BREAK otherwise our running count gets // lost, and we leak as we don't close the caller. break; } m_distroUpgradeProcess = new QProcess; connect (m_distroUpgradeProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(distroUpgradeError(QProcess::ProcessError))); connect (m_distroUpgradeProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(distroUpgradeFinished(int,QProcess::ExitStatus))); QStringList env = QProcess::systemEnvironment(); env << "DESKTOP=kde"; m_distroUpgradeProcess->setEnvironment(env); m_distroUpgradeProcess->start("/usr/share/PackageKit/pk-upgrade-distro.sh"); // TODO // suppressSleep(true); break; // perhaps more actions needed in the future } // in persistent mode we need to manually close it notify->close(); } void DistroUpgrade::distroUpgradeFinished(int exitCode, QProcess::ExitStatus exitStatus) { - KNotification *notify = new KNotification("DistroUpgradeFinished"); + auto notify = new KNotification("DistroUpgradeFinished"); notify->setComponentName("apperd"); if (exitStatus == QProcess::NormalExit && exitCode == 0) { - notify->setPixmap(KIcon("security-high").pixmap(64, 64)); + notify->setPixmap(QIcon::fromTheme("security-high").pixmap(64, 64)); notify->setText(i18n("Distribution upgrade finished. ")); } else if (exitStatus == QProcess::NormalExit) { - notify->setPixmap(KIcon("dialog-warning").pixmap(64, 64)); + notify->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(64, 64)); notify->setText(i18n("Distribution upgrade process exited with code %1.", exitCode)); }/* else { notify->setText(i18n("Distribution upgrade didn't exit normally, the process probably crashed. ")); }*/ notify->sendEvent(); m_distroUpgradeProcess->deleteLater(); m_distroUpgradeProcess = 0; // suppressSleep(false); } void DistroUpgrade::distroUpgradeError(QProcess::ProcessError error) { QString text; - KNotification *notify = new KNotification("DistroUpgradeError"); + auto notify = new KNotification("DistroUpgradeError"); notify->setComponentName("apperd"); switch(error) { case QProcess::FailedToStart: text = i18n("The distribution upgrade process failed to start."); break; case QProcess::Crashed: text = i18n("The distribution upgrade process crashed some time after starting successfully.") ; break; default: text = i18n("The distribution upgrade process failed with an unknown error."); break; } - notify->setPixmap(KIcon("dialog-error").pixmap(64,64)); + notify->setPixmap(QIcon::fromTheme("dialog-error").pixmap(64,64)); notify->setText(text); notify->sendEvent(); } #include "DistroUpgrade.moc" diff --git a/apperd/RefreshCacheTask.cpp b/apperd/RefreshCacheTask.cpp index 7a6ee3f..fbc3b9f 100644 --- a/apperd/RefreshCacheTask.cpp +++ b/apperd/RefreshCacheTask.cpp @@ -1,88 +1,87 @@ /*************************************************************************** * Copyright (C) 2012 by Daniel Nicoletti dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "RefreshCacheTask.h" #include #include #include -#include #include #include RefreshCacheTask::RefreshCacheTask(QObject *parent) : QObject(parent), m_transaction(0), m_notification(0), m_lastError(Transaction::ErrorUnknown), m_cacheAge(3600) { } void RefreshCacheTask::refreshCache() { kDebug(); if (!m_transaction) { // Refresh Cache is false otherwise it will rebuild // the whole cache on Fedora Daemon::setHints (QLatin1String("cache-age=")+QString::number(m_cacheAge)); m_transaction = Daemon::refreshCache(false); connect(m_transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(refreshCacheFinished(PackageKit::Transaction::Exit,uint))); connect(m_transaction, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), this, SLOT(errorCode(PackageKit::Transaction::Error,QString))); } } void RefreshCacheTask::refreshCacheFinished(PackageKit::Transaction::Exit status, uint runtime) { Q_UNUSED(runtime) m_transaction = 0; if (status == Transaction::ExitSuccess) { m_lastError = Transaction::ErrorUnknown; m_lastErrorString.clear(); } } void RefreshCacheTask::errorCode(Transaction::Error error, const QString &errorMessage) { if (m_notification || (m_lastError == error && m_lastErrorString == errorMessage)) { return; } m_notification = new KNotification("TransactionFailed", KNotification::Persistent, this); m_notification->setComponentName("apperd"); connect(m_notification, SIGNAL(closed()), this, SLOT(notificationClosed())); - KIcon icon("dialog-cancel"); + QIcon icon = QIcon::fromTheme("dialog-cancel"); // use of QSize does the right thing m_notification->setPixmap(icon.pixmap(QSize(KPK_ICON_SIZE, KPK_ICON_SIZE))); m_notification->setTitle(PkStrings::error(error)); m_notification->setText(errorMessage); m_notification->sendEvent(); } void RefreshCacheTask::notificationClosed() { m_notification->deleteLater(); m_notification = 0; } diff --git a/apperd/Updater.cpp b/apperd/Updater.cpp index 56cd521..6a0d4fc 100644 --- a/apperd/Updater.cpp +++ b/apperd/Updater.cpp @@ -1,325 +1,323 @@ /*************************************************************************** * Copyright (C) 2008 by Trever Fischer * * wm161@wm161.net * * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Updater.h" #include "ApperdThread.h" #include #include #include #include #include #include #include #include #include #include #include #include #define UPDATES_ICON "system-software-update" using namespace PackageKit; Updater::Updater(QObject* parent) : QObject(parent), m_getUpdatesT(0) { // in case registration fails due to another user or application running // keep an eye on it so we can register when available - QDBusServiceWatcher *watcher; - watcher = new QDBusServiceWatcher(QLatin1String("org.kde.ApperUpdaterIcon"), - QDBusConnection::sessionBus(), - QDBusServiceWatcher::WatchForOwnerChange, - this); - connect(watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), - this, SLOT(serviceOwnerChanged(QString,QString,QString))); + auto watcher = new QDBusServiceWatcher(QLatin1String("org.kde.ApperUpdaterIcon"), + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForOwnerChange, + this); + connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &Updater::serviceOwnerChanged); m_hasAppletIconified = ApperdThread::nameHasOwner(QLatin1String("org.kde.ApperUpdaterIcon"), QDBusConnection::sessionBus()); } Updater::~Updater() { } void Updater::setConfig(const QVariantHash &configs) { m_configs = configs; } void Updater::setSystemReady() { // System ready changed, maybe we can auto // install some updates m_systemReady = true; getUpdateFinished(); } void Updater::checkForUpdates(bool systemReady) { m_systemReady = systemReady; // Skip the check if one is already running or // the plasmoid is in Icon form and the auto update type is None if (m_getUpdatesT) { return; } m_updateList.clear(); m_importantList.clear(); m_securityList.clear(); m_getUpdatesT = Daemon::getUpdates(); connect(m_getUpdatesT, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), this, SLOT(packageToUpdate(PackageKit::Transaction::Info,QString,QString))); connect(m_getUpdatesT, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), this, SLOT(getUpdateFinished())); } void Updater::packageToUpdate(Transaction::Info info, const QString &packageID, const QString &summary) { Q_UNUSED(summary) switch (info) { case Transaction::InfoBlocked: // Blocked updates are not instalable updates so there is no // reason to show/count them return; case Transaction::InfoImportant: m_importantList << packageID; break; case Transaction::InfoSecurity: m_securityList << packageID; break; default: break; } m_updateList << packageID; } void Updater::getUpdateFinished() { m_getUpdatesT = 0; if (!m_updateList.isEmpty()) { Transaction *transaction = qobject_cast(sender()); bool different = false; if (m_oldUpdateList.size() != m_updateList.size()) { different = true; } else { // The lists have the same size let's make sure // all the packages are the same foreach (const QString &packageId, m_updateList) { if (!m_oldUpdateList.contains(packageId)) { different = true; break; } } } // sender is not a transaction when we systemReady has changed // if the lists are the same don't show // a notification or try to upgrade again if (transaction && !different) { return; } uint updateType = m_configs[CFG_AUTO_UP].value(); if (m_systemReady && updateType == Enum::All) { // update all bool ret; ret = updatePackages(m_updateList, false, "plasmagik", i18n("Updates are being automatically installed.")); if (ret) { return; } } else if (m_systemReady && updateType == Enum::Security && !m_securityList.isEmpty()) { // Defaults to security bool ret; ret = updatePackages(m_securityList, false, UPDATES_ICON, i18n("Security updates are being automatically installed.")); if (ret) { return; } } else if (m_systemReady && updateType == Enum::DownloadOnly) { // Download all updates bool ret; ret = updatePackages(m_updateList, true, "download", i18n("Updates are being automatically downloaded.")); if (ret) { return; } } else if (!m_systemReady && (updateType == Enum::All || updateType == Enum::DownloadOnly || (updateType == Enum::Security && !m_securityList.isEmpty()))) { kDebug() << "Not auto updating or downloading, as we might be on battery or mobile connection"; } // If an erro happened to create the auto update // transaction show the update list if (transaction) { // The transaction is not valid if the systemReady changed showUpdatesPopup(); } } else { m_oldUpdateList.clear(); } } void Updater::autoUpdatesFinished(PkTransaction::ExitStatus status) { KNotification *notify = new KNotification("UpdatesComplete"); notify->setComponentName("apperd"); if (status == PkTransaction::Success) { if (sender()->property("DownloadOnly").toBool()) { // We finished downloading show the updates to the user showUpdatesPopup(); } else { QIcon icon = QIcon::fromTheme("task-complete"); // use of QSize does the right thing notify->setPixmap(icon.pixmap(KPK_ICON_SIZE, KPK_ICON_SIZE)); notify->setText(i18n("System update was successful.")); notify->sendEvent(); } } else { QIcon icon = QIcon::fromTheme("dialog-cancel"); // use of QSize does the right thing notify->setPixmap(icon.pixmap(KPK_ICON_SIZE, KPK_ICON_SIZE)); notify->setText(i18n("The software update failed.")); notify->sendEvent(); // show updates popup showUpdatesPopup(); } } void Updater::reviewUpdates() { if (m_hasAppletIconified) { QDBusMessage message; message = QDBusMessage::createMethodCall(QLatin1String("org.kde.ApperUpdaterIcon"), QLatin1String("/"), QLatin1String("org.kde.ApperUpdaterIcon"), QLatin1String("ReviewUpdates")); QDBusMessage reply = QDBusConnection::sessionBus().call(message); if (reply.type() == QDBusMessage::ReplyMessage) { return; } kWarning() << "Message did not receive a reply"; } // This must be called from the main thread... KToolInvocation::startServiceByDesktopName("apper_updates"); } void Updater::installUpdates() { bool ret; ret = updatePackages(m_updateList, false); if (ret) { return; } reviewUpdates(); } void Updater::serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner) { Q_UNUSED(service) Q_UNUSED(oldOwner) m_hasAppletIconified = !newOwner.isEmpty(); } void Updater::showUpdatesPopup() { m_oldUpdateList = m_updateList; KNotification *notify = new KNotification("ShowUpdates", 0, KNotification::Persistent); notify->setComponentName("apperd"); connect(notify, SIGNAL(action1Activated()), this, SLOT(reviewUpdates())); connect(notify, SIGNAL(action2Activated()), this, SLOT(installUpdates())); notify->setTitle(i18np("There is one new update", "There are %1 new updates", m_updateList.size())); QString text; foreach (const QString &packageId, m_updateList) { QString packageName = Transaction::packageName(packageId); if (text.length() + packageName.length() > 150) { text.append(QLatin1String(" ...")); break; } else if (!text.isNull()) { text.append(QLatin1String(", ")); } text.append(packageName); } notify->setText(text); QStringList actions; actions << i18n("Review"); if (m_hasAppletIconified) { actions << i18n("Install"); } notify->setActions(actions); // use of QSize does the right thing notify->setPixmap(QIcon::fromTheme("system-software-update").pixmap(KPK_ICON_SIZE, KPK_ICON_SIZE)); notify->sendEvent(); } bool Updater::updatePackages(const QStringList &packages, bool downloadOnly, const QString &icon, const QString &msg) { m_oldUpdateList = m_updateList; // Defaults to security PkTransaction *transaction = new PkTransaction; transaction->setProperty("DownloadOnly", downloadOnly); transaction->enableJobWatcher(true); transaction->updatePackages(packages, downloadOnly); connect(transaction, SIGNAL(finished(PkTransaction::ExitStatus)), this, SLOT(autoUpdatesFinished(PkTransaction::ExitStatus))); if (!icon.isNull()) { KNotification *notify; if (downloadOnly) { notify = new KNotification("DownloadingUpdates"); } else { notify = new KNotification("AutoInstallingUpdates"); } notify->setComponentName("apperd"); notify->setText(msg); // use of QSize does the right thing notify->setPixmap(QIcon::fromTheme(icon).pixmap(QSize(KPK_ICON_SIZE, KPK_ICON_SIZE))); notify->sendEvent(); } return true; } diff --git a/libapper/ApplicationsDelegate.cpp b/libapper/ApplicationsDelegate.cpp index 3278816..51b319c 100644 --- a/libapper/ApplicationsDelegate.cpp +++ b/libapper/ApplicationsDelegate.cpp @@ -1,343 +1,346 @@ /* * Copyright (C) 2007 Ivan Cukic * Copyright (C) 2008-2011 Daniel Nicoletti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * 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 Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ApplicationsDelegate.h" #include #include #include #include +#include +#include + #include "PackageModel.h" #include "PkIcons.h" #define UNIVERSAL_PADDING 4 #define FADE_LENGTH 16 using namespace PackageKit; ApplicationsDelegate::ApplicationsDelegate(QAbstractItemView *parent) : QStyledItemDelegate(parent), m_viewport(parent->viewport()), // loads it here to be faster when displaying items m_installIcon("go-down"), m_installString(i18n("Install")), m_removeIcon("edit-delete"), m_removeString(i18n("Remove")), m_undoIcon("edit-undo"), m_undoString(i18n("Deselect")), m_checkedIcon("dialog-ok"), m_checkable(false) { m_viewport->setAttribute(Qt::WA_Hover, true); QPushButton button, button2; button.setText(m_installString); button.setIcon(m_installIcon); button2.setText(m_removeString); button2.setIcon(m_removeIcon); m_buttonSize = button.sizeHint(); int width = qMax(button.sizeHint().width(), button2.sizeHint().width()); button.setText(m_undoString); width = qMax(width, button2.sizeHint().width()); m_buttonSize.setWidth(width); m_buttonIconSize = button.iconSize(); } void ApplicationsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return; } // Button height int btHeight = m_buttonSize.height() + UNIVERSAL_PADDING; if (index.column() == PackageModel::VersionCol || index.column() == PackageModel::CurrentVersionCol || index.column() == PackageModel::ArchCol || index.column() == PackageModel::OriginCol || index.column() == PackageModel::SizeCol) { QStyleOptionViewItem opt(option); if (opt.state & QStyle::State_HasFocus) { opt.state ^= QStyle::State_HasFocus; } painter->save(); QStyledItemDelegate::paint(painter, opt, index); painter->restore(); return; } else if (index.column() == PackageModel::NameCol) { bool leftToRight = (painter->layoutDirection() == Qt::LeftToRight); QStyleOptionViewItem opt1(option); if (opt1.state & QStyle::State_HasFocus) { opt1.state ^= QStyle::State_HasFocus; } QSize size = QStyledItemDelegate::sizeHint(opt1, index); if (leftToRight) { opt1.rect.setRight(size.width()); } else { opt1.rect.setLeft(option.rect.left() + (option.rect.width() - size.width())); } painter->save(); QStyledItemDelegate::paint(painter, opt1, index); painter->restore(); // a new option for the summary QStyleOptionViewItem opt(option); if (leftToRight) { opt.rect.setLeft(size.width() + 1); } else { opt.rect.setRight(option.rect.left() + (option.rect.width() - size.width()) - 1); } QPixmap pixmap(opt.rect.size()); pixmap.fill(Qt::transparent); QPainter p(&pixmap); if (!p.isActive()) { return; // TODO test if this fixes warnigns } p.translate(-opt.rect.topLeft()); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); opt.viewItemPosition = QStyleOptionViewItem::Middle; painter->save(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); painter->restore(); int left = opt.rect.left(); int width = opt.rect.width(); QString pkgSummary = index.data(PackageModel::SummaryRole).toString(); if (!pkgSummary.isEmpty()) { if (leftToRight) { pkgSummary.prepend(QLatin1String("- ")); } else { pkgSummary.append(QLatin1String(" -")); } } // store the original opacity qreal opa = p.opacity(); QStyleOptionViewItem local_option_normal(opt); QColor foregroundColor; p.setOpacity(0.75); if (opt.state.testFlag(QStyle::State_Selected)) { foregroundColor = opt.palette.color(QPalette::HighlightedText); } else { foregroundColor = opt.palette.color(QPalette::Text); } p.setFont(local_option_normal.font); p.setPen(foregroundColor); p.drawText(opt.rect, Qt::AlignVCenter | (leftToRight ? Qt::AlignLeft : Qt::AlignRight), pkgSummary); p.setOpacity(opa); QLinearGradient gradient; // Gradient part of the background - fading of the text at the end if (leftToRight) { gradient = QLinearGradient(left + width - UNIVERSAL_PADDING - FADE_LENGTH, 0, left + width - UNIVERSAL_PADDING, 0); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, Qt::transparent); } else { gradient = QLinearGradient(left + UNIVERSAL_PADDING, 0, left + UNIVERSAL_PADDING + FADE_LENGTH, 0); gradient.setColorAt(0, Qt::transparent); gradient.setColorAt(1, Qt::white); } QRect paintRect = opt.rect; p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.fillRect(paintRect, gradient); if (leftToRight) { gradient.setStart(left + width - (UNIVERSAL_PADDING) - FADE_LENGTH, 0); gradient.setFinalStop(left + width - (UNIVERSAL_PADDING), 0); } else { gradient.setStart(left + UNIVERSAL_PADDING + (UNIVERSAL_PADDING ), 0); gradient.setFinalStop(left + UNIVERSAL_PADDING + (UNIVERSAL_PADDING) + FADE_LENGTH, 0); } paintRect.setHeight(btHeight); p.fillRect(paintRect, gradient); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.end(); painter->drawPixmap(opt.rect.topLeft(), pixmap); return; } else if (index.column() == PackageModel::ActionCol) { bool pkgChecked = index.data(PackageModel::CheckStateRole).toBool(); QStyleOptionViewItem opt(option); if (opt.state & QStyle::State_HasFocus) { opt.state ^= QStyle::State_HasFocus; } // Do not draw if the line is not selected or the mouse is over it if (!(option.state & QStyle::State_MouseOver) && !(option.state & QStyle::State_Selected) && !pkgChecked) { QStyledItemDelegate::paint(painter, opt, index); return; } QStyledItemDelegate::paint(painter, opt, index); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); QStyleOptionButton optBt; optBt.rect = option.rect; Transaction::Info info; info = index.data(PackageModel::InfoRole).value(); bool pkgInstalled = (info == Transaction::InfoInstalled || info == Transaction::InfoCollectionInstalled); // Calculate the top of the button which is the item height - the button height size divided by 2 // this give us a little value which is the top and bottom margin optBt.rect.setLeft(optBt.rect.left() + UNIVERSAL_PADDING / 2); optBt.rect.setTop(optBt.rect.top() + ((btHeight - m_buttonSize.height()) / 2)); optBt.rect.setSize(m_buttonSize); // the width and height sizes of the button if (option.state & QStyle::State_Selected) { optBt.palette.setColor(QPalette::WindowText, option.palette.color(QPalette::HighlightedText)); } optBt.features = QStyleOptionButton::Flat; optBt.iconSize = m_buttonIconSize; if (pkgChecked) { optBt.state |= QStyle::State_Sunken | QStyle::State_Active | QStyle::State_Enabled;; } else { if (option.state & QStyle::State_MouseOver) { optBt.state |= QStyle::State_MouseOver; } optBt.state |= QStyle::State_Raised | QStyle::State_Active | QStyle::State_Enabled; } optBt.icon = pkgInstalled ? m_removeIcon : m_installIcon; optBt.text = pkgInstalled ? m_removeString : m_installString; style->drawControl(QStyle::CE_PushButton, &optBt, painter); return; } } bool ApplicationsDelegate::insideButton(const QRect &rect, const QPoint &pos) const { // kDebug() << rect << pos; if ((pos.x() >= rect.x() && (pos.x() <= rect.x() + rect.width())) && (pos.y() >= rect.y() && (pos.y() <= rect.y() + rect.height()))) { return true; } return false; } bool ApplicationsDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { bool setData = false; if (index.column() == PackageModel::ActionCol && event->type() == QEvent::MouseButtonPress) { setData = true; } const QWidget *widget = 0; if (const QStyleOptionViewItem *v = qstyleoption_cast(&option)) { widget = v->widget; } QStyle *style = widget ? widget->style() : QApplication::style(); // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) || (event->type() == QEvent::MouseButtonDblClick)) { QStyleOptionViewItem viewOpt(option); initStyleOption(&viewOpt, index); QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget); QMouseEvent *me = static_cast(event); if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) return false; // eat the double click events inside the check rect if (event->type() == QEvent::MouseButtonDblClick) return true; setData = true; } else if (event->type() == QEvent::KeyPress) { if (static_cast(event)->key() == Qt::Key_Space || static_cast(event)->key() == Qt::Key_Select) { setData = true; } } if (setData) { return model->setData(index, !index.data(PackageModel::CheckStateRole).toBool(), Qt::CheckStateRole); } return false; } void ApplicationsDelegate::setCheckable(bool checkable) { m_checkable = checkable; } QSize ApplicationsDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QSize size; // kDebug() << index; if (index.column() == PackageModel::ActionCol) { size = m_buttonSize; size.rheight() += UNIVERSAL_PADDING; size.rwidth() += UNIVERSAL_PADDING; } else { QFontMetrics metric = QFontMetrics(option.font); // Button size is always bigger than text (since it has text in it size.setHeight(m_buttonSize.height() + UNIVERSAL_PADDING); size.setWidth(metric.width(index.data().toString())); if (index.column() == PackageModel::NameCol) { if (m_checkable) { const QStyle *style = QApplication::style(); QRect rect = style->subElementRect(QStyle::SE_CheckBoxIndicator, &option); // Adds the icon size AND the checkbox size // [ x ] (icon) Text size.rwidth() += 4 * UNIVERSAL_PADDING + 46 + rect.width(); // return QStyledItemDelegate::sizeHint(option, index); } else { // Adds the icon size size.rwidth() += 3 * UNIVERSAL_PADDING + 44; } } else { size.rwidth() += 2 * UNIVERSAL_PADDING; } } return size; } #include "ApplicationsDelegate.moc" diff --git a/libapper/ApplicationsDelegate.h b/libapper/ApplicationsDelegate.h index 4c95bb4..1eb0a47 100644 --- a/libapper/ApplicationsDelegate.h +++ b/libapper/ApplicationsDelegate.h @@ -1,65 +1,63 @@ /* * Copyright (C) 2007 Ivan Cukic * Copyright (C) 2008-2011 Daniel Nicoletti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * 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 Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef APPLICATIONS_DELEGATE_H #define APPLICATIONS_DELEGATE_H -#include -#include #include -#include +#include /** * Delegate for displaying the packages */ class Q_DECL_EXPORT ApplicationsDelegate: public QStyledItemDelegate { Q_OBJECT public: explicit ApplicationsDelegate(QAbstractItemView *parent); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); void setCheckable(bool checkable); private: bool insideButton(const QRect &rect, const QPoint &pos) const; QWidget *m_viewport; - KIcon m_packageIcon; - KIcon m_installIcon; + QIcon m_packageIcon; + QIcon m_installIcon; QString m_installString; - KIcon m_removeIcon; + QIcon m_removeIcon; QString m_removeString; - KIcon m_undoIcon; + QIcon m_undoIcon; QString m_undoString; - KIcon m_checkedIcon; + QIcon m_checkedIcon; QSize m_buttonSize; QSize m_buttonIconSize; bool m_checkable; }; #endif diff --git a/libapper/ChangesDelegate.cpp b/libapper/ChangesDelegate.cpp index 88e0e7c..fe08efb 100644 --- a/libapper/ChangesDelegate.cpp +++ b/libapper/ChangesDelegate.cpp @@ -1,434 +1,436 @@ /* * Copyright (C) 2007 Ivan Cukic * Copyright (C) 2008-2011 Daniel Nicoletti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * 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 Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ChangesDelegate.h" #include #include #include #include #include #include #include +#include + #include "PackageModel.h" #include "PkIcons.h" #include #define FAV_ICON_SIZE 24 #define EMBLEM_ICON_SIZE 8 #define UNIVERSAL_PADDING 4 #define FADE_LENGTH 16 #define MAIN_ICON_SIZE 32 using namespace PackageKit; ChangesDelegate::ChangesDelegate(QAbstractItemView *parent) : KExtendableItemDelegate(parent), m_viewport(parent->viewport()), // loads it here to be faster when displaying items m_packageIcon("package"), m_collectionIcon("package-orign"), m_installIcon("dialog-cancel"), m_installString(i18n("Do not Install")), m_removeIcon("dialog-cancel"), m_removeString(i18n("Do not Remove")), m_undoIcon("edit-undo"), m_undoString(i18n("Deselect")), m_checkedIcon("dialog-ok-apply") { // maybe rename or copy it to package-available if (QApplication::isRightToLeft()) { setExtendPixmap(SmallIcon("arrow-left")); } else { setExtendPixmap(SmallIcon("arrow-right")); } setContractPixmap(SmallIcon("arrow-down")); // store the size of the extend pixmap to know how much we should move m_extendPixmapWidth = SmallIcon("arrow-right").size().width(); QPushButton button, button2; button.setText(m_installString); button.setIcon(m_installIcon); button2.setText(m_removeString); button2.setIcon(m_removeIcon); m_buttonSize = button.sizeHint(); int width = qMax(button.sizeHint().width(), button2.sizeHint().width()); button.setText(m_undoString); width = qMax(width, button2.sizeHint().width()); m_buttonSize.setWidth(width); m_buttonIconSize = button.iconSize(); } void ChangesDelegate::paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const + const QStyleOptionViewItem &option, + const QModelIndex &index) const { if (!index.isValid()) { return; } bool leftToRight = (painter->layoutDirection() == Qt::LeftToRight); - QStyleOptionViewItemV4 opt(option); + QStyleOptionViewItem opt(option); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); painter->save(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); painter->restore(); //grab the package from the index pointer QString pkgName = index.data(PackageModel::NameRole).toString(); QString pkgSummary = index.data(PackageModel::SummaryRole).toString(); QString pkgVersion = index.data(PackageModel::VersionRole).toString(); QString pkgArch = index.data(PackageModel::ArchRole).toString(); // QString pkgIconPath = index.data(PackageModel::IconPathRole).toString(); bool pkgChecked = index.data(PackageModel::CheckStateRole).toBool(); bool pkgCheckable = !index.data(Qt::CheckStateRole).isNull(); Transaction::Info info; info = index.data(PackageModel::InfoRole).value(); bool pkgInstalled = (info == Transaction::InfoInstalled || info == Transaction::InfoCollectionInstalled); bool pkgCollection = (info == Transaction::InfoCollectionInstalled || info == Transaction::InfoCollectionAvailable); QIcon emblemIcon; if (pkgCheckable) { // update kind icon emblemIcon = index.data(PackageModel::IconRole).value(); } else { emblemIcon = m_checkedIcon; } // pain the background (checkbox and the extender) if (m_extendPixmapWidth) { KExtendableItemDelegate::paint(painter, opt, index); } int leftCount; if (leftToRight) { opt.rect.setLeft(option.rect.left() + m_extendPixmapWidth + UNIVERSAL_PADDING); leftCount = opt.rect.left() + UNIVERSAL_PADDING; } else { opt.rect.setRight(option.rect.right() - m_extendPixmapWidth - UNIVERSAL_PADDING); leftCount = opt.rect.width() - (UNIVERSAL_PADDING + MAIN_ICON_SIZE); } int left = opt.rect.left(); int top = opt.rect.top(); int width = opt.rect.width(); QStyleOptionButton optBt; optBt.rect = opt.rect; if (pkgCheckable) { optBt.rect = style->subElementRect(QStyle::SE_CheckBoxIndicator, &optBt); // Count the checkbox size if (leftToRight) { leftCount += optBt.rect.width(); } else { leftCount -= optBt.rect.width(); } } else if ((option.state & QStyle::State_MouseOver) || (option.state & QStyle::State_Selected) || !pkgChecked) { if (leftToRight) { optBt.rect.setLeft(left + width - (m_buttonSize.width() + UNIVERSAL_PADDING)); width -= m_buttonSize.width() + UNIVERSAL_PADDING; } else { optBt.rect.setLeft(left + UNIVERSAL_PADDING); left += m_buttonSize.width() + UNIVERSAL_PADDING; } // Calculate the top of the button which is the item height - the button height size divided by 2 // this give us a little value which is the top and bottom margin optBt.rect.setTop(optBt.rect.top() + ((calcItemHeight(option) - m_buttonSize.height()) / 2)); optBt.rect.setSize(m_buttonSize); // the width and height sizes of the button optBt.features = QStyleOptionButton::Flat; optBt.iconSize = m_buttonIconSize; optBt.icon = pkgInstalled ? m_removeIcon : m_installIcon; optBt.text = pkgInstalled ? m_removeString : m_installString; if (pkgChecked) { optBt.state |= QStyle::State_Raised | QStyle::State_Active | QStyle::State_Enabled;; } else { if ((option.state & QStyle::State_MouseOver) && !(option.state & QStyle::State_Selected)) { optBt.state |= QStyle::State_MouseOver; } optBt.state |= QStyle::State_Sunken | QStyle::State_Active | QStyle::State_Enabled; } style->drawControl(QStyle::CE_PushButton, &optBt, painter); } // QAbstractItemView *view = qobject_cast(parent()); // QPoint pos = view->viewport()->mapFromGlobal(QCursor::pos()); // kDebug() << pos; // selects the mode to paint the icon based on the info field QIcon::Mode iconMode = QIcon::Normal; if (option.state & QStyle::State_MouseOver) { iconMode = QIcon::Active; } QColor foregroundColor = (option.state.testFlag(QStyle::State_Selected))? option.palette.color(QPalette::HighlightedText):option.palette.color(QPalette::Text); // Painting main column QStyleOptionViewItem local_option_title(option); QStyleOptionViewItem local_option_normal(option); local_option_normal.font.setPointSize(local_option_normal.font.pointSize() - 1); QPixmap pixmap(option.rect.size()); pixmap.fill(Qt::transparent); QPainter p(&pixmap); p.translate(-option.rect.topLeft()); // Main icon QIcon icon; if (pkgCollection) { icon = m_collectionIcon; } else { icon = PkIcons::getIcon(index.data(PackageModel::IconRole).toString(), QString()); if (icon.isNull()) { icon = m_packageIcon; } } // if (pkgIconPath.isEmpty()) { // icon = pkgCollection ? m_collectionIcon : m_packageIcon; // } else { // icon = PkIcons::getIcon(pkgIconPath, "package"); // } int iconSize = calcItemHeight(option) - 2 * UNIVERSAL_PADDING; icon.paint(&p, leftCount, top + UNIVERSAL_PADDING, iconSize, iconSize, Qt::AlignCenter, iconMode); int textWidth; if (leftToRight) { // add the main icon leftCount += iconSize + UNIVERSAL_PADDING; textWidth = width - (leftCount - left); } else { leftCount -= UNIVERSAL_PADDING; textWidth = leftCount - left; leftCount = left; } // Painting // Text const int itemHeight = calcItemHeight(option); p.setPen(foregroundColor); // compose the top line // Collections does not have version and arch if (option.state & QStyle::State_MouseOver && !pkgCollection) { //! pkgName = pkgName + " - " + pkgVersion + (pkgArch.isNull() ? NULL : " (" + pkgArch + ')'); } // draw the top line int topTextHeight = QFontInfo(local_option_title.font).pixelSize(); p.setFont(local_option_title.font); p.drawText(leftCount, top, textWidth, topTextHeight + UNIVERSAL_PADDING, Qt::AlignVCenter | Qt::AlignLeft, pkgName); // draw the bottom line iconSize = topTextHeight + UNIVERSAL_PADDING; if (pkgCheckable || pkgInstalled) { emblemIcon.paint(&p, leftToRight ? leftCount : (textWidth + left) - iconSize, top + topTextHeight + UNIVERSAL_PADDING, iconSize, iconSize, Qt::AlignVCenter | Qt::AlignHCenter, iconMode); } // store the original opacity qreal opa = p.opacity(); if (!(option.state & QStyle::State_MouseOver) && !(option.state & QStyle::State_Selected)) { p.setOpacity(opa / 2.5); } p.setFont(local_option_normal.font); p.drawText(leftToRight ? leftCount + iconSize + UNIVERSAL_PADDING : left - UNIVERSAL_PADDING, top + itemHeight / 2, textWidth - iconSize, QFontInfo(local_option_normal.font).pixelSize() + UNIVERSAL_PADDING, Qt::AlignTop | Qt::AlignLeft, pkgSummary); p.setOpacity(opa); QLinearGradient gradient; // Gradient part of the background - fading of the text at the end if (leftToRight) { gradient = QLinearGradient(left + width - UNIVERSAL_PADDING - FADE_LENGTH, 0, left + width - UNIVERSAL_PADDING, 0); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, Qt::transparent); } else { gradient = QLinearGradient(left + UNIVERSAL_PADDING, 0, left + UNIVERSAL_PADDING + FADE_LENGTH, 0); gradient.setColorAt(0, Qt::transparent); gradient.setColorAt(1, Qt::white); } QRect paintRect = option.rect; p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.fillRect(paintRect, gradient); if (leftToRight) { gradient.setStart(left + width - (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE) - FADE_LENGTH, 0); gradient.setFinalStop(left + width - (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE), 0); } else { gradient.setStart(left + UNIVERSAL_PADDING + (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE), 0); gradient.setFinalStop(left + UNIVERSAL_PADDING + (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE) + FADE_LENGTH, 0); } paintRect.setHeight(UNIVERSAL_PADDING + MAIN_ICON_SIZE / 2); p.fillRect(paintRect, gradient); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.end(); painter->drawPixmap(option.rect.topLeft(), pixmap); } int ChangesDelegate::calcItemHeight(const QStyleOptionViewItem &option) const { // Painting main column QStyleOptionViewItem local_option_title(option); QStyleOptionViewItem local_option_normal(option); local_option_normal.font.setPointSize(local_option_normal.font.pointSize() - 1); int textHeight = QFontInfo(local_option_title.font).pixelSize() + QFontInfo(local_option_normal.font).pixelSize(); return textHeight + 3 * UNIVERSAL_PADDING; } bool ChangesDelegate::insideButton(const QRect &rect, const QPoint &pos) const { // kDebug() << rect << pos; if ((pos.x() >= rect.x() && (pos.x() <= rect.x() + rect.width())) && (pos.y() >= rect.y() && (pos.y() <= rect.y() + rect.height()))) { return true; } return false; } bool ChangesDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { Q_UNUSED(option) if (event->type() == QEvent::MouseButtonRelease) { QAbstractItemView *view = qobject_cast(parent()); QPoint point = m_viewport->mapFromGlobal(QCursor::pos()); QTreeView *tree = qobject_cast(parent()); if (tree) { point.ry() -= tree->header()->size().height(); } bool leftToRight = QApplication::isLeftToRight(); QStyleOptionButton optBt; optBt.rect = option.rect; if (leftToRight) { optBt.rect.setLeft(option.rect.left() + option.rect.width() - (m_buttonSize.width() + UNIVERSAL_PADDING)); } else { optBt.rect.setLeft(option.rect.left() + UNIVERSAL_PADDING); } // Calculate the top of the button which is the item height - the button height size divided by 2 // this give us a little value which is the top and bottom margin optBt.rect.setTop(optBt.rect.top() + ((calcItemHeight(option) - m_buttonSize.height()) / 2)); optBt.rect.setSize(m_buttonSize); kDebug() << point << option.rect.left() << option << insideButton(optBt.rect, point); // kDebug() << view->visualRect(index); if (insideButton(optBt.rect, point)) { return model->setData(index, !index.data(PackageModel::CheckStateRole).toBool(), Qt::CheckStateRole); } QRect rect = view->visualRect(index); if (QApplication::isRightToLeft()) { if ((rect.width() - point.x()) <= m_extendPixmapWidth) { emit showExtendItem(index); } } else if (point.x() <= m_extendPixmapWidth) { emit showExtendItem(index); } } // We need move the option rect left because KExtendableItemDelegate // drew the extendPixmap - QStyleOptionViewItemV4 opt(option); + QStyleOptionViewItem opt(option); if (QApplication::isRightToLeft()) { opt.rect.setRight(option.rect.right() - m_extendPixmapWidth); } else { opt.rect.setLeft(option.rect.left() + m_extendPixmapWidth); } // When the exterder is shown the height get compromised, // this makes sure the check box is always known opt.rect.setHeight(calcItemHeight(option)); return KExtendableItemDelegate::editorEvent(event, model, opt, index); } void ChangesDelegate::setExtendPixmapWidth(int width) { m_extendPixmapWidth = width; } void ChangesDelegate::setViewport(QWidget *viewport) { m_viewport = viewport; } QSize ChangesDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const { int width = (index.column() == 0) ? index.data(Qt::SizeHintRole).toSize().width() : FAV_ICON_SIZE + 2 * UNIVERSAL_PADDING; QSize ret(KExtendableItemDelegate::sizeHint(option, index)); // remove the default size of the index ret -= QStyledItemDelegate::sizeHint(option, index); ret.rheight() += calcItemHeight(option); ret.rwidth() += width; return ret; } #include "ChangesDelegate.moc" diff --git a/libapper/ChangesDelegate.h b/libapper/ChangesDelegate.h index 45e6bc2..76bd8fc 100644 --- a/libapper/ChangesDelegate.h +++ b/libapper/ChangesDelegate.h @@ -1,71 +1,67 @@ /* * Copyright (C) 2007 Ivan Cukic * Copyright (C) 2008-2011 Daniel Nicoletti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * 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 Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CHANGES_DELEGATE_H #define CHANGES_DELEGATE_H -#include -#include #include -#include - /** * Delegate for displaying the packages */ class Q_DECL_EXPORT ChangesDelegate: public KExtendableItemDelegate { Q_OBJECT public: explicit ChangesDelegate(QAbstractItemView *parent); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); void setExtendPixmapWidth(int width); void setViewport(QWidget *viewport); Q_SIGNALS: void showExtendItem(const QModelIndex &index); private: int calcItemHeight(const QStyleOptionViewItem &option) const; bool insideButton(const QRect &rect, const QPoint &pos) const; QWidget *m_viewport; - KIcon m_packageIcon; - KIcon m_collectionIcon; - KIcon m_installIcon; + QIcon m_packageIcon; + QIcon m_collectionIcon; + QIcon m_installIcon; QString m_installString; - KIcon m_removeIcon; + QIcon m_removeIcon; QString m_removeString; - KIcon m_undoIcon; + QIcon m_undoIcon; QString m_undoString; - KIcon m_checkedIcon; + QIcon m_checkedIcon; int m_extendPixmapWidth; QSize m_buttonSize; QSize m_buttonIconSize; }; #endif diff --git a/libapper/InfoWidget.cpp b/libapper/InfoWidget.cpp index 4a3d60f..3070f10 100644 --- a/libapper/InfoWidget.cpp +++ b/libapper/InfoWidget.cpp @@ -1,80 +1,80 @@ /*************************************************************************** * Copyright (C) 2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "InfoWidget.h" #include "ui_InfoWidget.h" #include #include InfoWidget::InfoWidget(QWidget *parent) : QWidget(parent), ui(new Ui::InfoWidget) { ui->setupUi(this); - ui->iconL->setPixmap(KIcon("dialog-warning").pixmap(128, 128)); + ui->iconL->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(128, 128)); } InfoWidget::~InfoWidget() { delete ui; } -void InfoWidget::setIcon(const KIcon &icon) +void InfoWidget::setIcon(const QIcon &icon) { ui->iconL->setPixmap(icon.pixmap(128, 128)); } void InfoWidget::setDescription(const QString &description) { ui->descriptionL->setText(description); } void InfoWidget::setDetails(const QString &details) { if (!details.isEmpty()) { - KTextBrowser *browser = new KTextBrowser(this); + auto browser = new QTextBrowser(this); browser->setFrameShape(QFrame::NoFrame); browser->setFrameShadow(QFrame::Plain); browser->setStyleSheet("QTextEdit {\nbackground-color: transparent;\n};"); browser->setText(details); ui->descriptionLayout->addWidget(browser); ui->descriptionLayout->insertSpacing(0, 20); } } void InfoWidget::addWidget(QWidget *widget) { if (widget) { ui->descriptionLayout->insertSpacing(0, 20); ui->descriptionLayout->addWidget(widget); } } void InfoWidget::reset() { - ui->iconL->setPixmap(KIcon("dialog-information").pixmap(128, 128)); + ui->iconL->setPixmap(QIcon::fromTheme("dialog-information").pixmap(128, 128)); setWindowTitle(""); setDescription(""); setDetails(""); } #include "InfoWidget.moc" diff --git a/libapper/InfoWidget.h b/libapper/InfoWidget.h index 7b35d27..2d54a8b 100644 --- a/libapper/InfoWidget.h +++ b/libapper/InfoWidget.h @@ -1,48 +1,48 @@ /*************************************************************************** * Copyright (C) 2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef INFO_WIDGET_H #define INFO_WIDGET_H #include -#include +#include namespace Ui { class InfoWidget; } class Q_DECL_EXPORT InfoWidget : public QWidget { Q_OBJECT public: explicit InfoWidget(QWidget *parent = 0); ~InfoWidget(); void setDescription(const QString &description); - void setIcon(const KIcon &icon); + void setIcon(const QIcon &icon); void setDetails(const QString &details); void addWidget(QWidget *widget); void reset(); private: Ui::InfoWidget *ui; }; #endif diff --git a/libapper/PkIcons.cpp b/libapper/PkIcons.cpp index 3e55bfa..a66c0b0 100644 --- a/libapper/PkIcons.cpp +++ b/libapper/PkIcons.cpp @@ -1,333 +1,334 @@ /*************************************************************************** * Copyright (C) 2008 by Trever Fischer * * wm161@wm161.net * * Copyright (C) 2009-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include "PkIcons.h" #include -#include #include #include using namespace PackageKit; bool PkIcons::init = false; QHash PkIcons::cache = QHash(); void PkIcons::configure() { - KGlobal::dirs()->addResourceDir("xdgdata-pixmap", "/usr/share/app-info/icons/", "/usr/share/app-install/icons/"); - KIconLoader::global()->reconfigure("apper"); + QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() + + QStringList{"xdgdata-pixmap", "/usr/share/app-info/icons/", "/usr/share/app-install/icons/"}); +// KStandardDirs:: KGlobal::dirs()->addResourceDir("xdgdata-pixmap", "/usr/share/app-info/icons/", "/usr/share/app-install/icons/"); +// KIconLoader::global()->reconfigure("apper"); PkIcons::init = true; } QIcon PkIcons::getIcon(const QString &name) { if (!PkIcons::init) { PkIcons::configure(); } return QIcon::fromTheme(name); } QIcon PkIcons::getIcon(const QString &name, const QString &defaultName) { if (!PkIcons::init) { PkIcons::configure(); } if (name.isEmpty()) { return QIcon(); } bool isNull; isNull = KIconLoader::global()->iconPath(name, KIconLoader::NoGroup, true).isEmpty(); if (isNull && !defaultName.isNull()) { return QIcon::fromTheme(defaultName); } else if (isNull) { return QIcon(); } return QIcon::fromTheme(name); } QString PkIcons::statusIconName(Transaction::Status status) { if (!PkIcons::init) { PkIcons::configure(); } switch (status) { case Transaction::StatusUnknown : return "help-browser"; case Transaction::StatusCancel : case Transaction::StatusCleanup : return "package-clean-up"; case Transaction::StatusCommit : return "package-working";//TODO needs a better icon case Transaction::StatusDepResolve : return "package-info"; case Transaction::StatusDownloadChangelog : case Transaction::StatusDownloadFilelist : case Transaction::StatusDownloadGroup : case Transaction::StatusDownloadPackagelist : return "refresh-cache"; case Transaction::StatusDownload : return "package-download"; case Transaction::StatusDownloadRepository : case Transaction::StatusDownloadUpdateinfo : return "refresh-cache"; case Transaction::StatusFinished : return "package-clean-up"; case Transaction::StatusGeneratePackageList : return "refresh-cache"; case Transaction::StatusWaitingForLock : return "dialog-password"; case Transaction::StatusWaitingForAuth : return "dialog-password";//IMPROVE ME case Transaction::StatusInfo : return "package-info"; case Transaction::StatusInstall : return "kpk-package-add"; case Transaction::StatusLoadingCache : return "refresh-cache"; case Transaction::StatusObsolete : return "package-clean-up"; case Transaction::StatusQuery : return "search-package"; case Transaction::StatusRefreshCache : return "refresh-cache"; case Transaction::StatusRemove : return "package-removed"; case Transaction::StatusRepackaging : return "package-clean-up"; case Transaction::StatusRequest : return "search-package"; case Transaction::StatusRunning : return "package-working"; case Transaction::StatusScanApplications : return "search-package"; case Transaction::StatusSetup : return "package-working"; case Transaction::StatusSigCheck : case Transaction::StatusTestCommit : return "package-info";//TODO needs a better icon case Transaction::StatusUpdate : return "package-update"; case Transaction::StatusWait : return "package-wait"; case Transaction::StatusScanProcessList : return "package-info"; case Transaction::StatusCheckExecutableFiles : return "package-info"; case Transaction::StatusCheckLibraries : return "package-info"; case Transaction::StatusCopyFiles : return "package-info"; } kDebug() << "status icon unrecognised: " << status; return "help-browser"; } QIcon PkIcons::statusIcon(Transaction::Status status) { return QIcon::fromTheme(PkIcons::statusIconName(status)); } QString PkIcons::statusAnimation(Transaction::Status status) { if (!PkIcons::init) { PkIcons::configure(); } switch (status) { case Transaction::StatusUnknown : return "help-browser"; case Transaction::StatusCancel : case Transaction::StatusCleanup : return "pk-cleaning-up"; case Transaction::StatusCommit : case Transaction::StatusDepResolve : return "pk-testing"; case Transaction::StatusDownloadChangelog : case Transaction::StatusDownloadFilelist : case Transaction::StatusDownloadGroup : case Transaction::StatusDownloadPackagelist : return "pk-refresh-cache"; case Transaction::StatusDownload : return "pk-downloading"; case Transaction::StatusDownloadRepository : case Transaction::StatusDownloadUpdateinfo : return "pk-refresh-cache"; case Transaction::StatusFinished : return "pk-cleaning-up"; case Transaction::StatusGeneratePackageList : return "pk-searching"; case Transaction::StatusWaitingForLock : return "pk-waiting"; case Transaction::StatusInfo : return "package-working"; case Transaction::StatusInstall : return "pk-installing"; case Transaction::StatusLoadingCache : return "pk-refresh-cache"; case Transaction::StatusObsolete : return "pk-cleaning-up"; case Transaction::StatusQuery : return "pk-searching"; case Transaction::StatusRefreshCache : return "pk-refresh-cache"; case Transaction::StatusRemove : return "package-removed";//TODO do the animation case Transaction::StatusRepackaging : return "pk-searching"; case Transaction::StatusRequest : return "process-working"; case Transaction::StatusRunning : return "pk-testing"; case Transaction::StatusScanApplications : return "pk-searching"; case Transaction::StatusSetup : return "pk-searching"; case Transaction::StatusSigCheck : return "package-info"; case Transaction::StatusTestCommit : return "pk-testing"; case Transaction::StatusUpdate : return "pk-installing"; case Transaction::StatusWait : return "pk-waiting"; case Transaction::StatusWaitingForAuth : return "dialog-password"; case Transaction::StatusScanProcessList : return "utilities-system-monitor"; default : kDebug() << "status icon unrecognised: " << status; return "help-browser"; } } QString PkIcons::actionIconName(Transaction::Role role) { if (!PkIcons::init) { PkIcons::configure(); } switch (role) { case Transaction::RoleUnknown : return "applications-other"; case Transaction::RoleAcceptEula : return "package-info"; case Transaction::RoleCancel : return "process-stop"; case Transaction::RoleDownloadPackages : return "package-download"; case Transaction::RoleGetCategories : return "package-info"; case Transaction::RoleDependsOn : return "package-info"; case Transaction::RoleGetDetails : return "package-info"; case Transaction::RoleGetDetailsLocal : return "package-info"; case Transaction::RoleGetDistroUpgrades : return "distro-upgrade"; case Transaction::RoleGetFiles : return "search-package"; case Transaction::RoleGetFilesLocal : return "search-package"; case Transaction::RoleGetOldTransactions : return "package-info"; case Transaction::RoleGetPackages : return "package-packages"; case Transaction::RoleGetRepoList : return "package-orign"; case Transaction::RoleRequiredBy : return "package-info"; case Transaction::RoleGetUpdateDetail : return "package-info"; case Transaction::RoleGetUpdates : return "package-info"; case Transaction::RoleInstallFiles : return "package-installed"; case Transaction::RoleInstallPackages : return "package-installed"; case Transaction::RoleInstallSignature : return "package-installed"; case Transaction::RoleRefreshCache : return "refresh-cache"; case Transaction::RoleRemovePackages : return "package-removed"; case Transaction::RoleRepoEnable : return "package-orign"; case Transaction::RoleRepoSetData : return "package-orign"; case Transaction::RoleRepoRemove : return "package-orign"; case Transaction::RoleResolve : return "search-package"; case Transaction::RoleSearchDetails : return "search-package"; case Transaction::RoleSearchFile : return "search-package"; case Transaction::RoleSearchGroup : return "search-package"; case Transaction::RoleSearchName : return "search-package"; case Transaction::RoleUpdatePackages : return "package-update"; case Transaction::RoleWhatProvides : return "search-package"; case Transaction::RoleRepairSystem : return "package-rollback"; } kDebug() << "action unrecognised: " << role; return "applications-other"; } QIcon PkIcons::actionIcon(Transaction::Role role) { return QIcon::fromTheme(actionIconName(role)); } QIcon PkIcons::groupsIcon(Transaction::Group group) { if (!PkIcons::init) { PkIcons::configure(); } switch (group) { case Transaction::GroupUnknown : return QIcon::fromTheme("unknown"); case Transaction::GroupAccessibility : return QIcon::fromTheme("preferences-desktop-accessibility"); case Transaction::GroupAccessories : return QIcon::fromTheme("applications-accessories"); case Transaction::GroupAdminTools : return QIcon::fromTheme("dialog-password"); case Transaction::GroupCommunication : return QIcon::fromTheme("network-workgroup");//FIXME case Transaction::GroupDesktopGnome : return QIcon::fromTheme("kpk-desktop-gnome"); case Transaction::GroupDesktopKde : return QIcon::fromTheme("kde"); case Transaction::GroupDesktopOther : return QIcon::fromTheme("user-desktop"); case Transaction::GroupDesktopXfce : return QIcon::fromTheme("kpk-desktop-xfce"); case Transaction::GroupDocumentation : return QIcon::fromTheme("accessories-dictionary");//FIXME case Transaction::GroupEducation : return QIcon::fromTheme("applications-education"); case Transaction::GroupElectronics : return QIcon::fromTheme("media-flash"); case Transaction::GroupFonts : return QIcon::fromTheme("preferences-desktop-font"); case Transaction::GroupGames : return QIcon::fromTheme("applications-games"); case Transaction::GroupGraphics : return QIcon::fromTheme("applications-graphics"); case Transaction::GroupInternet : return QIcon::fromTheme("applications-internet"); case Transaction::GroupLegacy : return QIcon::fromTheme("media-floppy"); case Transaction::GroupLocalization : return QIcon::fromTheme("applications-education-language"); case Transaction::GroupMaps : return QIcon::fromTheme("Maps");//FIXME case Transaction::GroupCollections : return QIcon::fromTheme("package-orign"); case Transaction::GroupMultimedia : return QIcon::fromTheme("applications-multimedia"); case Transaction::GroupNetwork : return QIcon::fromTheme("network-wired"); case Transaction::GroupOffice : return QIcon::fromTheme("applications-office"); case Transaction::GroupOther : return QIcon::fromTheme("applications-other"); case Transaction::GroupPowerManagement : return QIcon::fromTheme("battery"); case Transaction::GroupProgramming : return QIcon::fromTheme("applications-development"); case Transaction::GroupPublishing : return QIcon::fromTheme("accessories-text-editor"); case Transaction::GroupRepos : return QIcon::fromTheme("application-x-compressed-tar"); case Transaction::GroupScience : return QIcon::fromTheme("applications-science"); case Transaction::GroupSecurity : return QIcon::fromTheme("security-high"); case Transaction::GroupServers : return QIcon::fromTheme("network-server"); case Transaction::GroupSystem : return QIcon::fromTheme("applications-system"); case Transaction::GroupVirtualization : return QIcon::fromTheme("cpu"); case Transaction::GroupVendor : return QIcon::fromTheme("application-certificate"); case Transaction::GroupNewest : return QIcon::fromTheme("dialog-information"); } kDebug() << "group unrecognised: " << group; return QIcon::fromTheme("unknown"); } QIcon PkIcons::packageIcon(Transaction::Info info) { if (!PkIcons::init) { PkIcons::configure(); } switch (info) { case Transaction::InfoBugfix : return QIcon::fromTheme("script-error"); case Transaction::InfoEnhancement : return QIcon::fromTheme("ktip"); case Transaction::InfoImportant : return QIcon::fromTheme("security-medium"); case Transaction::InfoLow : return QIcon::fromTheme("security-high"); case Transaction::InfoSecurity : return QIcon::fromTheme("security-low"); case Transaction::InfoNormal : return QIcon::fromTheme("emblem-new"); case Transaction::InfoBlocked : return QIcon::fromTheme("dialog-cancel"); case Transaction::InfoAvailable : return QIcon::fromTheme("package-download"); case Transaction::InfoInstalled : return QIcon::fromTheme("package-installed"); default : return QIcon::fromTheme("package"); } } QString PkIcons::restartIconName(Transaction::Restart type) { if (!PkIcons::init) { PkIcons::configure(); } // These names MUST be standard icons, otherwise KStatusNotifierItem // will not be able to load them switch (type) { case Transaction::RestartSecuritySystem : case Transaction::RestartSystem : return "system-reboot"; case Transaction::RestartSecuritySession : case Transaction::RestartSession : return "system-log-out"; case Transaction::RestartApplication : return "process-stop"; case Transaction::RestartNone : case Transaction::RestartUnknown : break; } return ""; } QIcon PkIcons::restartIcon(Transaction::Restart type) { return PkIcons::getIcon(restartIconName(type)); } QIcon PkIcons::getPreloadedIcon(const QString &name) { if (!PkIcons::init) { PkIcons::configure(); } kDebug() << KIconLoader::global()->iconPath(name, KIconLoader::NoGroup, true); QIcon icon; icon.addPixmap(QIcon::fromTheme(name).pixmap(48, 48)); return icon; } QString PkIcons::lastCacheRefreshIconName(uint lastTime) { unsigned long fifteen = 60 * 60 * 24 * 15; unsigned long tirty = 60 * 60 * 24 * 30; if (lastTime != UINT_MAX && lastTime < fifteen) { return QLatin1String("security-high"); } else if (lastTime != UINT_MAX && lastTime > fifteen && lastTime < tirty) { return QLatin1String("security-medium"); } return QLatin1String("security-low"); } diff --git a/libapper/PkTransaction.cpp b/libapper/PkTransaction.cpp index c070810..20681bf 100644 --- a/libapper/PkTransaction.cpp +++ b/libapper/PkTransaction.cpp @@ -1,800 +1,800 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include "PkTransaction.h" #include #include #include #include #include #include #include #include #include #include #include "Enum.h" #include "PkStrings.h" #include "RepoSig.h" #include "LicenseAgreement.h" #include "PkIcons.h" #include "ApplicationLauncher.h" #include "PackageModel.h" #include "Requirements.h" #include "PkTransactionProgressModel.h" #include "PkTransactionWidget.h" class PkTransactionPrivate { public: bool allowDeps; bool jobWatcher; bool handlingActionRequired; bool showingError; //This might replace the above qulonglong downloadSizeRemaining; PkTransaction::ExitStatus exitStatus; Transaction::Status status; Transaction::TransactionFlags flags; Transaction::Role originalRole; Transaction::Error error; Transaction::Role role; QStringList packages; ApplicationLauncher *launcher; QStringList files; QStringList newPackages; PackageModel *simulateModel; PkTransactionProgressModel *progressModel; QWidget *parentWindow; QDBusObjectPath tid; Transaction *transaction; }; PkTransaction::PkTransaction(QObject *parent) : QObject(parent), d(new PkTransactionPrivate) { // for sanity we are finished till some transaction is set d->allowDeps = false; d->jobWatcher = false; d->handlingActionRequired = false; d->showingError = false; d->downloadSizeRemaining = 0; d->exitStatus = Success; d->status = Transaction::StatusUnknown; // for sanity we are trusted till an error is given and the user accepts d->flags = Transaction::TransactionFlagOnlyTrusted; d->originalRole = Transaction::RoleUnknown; d->role = Transaction::RoleUnknown; d->error = Transaction::ErrorUnknown; d->launcher = 0; d->simulateModel = 0; d->progressModel = new PkTransactionProgressModel(this); d->parentWindow = qobject_cast(parent); d->transaction = 0; } PkTransaction::~PkTransaction() { // DO NOT disconnect the transaction here, // it might not exist when this happen delete d; } void PkTransaction::installFiles(const QStringList &files) { // if (Daemon::global()->roles() & Transaction::RoleInstallFiles) { d->originalRole = Transaction::RoleInstallFiles; d->files = files; d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; setupTransaction(Daemon::installFiles(files, d->flags)); // } else { // showError(i18n("Current backend does not support installing files."), i18n("Error")); // } } void PkTransaction::installPackages(const QStringList &packages) { // if (Daemon::global()->roles() & Transaction::RoleInstallPackages) { d->originalRole = Transaction::RoleInstallPackages; d->packages = packages; d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; setupTransaction(Daemon::installPackages(d->packages, d->flags)); // } else { // showError(i18n("Current backend does not support installing packages."), i18n("Error")); // } } void PkTransaction::removePackages(const QStringList &packages) { // if (Daemon::global()->roles() & Transaction::RoleRemovePackages) { d->originalRole = Transaction::RoleRemovePackages; d->allowDeps = true; // *was* false, Default to avoid dependencies removal unless simulate says so, except for https://bugs.kde.org/show_bug.cgi?id=315063 d->packages = packages; d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; setupTransaction(Daemon::removePackages(d->packages, d->allowDeps, AUTOREMOVE, d->flags)); // } else { // showError(i18n("The current backend does not support removing packages."), i18n("Error")); // } } void PkTransaction::updatePackages(const QStringList &packages, bool downloadOnly) { // if (Daemon::global()->roles() & Transaction::RoleUpdatePackages) { d->originalRole = Transaction::RoleUpdatePackages; d->packages = packages; if (downloadOnly) { // Don't simulate if we are just downloading d->flags = Transaction::TransactionFlagOnlyDownload; } else { d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; } setupTransaction(Daemon::updatePackages(d->packages, d->flags)); // } else { // showError(i18n("The current backend does not support updating packages."), i18n("Error")); // } } void PkTransaction::refreshCache(bool force) { setupTransaction(Daemon::refreshCache(force)); } void PkTransaction::installPackages() { setupTransaction(Daemon::installPackages(d->packages, d->flags)); } void PkTransaction::installFiles() { setupTransaction(Daemon::installFiles(d->files, d->flags)); } void PkTransaction::removePackages() { setupTransaction(Daemon::removePackages(d->packages, d->allowDeps, AUTOREMOVE, d->flags)); } void PkTransaction::updatePackages() { setupTransaction(Daemon::updatePackages(d->packages, d->flags)); } void PkTransaction::requeueTransaction() { Requirements *requires = qobject_cast(sender()); if (requires) { // As we have requires allow deps removal d->allowDeps = true; if (!requires->trusted()) { // Set only trusted to false, to do as the user asked setTrusted(false); } } // Delete the simulate model if (d->simulateModel) { d->simulateModel->deleteLater(); d->simulateModel = 0; } // We are not handling any required action yet for the requeued transaction. // Without this a second license agreement f.e. does not get shown, // see http://bugs.kde.org/show_bug.cgi?id=326619 d->handlingActionRequired = false; switch (d->originalRole) { case Transaction::RoleRemovePackages: removePackages(); break; case Transaction::RoleInstallPackages: installPackages(); break; case Transaction::RoleInstallFiles: installFiles(); break; case Transaction::RoleUpdatePackages: updatePackages(); break; default : setExitStatus(Failed); return; } } void PkTransaction::slotErrorCode(Transaction::Error error, const QString &details) { kDebug() << "errorCode: " << error << details; d->error = error; if (d->handlingActionRequired) { // We are already handling required actions // like eulaRequired() and repoSignatureRequired() return; } switch (error) { case Transaction::ErrorTransactionCancelled: case Transaction::ErrorProcessKill: // these errors should be ignored break; case Transaction::ErrorGpgFailure: case Transaction::ErrorBadGpgSignature: case Transaction::ErrorMissingGpgSignature: case Transaction::ErrorCannotInstallRepoUnsigned: case Transaction::ErrorCannotUpdateRepoUnsigned: { d->handlingActionRequired = true; int ret = KMessageBox::warningYesNo(d->parentWindow, i18n("You are about to install unsigned packages that can compromise your system, " "as it is impossible to verify if the software came from a trusted " "source.\n\nAre you sure you want to proceed with the installation?"), i18n("Installing unsigned software")); if (ret == KMessageBox::Yes) { // Set only trusted to false, to do as the user asked setTrusted(false); requeueTransaction(); } else { setExitStatus(Cancelled); } d->handlingActionRequired = false; return; } default: d->showingError = true; showSorry(PkStrings::error(error), PkStrings::errorMessage(error), QString(details).replace('\n', "
")); // when we receive an error we are done setExitStatus(Failed); } } void PkTransaction::slotEulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement) { if (d->handlingActionRequired) { // if its true means that we alread passed here d->handlingActionRequired = false; return; } else { d->handlingActionRequired = true; } - LicenseAgreement *eula = new LicenseAgreement(eulaID, packageID, vendor, licenseAgreement, d->parentWindow); + auto eula = new LicenseAgreement(eulaID, packageID, vendor, licenseAgreement, d->parentWindow); connect(eula, SIGNAL(yesClicked()), this, SLOT(acceptEula())); connect(eula, SIGNAL(rejected()), this, SLOT(reject())); showDialog(eula); } void PkTransaction::acceptEula() { LicenseAgreement *eula = qobject_cast(sender()); if (eula) { kDebug() << "Accepting EULA" << eula->id(); setupTransaction(Daemon::acceptEula(eula->id())); } else { kWarning() << "something is broken, slot is bound to LicenseAgreement but signalled from elsewhere."; } } void PkTransaction::slotChanged() { Transaction *transaction = qobject_cast(sender()); d->downloadSizeRemaining = transaction->downloadSizeRemaining(); d->role = transaction->role(); if (!d->jobWatcher) { return; } QDBusObjectPath _tid = transaction->tid(); if (d->tid != _tid && !(d->flags & Transaction::TransactionFlagSimulate)) { d->tid = _tid; // if the transaction changed and // the user wants the watcher send the tid QDBusMessage message; message = QDBusMessage::createMethodCall(QLatin1String("org.kde.apperd"), QLatin1String("/"), QLatin1String("org.kde.apperd"), QLatin1String("WatchTransaction")); // Use our own cached tid to avoid crashes message << qVariantFromValue(_tid); if (!QDBusConnection::sessionBus().send(message)) { kWarning() << "Failed to put WatchTransaction on the DBus queue"; } } } void PkTransaction::slotMediaChangeRequired(Transaction::MediaType type, const QString &id, const QString &text) { Q_UNUSED(id) d->handlingActionRequired = true; int ret = KMessageBox::questionYesNo(d->parentWindow, PkStrings::mediaMessage(type, text), i18n("A media change is required"), KStandardGuiItem::cont(), KStandardGuiItem::cancel()); d->handlingActionRequired = false; // if the user clicked continue we got yes if (ret == KMessageBox::Yes) { requeueTransaction(); } else { setExitStatus(Cancelled); } } void PkTransaction::slotRepoSignature(const QString &packageID, const QString &repoName, const QString &keyUrl, const QString &keyUserid, const QString &keyId, const QString &keyFingerprint, const QString &keyTimestamp, Transaction::SigType type) { if (d->handlingActionRequired) { // if its true means that we alread passed here d->handlingActionRequired = false; return; } else { d->handlingActionRequired = true; } RepoSig *repoSig = new RepoSig(packageID, repoName, keyUrl, keyUserid, keyId, keyFingerprint, keyTimestamp, type, d->parentWindow); connect(repoSig, SIGNAL(yesClicked()), this, SLOT(installSignature())); connect(repoSig, SIGNAL(rejected()), this, SLOT(reject())); showDialog(repoSig); } void PkTransaction::installSignature() { RepoSig *repoSig = qobject_cast(sender()); if (repoSig) { kDebug() << "Installing Signature" << repoSig->keyID(); setupTransaction(Daemon::installSignature(repoSig->sigType(), repoSig->keyID(), repoSig->packageID())); } else { kWarning() << "something is broken, slot is bound to RepoSig but signalled from elsewhere."; } } void PkTransaction::slotFinished(Transaction::Exit status) { // Clear the model to don't keep trash when reusing the transaction d->progressModel->clear(); Requirements *requires = 0; Transaction::Role _role = qobject_cast(sender())->role(); d->transaction = 0; // Will be deleted later kDebug() << status << _role; switch (_role) { case Transaction::RoleInstallSignature: case Transaction::RoleAcceptEula: if (status == Transaction::ExitSuccess) { // if the required action was performed with success // requeue our main transaction requeueTransaction(); return; } break; default: break; } switch(status) { case Transaction::ExitSuccess: // Check if we are just simulating if (d->flags & Transaction::TransactionFlagSimulate) { // Disable the simulate flag d->flags ^= Transaction::TransactionFlagSimulate; d->simulateModel->finished(); // Remove the transaction packages foreach (const QString &packageID, d->packages) { d->simulateModel->removePackage(packageID); } d->newPackages = d->simulateModel->packagesWithInfo(Transaction::InfoInstalling); if (_role == Transaction::RoleInstallPackages) { d->newPackages << d->packages; d->newPackages.removeDuplicates(); } requires = new Requirements(d->simulateModel, d->parentWindow); requires->setDownloadSizeRemaining(d->downloadSizeRemaining); connect(requires, SIGNAL(accepted()), this, SLOT(requeueTransaction())); connect(requires, SIGNAL(rejected()), this, SLOT(reject())); if (requires->shouldShow()) { showDialog(requires); } else { requires->deleteLater(); // Since we removed the Simulate Flag this will procced // with the actual action requeueTransaction(); } } else { KConfig config("apper"); KConfigGroup transactionGroup(&config, "Transaction"); bool showApp = transactionGroup.readEntry("ShowApplicationLauncher", true); if (showApp && !d->newPackages.isEmpty() && (_role == Transaction::RoleInstallPackages || _role == Transaction::RoleInstallFiles || _role == Transaction::RoleRemovePackages || _role == Transaction::RoleUpdatePackages)) { // When installing files or updates that involves new packages // try to resolve the available packages at simulation time // to maybe show the user the new applications that where installed if (d->launcher) { delete d->launcher; } d->launcher = new ApplicationLauncher(d->parentWindow); connect(this, SIGNAL(files(QString,QStringList)), d->launcher, SLOT(files(QString,QStringList))); setupTransaction(Daemon::getFiles(d->newPackages)); d->newPackages.clear(); return; // avoid the exit code } else if (_role == Transaction::RoleGetFiles && d->launcher && d->launcher->hasApplications()) { // if we have a launcher and the laucher has applications // show them to the user showDialog(d->launcher); connect(d->launcher, SIGNAL(finished()), SLOT(setExitStatus())); return; } setExitStatus(Success); } break; case Transaction::ExitNeedUntrusted: case Transaction::ExitKeyRequired: case Transaction::ExitEulaRequired: case Transaction::ExitMediaChangeRequired: kDebug() << "finished KeyRequired or EulaRequired: " << status; if (!d->handlingActionRequired) { kDebug() << "Not Handling Required Action"; setExitStatus(Failed); } break; case Transaction::ExitCancelled: // Avoid crash in case we are showing an error if (!d->showingError) { setExitStatus(Cancelled); } break; case Transaction::ExitFailed: if (!d->handlingActionRequired && !d->showingError) { kDebug() << "Yep, we failed."; setExitStatus(Failed); } break; default : kDebug() << "finished default" << status; setExitStatus(Failed); break; } } PkTransaction::ExitStatus PkTransaction::exitStatus() const { return d->exitStatus; } bool PkTransaction::isFinished() const { kDebug() << d->transaction->status() << d->transaction->role(); return d->transaction->status() == Transaction::StatusFinished; } PackageModel *PkTransaction::simulateModel() const { return d->simulateModel; } uint PkTransaction::percentage() const { if (d->transaction) { return d->transaction->percentage(); } return 0; } uint PkTransaction::remainingTime() const { if (d->transaction) { return d->transaction->remainingTime(); } return 0; } uint PkTransaction::speed() const { if (d->transaction) { return d->transaction->speed(); } return 0; } qulonglong PkTransaction::downloadSizeRemaining() const { if (d->transaction) { return d->transaction->downloadSizeRemaining(); } return 0; } Transaction::Status PkTransaction::status() const { if (d->transaction) { return d->transaction->status(); } return Transaction::StatusUnknown; } Transaction::Role PkTransaction::role() const { if (d->transaction) { return d->transaction->role(); } return Transaction::RoleUnknown; } bool PkTransaction::allowCancel() const { if (d->transaction) { return d->transaction->allowCancel(); } return false; } Transaction::TransactionFlags PkTransaction::transactionFlags() const { if (d->transaction) { return d->transaction->transactionFlags(); } return Transaction::TransactionFlagNone; } void PkTransaction::getUpdateDetail(const QString &packageID) { setupTransaction(Daemon::getUpdateDetail(packageID)); } void PkTransaction::getUpdates() { setupTransaction(Daemon::getUpdates()); } void PkTransaction::cancel() { if (d->transaction) { d->transaction->cancel(); } } void PkTransaction::setTrusted(bool trusted) { if (trusted) { d->flags |= Transaction::TransactionFlagOnlyTrusted; } else { d->flags ^= Transaction::TransactionFlagOnlyTrusted; } } void PkTransaction::setExitStatus(PkTransaction::ExitStatus status) { kDebug() << status; if (d->launcher) { d->launcher->deleteLater(); d->launcher = 0; } d->exitStatus = status; if (!d->handlingActionRequired || !d->showingError) { emit finished(status); } } void PkTransaction::reject() { setExitStatus(Cancelled); } void PkTransaction::setupTransaction(Transaction *transaction) { // Clear the model to don't keep trash when reusing the transaction d->progressModel->clear(); d->transaction = transaction; if (!(transaction->transactionFlags() & Transaction::TransactionFlagSimulate) && transaction->role() != Transaction::RoleGetUpdates && transaction->role() != Transaction::RoleGetUpdateDetail) { connect(transaction, SIGNAL(repoDetail(QString,QString,bool)), d->progressModel, SLOT(currentRepo(QString,QString,bool))); connect(transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), d->progressModel, SLOT(currentPackage(PackageKit::Transaction::Info,QString,QString))); connect(transaction, SIGNAL(itemProgress(QString,PackageKit::Transaction::Status,uint)), d->progressModel, SLOT(itemProgress(QString,PackageKit::Transaction::Status,uint))); } connect(transaction, SIGNAL(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime)), SIGNAL(updateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,PackageKit::Transaction::Restart,QString,QString,PackageKit::Transaction::UpdateState,QDateTime,QDateTime))); connect(transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), SIGNAL(package(PackageKit::Transaction::Info,QString,QString))); connect(transaction, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), SIGNAL(errorCode(PackageKit::Transaction::Error,QString))); // Required actions connect(transaction, SIGNAL(allowCancelChanged()), SIGNAL(allowCancelChanged())); connect(transaction, SIGNAL(downloadSizeRemainingChanged()), SIGNAL(downloadSizeRemainingChanged())); connect(transaction, SIGNAL(elapsedTimeChanged()), SIGNAL(elapsedTimeChanged())); connect(transaction, SIGNAL(isCallerActiveChanged()), SIGNAL(isCallerActiveChanged())); connect(transaction, SIGNAL(lastPackageChanged()), SIGNAL(lastPackageChanged())); connect(transaction, SIGNAL(percentageChanged()), SIGNAL(percentageChanged())); connect(transaction, SIGNAL(remainingTimeChanged()), SIGNAL(remainingTimeChanged())); connect(transaction, SIGNAL(roleChanged()), SIGNAL(roleChanged())); connect(transaction, SIGNAL(speedChanged()), SIGNAL(speedChanged())); connect(transaction, SIGNAL(statusChanged()), SIGNAL(statusChanged())); connect(transaction, SIGNAL(transactionFlagsChanged()), SIGNAL(transactionFlagsChanged())); connect(transaction, SIGNAL(uidChanged()), SIGNAL(uidChanged())); connect(transaction, SIGNAL(downloadSizeRemainingChanged()), SLOT(slotChanged())); connect(transaction, SIGNAL(errorCode(PackageKit::Transaction::Error,QString)), SLOT(slotErrorCode(PackageKit::Transaction::Error,QString))); connect(transaction, SIGNAL(eulaRequired(QString,QString,QString,QString)), SLOT(slotEulaRequired(QString,QString,QString,QString))); connect(transaction, SIGNAL(mediaChangeRequired(PackageKit::Transaction::MediaType,QString,QString)), SLOT(slotMediaChangeRequired(PackageKit::Transaction::MediaType,QString,QString))); connect(transaction, SIGNAL(repoSignatureRequired(QString,QString,QString,QString,QString,QString,QString,PackageKit::Transaction::SigType)), SLOT(slotRepoSignature(QString,QString,QString,QString,QString,QString,QString,PackageKit::Transaction::SigType))); connect(transaction, SIGNAL(finished(PackageKit::Transaction::Exit,uint)), SLOT(slotFinished(PackageKit::Transaction::Exit))); if (d->flags & Transaction::TransactionFlagSimulate) { d->simulateModel = new PackageModel(this); connect(d->transaction, SIGNAL(package(PackageKit::Transaction::Info,QString,QString)), d->simulateModel, SLOT(addPackage(PackageKit::Transaction::Info,QString,QString))); } #ifdef HAVE_DEBCONFKDE QString _tid = transaction->tid().path(); QString socket; // Build a socket path like /tmp/1761_edeceabd_data_debconf socket = QLatin1String("/tmp") % _tid % QLatin1String("_debconf"); QDBusMessage message; message = QDBusMessage::createMethodCall(QLatin1String("org.kde.apperd"), QLatin1String("/"), QLatin1String("org.kde.apperd"), QLatin1String("SetupDebconfDialog")); // Use our own cached tid to avoid crashes message << qVariantFromValue(_tid); message << qVariantFromValue(socket); if (d->parentWindow) { message << qVariantFromValue(static_cast(d->parentWindow->effectiveWinId())); } else { message << qVariantFromValue(0u); } if (!QDBusConnection::sessionBus().send(message)) { kWarning() << "Failed to put SetupDebconfDialog message in DBus queue"; } transaction->setHints(QLatin1String("frontend-socket=") % socket); #endif //HAVE_DEBCONFKDE } void PkTransaction::showDialog(KDialog *dlg) { - PkTransactionWidget *widget = qobject_cast(d->parentWindow); + auto widget = qobject_cast(d->parentWindow); if (!widget || widget->isCancelVisible()) { dlg->setModal(d->parentWindow); dlg->show(); } else { dlg->setProperty("embedded", true); emit dialog(dlg); } } void PkTransaction::showError(const QString &title, const QString &description, const QString &details) { PkTransactionWidget *widget = qobject_cast(d->parentWindow); if (!widget || widget->isCancelVisible()) { if (details.isEmpty()) { if (d->parentWindow) { KMessageBox::error(d->parentWindow, description, title); } else { KMessageBox::errorWId(0, description, title); } } else { KMessageBox::detailedError(d->parentWindow, description, details, title); } } else { emit errorMessage(title, description, details); } } void PkTransaction::showSorry(const QString &title, const QString &description, const QString &details) { PkTransactionWidget *widget = qobject_cast(d->parentWindow); if (!widget || widget->isCancelVisible()) { if (details.isEmpty()) { KMessageBox::sorry(d->parentWindow, description, title); } else { KMessageBox::detailedSorry(d->parentWindow, description, details, title); } } else { emit sorry(title, description, details); } } QString PkTransaction::title() const { return PkStrings::action(d->originalRole, d->flags); } Transaction::Role PkTransaction::cachedRole() const { return d->role; } Transaction::TransactionFlags PkTransaction::flags() const { return d->flags; } PkTransactionProgressModel *PkTransaction::progressModel() const { return d->progressModel; } void PkTransaction::enableJobWatcher(bool enable) { d->jobWatcher = enable; } #include "PkTransaction.moc" diff --git a/libapper/Requirements.cpp b/libapper/Requirements.cpp index 923ed83..e3ec627 100644 --- a/libapper/Requirements.cpp +++ b/libapper/Requirements.cpp @@ -1,268 +1,268 @@ /*************************************************************************** * Copyright (C) 2008-2011 by Daniel Nicoletti * * dantti12@gmail.com * * * * 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) any later version. * * * * 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; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Requirements.h" #include "ui_Requirements.h" #include "PkIcons.h" #include "PackageModel.h" #include "ApplicationSortFilterModel.h" #include #include #include #include Requirements::Requirements(PackageModel *model, QWidget *parent) : KDialog(parent), m_embed(false), m_shouldShow(true), m_untrustedButton(0), ui(new Ui::Requirements) { setAttribute(Qt::WA_DeleteOnClose); ui->setupUi(mainWidget()); connect(ui->confirmCB, SIGNAL(toggled(bool)), this, SLOT(on_confirmCB_Toggled(bool))); ApplicationSortFilterModel *proxy = new ApplicationSortFilterModel(this); proxy->setSourceModel(model); ui->packageView->setModel(proxy); ui->packageView->header()->setResizeMode(PackageModel::NameCol, QHeaderView::ResizeToContents); ui->packageView->header()->hideSection(PackageModel::ActionCol); ui->packageView->header()->hideSection(PackageModel::ArchCol); ui->packageView->header()->hideSection(PackageModel::CurrentVersionCol); ui->packageView->header()->hideSection(PackageModel::OriginCol); ui->packageView->header()->hideSection(PackageModel::SizeCol); m_hideAutoConfirm = false; setCaption(i18n("Additional changes")); setWindowIcon(QIcon::fromTheme("dialog-warning")); setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Help); setButtonText(KDialog::Ok, i18n("Continue")); // restore size setMinimumSize(QSize(600,480)); setInitialSize(QSize(600,600)); KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); restoreDialogSize(requirementsDialog); button(KDialog::Help)->setFlat(true); button(KDialog::Help)->setEnabled(false); button(KDialog::Help)->setIcon(QIcon::fromTheme("download")); m_buttonGroup = new QButtonGroup(this); connect(m_buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(actionClicked(int))); int count = 0; if (int c = model->countInfo(Transaction::InfoRemoving)) { QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setCheckable(true); button->setAutoRaise(true); button->setIconSize(QSize(32, 32)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(i18np("1 package to remove", "%1 packages to remove", c)); button->setIcon(PkIcons::actionIcon(Transaction::RoleRemovePackages)); m_buttonGroup->addButton(button, Transaction::InfoRemoving); ui->verticalLayout->insertWidget(count++, button); m_hideAutoConfirm = true; } if (int c = model->countInfo(Transaction::InfoDowngrading)) { QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setCheckable(true); button->setAutoRaise(true); button->setIconSize(QSize(32, 32)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(i18np("1 package to downgrade", "%1 packages to downgrade", c)); button->setIcon(PkIcons::actionIcon(Transaction::RoleRepairSystem)); m_buttonGroup->addButton(button, Transaction::InfoDowngrading); ui->verticalLayout->insertWidget(count++, button); m_hideAutoConfirm = true; } if (int c = model->countInfo(Transaction::InfoReinstalling)) { QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setCheckable(true); button->setAutoRaise(true); button->setIconSize(QSize(32, 32)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(i18np("1 package to reinstall", "%1 packages to reinstall", c)); button->setIcon(PkIcons::actionIcon(Transaction::RoleRemovePackages)); m_buttonGroup->addButton(button, Transaction::InfoReinstalling); ui->verticalLayout->insertWidget(count++, button); } if (int c = model->countInfo(Transaction::InfoInstalling)) { QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setCheckable(true); button->setAutoRaise(true); button->setIconSize(QSize(32, 32)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(i18np("1 package to install", "%1 packages to install", c)); button->setIcon(PkIcons::actionIcon(Transaction::RoleInstallPackages)); m_buttonGroup->addButton(button, Transaction::InfoInstalling); ui->verticalLayout->insertWidget(count++, button); } if (int c = model->countInfo(Transaction::InfoUpdating)) { QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setCheckable(true); button->setAutoRaise(true); button->setIconSize(QSize(32, 32)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(i18np("1 package to update", "%1 packages to update", c)); button->setIcon(PkIcons::actionIcon(Transaction::RoleUpdatePackages)); m_buttonGroup->addButton(button, Transaction::InfoUpdating); ui->verticalLayout->insertWidget(count++, button); } if (int c = model->countInfo(Transaction::InfoUntrusted)) { m_untrustedButton = new QToolButton(this); m_untrustedButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_untrustedButton->setCheckable(true); m_untrustedButton->setAutoRaise(true); m_untrustedButton->setIconSize(QSize(32, 32)); m_untrustedButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); m_untrustedButton->setText(i18np("1 untrusted package", "%1 untrusted packages", c)); m_untrustedButton->setIcon(QIcon::fromTheme("security-low")); m_untrustedButton->setVisible(false); ui->verticalLayout->insertWidget(count++, m_untrustedButton); } if (!m_buttonGroup->buttons().isEmpty()) { m_buttonGroup->buttons().first()->click(); if (m_hideAutoConfirm) { ui->confirmCB->setVisible(false); } else { // if the confirmCB is visible means that we can skip this // dialog, but only if the user previusly set so ui->confirmCB->setChecked(requirementsDialog.readEntry("autoConfirm", false)); } } else if (m_untrustedButton) { showUntrustedButton(); } else { // set this as false so the dialog is not shown m_shouldShow = false; } } Requirements::~Requirements() { KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); saveDialogSize(requirementsDialog); delete ui; } bool Requirements::embedded() const { return m_embed; } void Requirements::setEmbedded(bool embedded) { m_embed = embedded; ui->label->setVisible(!embedded); } void Requirements::setDownloadSizeRemaining(qulonglong size) { if (size) { QString text; text = i18nc("how many bytes are required for download", "Need to get %1 of archives", - KGlobal::locale()->formatByteSize(size)); + KLocale::global()->formatByteSize(size)); button(KDialog::Help)->setText(text); button(KDialog::Help)->setToolTip(text); button(KDialog::Help)->show(); } else { button(KDialog::Help)->hide(); } } bool Requirements::trusted() const { // There are untrusted packages if the button was created... return !m_untrustedButton; } bool Requirements::shouldShow() const { return (m_shouldShow && !ui->confirmCB->isChecked()); } void Requirements::slotButtonClicked(int button) { if (button == KDialog::Ok && m_untrustedButton && !m_untrustedButton->isVisible()) { showUntrustedButton(); } else { KDialog::slotButtonClicked(button); } } void Requirements::on_confirmCB_Toggled(bool checked) { KConfig config("apper"); KConfigGroup requirementsDialog(&config, "requirementsDialog"); if (!m_hideAutoConfirm) { requirementsDialog.writeEntry("autoConfirm", checked); } config.sync(); } void Requirements::actionClicked(int type) { ApplicationSortFilterModel *proxy; proxy = qobject_cast(ui->packageView->model()); proxy->setInfoFilter(static_cast(type)); } void Requirements::showUntrustedButton() { // Clear the other buttons foreach (QAbstractButton *button, m_buttonGroup->buttons()) { delete button; } // Hide the auto confirm button since we will be showing this dialog anyway ui->confirmCB->setVisible(false); ui->label->setText(i18n("You are about to install unsigned packages that can compromise your system, " "as it is impossible to verify if the software came from a trusted source.")); m_untrustedButton->setVisible(true); m_buttonGroup->addButton(m_untrustedButton, Transaction::InfoUntrusted); m_untrustedButton->click(); } #include "Requirements.moc"