File indexing completed on 2022-09-27 16:24:28

0001 /***************************************************************************
0002  *   Copyright (C) 2009-2010 by Daniel Nicoletti                           *
0003  *   dantti12@gmail.com                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; see the file COPYING. If not, write to       *
0017  *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,  *
0018  *   Boston, MA 02110-1301, USA.                                           *
0019  ***************************************************************************/
0020 
0021 #include "BrowseView.h"
0022 
0023 #include "PackageDetails.h"
0024 #include "CategoryModel.h"
0025 
0026 #include <ApplicationsDelegate.h>
0027 #include <ApplicationSortFilterModel.h>
0028 #include <PackageModel.h>
0029 
0030 #include <Daemon>
0031 
0032 #include <QFileDialog>
0033 #include <KPixmapSequence>
0034 #include <QMenu>
0035 #include <KIconLoader>
0036 #include <KConfig>
0037 #include <KConfigGroup>
0038 #include <KLocalizedString>
0039 
0040 #include <QDBusConnection>
0041 #include <QDBusMessage>
0042 #include <QAbstractItemView>
0043 #include <QScrollBar>
0044 
0045 #include <QLoggingCategory>
0046 
0047 using namespace PackageKit;
0048 
0049 BrowseView::BrowseView(QWidget *parent)
0050  : QWidget(parent)
0051 {
0052     setupUi(this);
0053     connect(categoryView, &QListView::clicked, this, &BrowseView::categoryActivated);
0054 
0055     m_busySeq = new KPixmapSequenceOverlayPainter(this);
0056     m_busySeq->setSequence(KIconLoader::global()->loadPixmapSequence(QLatin1String("process-working"), KIconLoader::SizeSmallMedium));
0057     m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
0058     m_busySeq->setWidget(packageView->viewport());
0059 
0060     m_model = new PackageModel(this);
0061     m_proxy = new ApplicationSortFilterModel(this);
0062     m_proxy->setSourceModel(m_model);
0063 
0064     packageView->setModel(m_proxy);
0065     packageView->sortByColumn(PackageModel::NameCol, Qt::AscendingOrder);
0066     packageView->header()->setDefaultAlignment(Qt::AlignCenter);
0067     packageView->header()->setStretchLastSection(false);
0068     packageView->header()->setSectionResizeMode(PackageModel::NameCol, QHeaderView::Stretch);
0069     packageView->header()->setSectionResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents);
0070     packageView->header()->setSectionResizeMode(PackageModel::ArchCol, QHeaderView::ResizeToContents);
0071     packageView->header()->setSectionResizeMode(PackageModel::OriginCol, QHeaderView::ResizeToContents);
0072     packageView->header()->setSectionResizeMode(PackageModel::SizeCol, QHeaderView::ResizeToContents);
0073     packageView->header()->setSectionResizeMode(PackageModel::ActionCol, QHeaderView::ResizeToContents);
0074 
0075     // Hide current Version since it's useless for us
0076     packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, true);
0077 
0078     ApplicationsDelegate *delegate = new ApplicationsDelegate(packageView);
0079     packageView->setItemDelegate(delegate);
0080 
0081     exportInstalledPB->setIcon(QIcon::fromTheme(QLatin1String("document-export")));
0082     importInstalledPB->setIcon(QIcon::fromTheme(QLatin1String("document-import")));
0083 
0084     KConfig config(QLatin1String("apper"));
0085     KConfigGroup viewGroup(&config, "BrowseView");
0086 
0087     // Version
0088     packageView->header()->setSectionHidden(PackageModel::VersionCol, true);
0089     m_showPackageVersion = new QAction(i18n("Show Versions"), this);
0090     m_showPackageVersion->setCheckable(true);
0091     connect(m_showPackageVersion, &QAction::toggled, this, &BrowseView::showVersions);
0092     m_showPackageVersion->setChecked(viewGroup.readEntry("ShowApplicationVersions", true));
0093 
0094     // Arch
0095     packageView->header()->setSectionHidden(PackageModel::ArchCol, true);
0096     m_showPackageArch = new QAction(i18n("Show Architectures"), this);
0097     m_showPackageArch->setCheckable(true);
0098     connect(m_showPackageArch, &QAction::toggled, this, &BrowseView::showArchs);
0099     m_showPackageArch->setChecked(viewGroup.readEntry("ShowApplicationArchitectures", false));
0100 
0101     // Origin
0102     packageView->header()->setSectionHidden(PackageModel::OriginCol, true);
0103     m_showPackageOrigin = new QAction(i18n("Show Origins"), this);
0104     m_showPackageOrigin->setCheckable(true);
0105     connect(m_showPackageOrigin, &QAction::toggled, this, &BrowseView::showOrigins);
0106     m_showPackageOrigin->setChecked(viewGroup.readEntry("ShowApplicationOrigins", false));
0107 
0108     // Sizes
0109     packageView->header()->setSectionHidden(PackageModel::SizeCol, true);
0110     m_showPackageSizes = new QAction(i18n("Show Sizes"), this);
0111     m_showPackageSizes->setCheckable(true);
0112     connect(m_showPackageSizes, &QAction::toggled, this, &BrowseView::showSizes);
0113     m_showPackageSizes->setChecked(viewGroup.readEntry("ShowPackageSizes", false));
0114 
0115 
0116     // Ensure the index is visible when the packageDetails appears
0117     connect(packageDetails, &PackageDetails::ensureVisible, this, &BrowseView::ensureVisible);
0118 }
0119 
0120 void BrowseView::init(Transaction::Roles roles)
0121 {
0122     packageDetails->init(roles);
0123 }
0124 
0125 BrowseView::~BrowseView()
0126 {
0127 }
0128 
0129 bool BrowseView::showPageHeader() const
0130 {
0131     return false;
0132 }
0133 
0134 PackageModel* BrowseView::model() const
0135 {
0136     return m_model;
0137 }
0138 
0139 void BrowseView::showVersions(bool enabled)
0140 {
0141     KConfig config(QLatin1String("apper"));
0142     KConfigGroup viewGroup(&config, "BrowseView");
0143     viewGroup.writeEntry("ShowApplicationVersions", enabled);
0144     packageView->header()->setSectionHidden(PackageModel::VersionCol, !enabled);
0145     packageDetails->hidePackageVersion(enabled);
0146 }
0147 
0148 void BrowseView::showArchs(bool enabled)
0149 {
0150     KConfig config(QLatin1String("apper"));
0151     KConfigGroup viewGroup(&config, "BrowseView");
0152     viewGroup.writeEntry("ShowApplicationArchitectures", enabled);
0153     packageView->header()->setSectionHidden(PackageModel::ArchCol, !enabled);
0154     packageDetails->hidePackageArch(enabled);
0155 }
0156 
0157 void BrowseView::showOrigins(bool enabled)
0158 {
0159     KConfig config(QLatin1String("apper"));
0160     KConfigGroup viewGroup(&config, "BrowseView");
0161     viewGroup.writeEntry("ShowApplicationOrigins", enabled);
0162     packageView->header()->setSectionHidden(PackageModel::OriginCol, !enabled);
0163 }
0164 
0165 void BrowseView::showSizes(bool enabled)
0166 {
0167     KConfig config(QLatin1String("apper"));
0168     KConfigGroup viewGroup(&config, "BrowseView");
0169     viewGroup.writeEntry("ShowPackageSizes", enabled);
0170     packageView->header()->setSectionHidden(PackageModel::SizeCol, !enabled);
0171     packageDetails->hidePackageArch(enabled);
0172     if (enabled) {
0173         m_model->fetchSizes();
0174     }
0175 }
0176 
0177 void BrowseView::on_packageView_customContextMenuRequested(const QPoint &pos)
0178 {
0179     auto menu = new QMenu(this);
0180     menu->addAction(m_showPackageVersion);
0181     menu->addAction(m_showPackageArch);
0182     menu->addAction(m_showPackageOrigin);
0183     menu->addAction(m_showPackageSizes);
0184     menu->exec(packageView->viewport()->mapToGlobal(pos));
0185     menu->deleteLater();
0186 }
0187 
0188 void BrowseView::on_packageView_clicked(const QModelIndex &index)
0189 {
0190     if (index.column() == PackageModel::ActionCol) {
0191         return;
0192     }
0193 
0194     QModelIndex origIndex = m_proxy->mapToSource(index);
0195     packageDetails->setPackage(origIndex);
0196 }
0197 
0198 void BrowseView::ensureVisible(const QModelIndex &index)
0199 {
0200     QModelIndex proxIndex = m_proxy->mapFromSource(index);
0201     packageView->scrollTo(proxIndex);
0202 }
0203 
0204 void BrowseView::showInstalledPanel(bool visible)
0205 {
0206     installedF->setVisible(visible);
0207 }
0208 
0209 ApplicationSortFilterModel* BrowseView::proxy() const
0210 {
0211     return m_proxy;
0212 }
0213 
0214 KPixmapSequenceOverlayPainter* BrowseView::busyCursor() const
0215 {
0216     return m_busySeq;
0217 }
0218 
0219 void BrowseView::setCategoryModel(QAbstractItemModel *model)
0220 {
0221     categoryView->setModel(model);
0222 }
0223 
0224 void BrowseView::setParentCategory(const QModelIndex &index)
0225 {
0226     categoryView->setRootIndex(index);
0227     // Make sure the last item is not selected
0228     categoryView->selectionModel()->clearSelection();
0229     categoryView->horizontalScrollBar()->setValue(0);
0230 
0231     // Display the category view if the index has child items
0232     categoryF->setVisible(categoryView->model()->rowCount(index));
0233 }
0234 
0235 bool BrowseView::goBack()
0236 {
0237     packageDetails->hide();
0238     QModelIndex index = categoryView->rootIndex();
0239     if (index.parent().isValid()) {
0240         index = index.parent();
0241         // if it's valid we need to know if it wasn't a  PK root category
0242         if (index.data(CategoryModel::GroupRole).type() == QVariant::String) {
0243             QString category = index.data(CategoryModel::GroupRole).toString();
0244             if (!category.startsWith(QLatin1Char('@'))) {
0245                 return true;
0246             }
0247         }
0248         setParentCategory(index);
0249         emit categoryActivated(index);
0250         return false;
0251     }
0252     return true;
0253 }
0254 
0255 void BrowseView::on_categoryMvLeft_clicked()
0256 {
0257     categoryView->horizontalScrollBar()->setValue(categoryView->horizontalScrollBar()->value() - 1);
0258 }
0259 
0260 void BrowseView::on_categoryMvRight_clicked()
0261 {
0262     categoryView->horizontalScrollBar()->setValue(categoryView->horizontalScrollBar()->value() + 1);
0263 }
0264 
0265 void BrowseView::cleanUi()
0266 {
0267     packageDetails->hide();
0268     categoryF->setVisible(false);
0269 }
0270 
0271 bool BrowseView::isShowingSizes() const
0272 {
0273     return m_showPackageSizes->isChecked();
0274 }
0275 
0276 void BrowseView::on_exportInstalledPB_clicked()
0277 {
0278     // We will assume the installed model
0279     // is populated since the user is seeing it.
0280     QString fileName;
0281     fileName = QFileDialog::getSaveFileName(this,
0282                                             i18n("Export installed packages"),
0283                                             QString(),
0284                                             QStringLiteral("*.catalog"));
0285     if (fileName.isEmpty()) {
0286         return;
0287     }
0288 
0289     QFile file(fileName);
0290     file.open(QIODevice::WriteOnly);
0291     QTextStream out(&file);
0292     out << "[PackageKit Catalog]\n\n";
0293     out << "InstallPackages(" << Daemon::global()->distroID() << ")=";
0294     QStringList packages;
0295     for (int i = 0; i < m_model->rowCount(); i++) {
0296         packages << m_model->data(m_model->index(i, 0),
0297                                   PackageModel::PackageName).toString();
0298     }
0299     out << packages.join(QLatin1Char(';'));
0300 }
0301 
0302 void BrowseView::on_importInstalledPB_clicked()
0303 {
0304     QString fileName;
0305     fileName = QFileDialog::getOpenFileName(this,
0306                                             i18n("Install packages from catalog"),
0307                                             QString(),
0308                                             QStringLiteral("*.catalog"));
0309     if (fileName.isEmpty()) {
0310         return;
0311     }
0312 
0313     // send a DBus message to install this catalog
0314     QDBusMessage message;
0315     message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.PackageKit"),
0316                                              QLatin1String("/org/freedesktop/PackageKit"),
0317                                              QLatin1String("org.freedesktop.PackageKit.Modify"),
0318                                              QLatin1String("InstallCatalogs"));
0319     message << static_cast<uint>(effectiveWinId());
0320     message << (QStringList() << fileName);
0321     message << QString();
0322 
0323     // This call must block otherwise this application closes before
0324     // smarticon is activated
0325     QDBusMessage reply = QDBusConnection::sessionBus().call(message, QDBus::Block);
0326 }
0327 
0328 void BrowseView::disableExportInstalledPB()
0329 {
0330     exportInstalledPB->setEnabled(false);
0331 }
0332 
0333 void BrowseView::enableExportInstalledPB()
0334 {
0335     exportInstalledPB->setEnabled(true);
0336 }
0337 
0338 #include "moc_BrowseView.cpp"