File indexing completed on 2024-03-24 17:22:08
0001 /*************************************************************************** 0002 * Copyright (C) 2009-2011 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 "PkInstallCatalogs.h" 0022 #include "IntroDialog.h" 0023 #include "FilesModel.h" 0024 0025 #include <PkStrings.h> 0026 0027 #include <KLocalizedString> 0028 #include <KMessageBox> 0029 0030 #include <QLoggingCategory> 0031 0032 #include <QFile> 0033 0034 #include <Daemon> 0035 0036 Q_DECLARE_LOGGING_CATEGORY(APPER_SESSION) 0037 0038 PkInstallCatalogs::PkInstallCatalogs(uint xid, 0039 const QStringList &files, 0040 const QString &interaction, 0041 const QDBusMessage &message, 0042 QWidget *parent) 0043 : SessionTask(xid, interaction, message, parent), 0044 m_interaction(interaction), 0045 m_message(message) 0046 { 0047 setWindowTitle(i18n("Install Packages Catalogs")); 0048 0049 // Find out how many packages PackageKit is able to resolve 0050 QFile file(QLatin1String("/etc/PackageKit/PackageKit.conf")); 0051 QRegExp rx(QLatin1String("\\s*MaximumItemsToResolve=(\\d+)"), Qt::CaseSensitive); 0052 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0053 QTextStream in(&file); 0054 while (!in.atEnd()) { 0055 if (rx.indexIn(in.readLine()) != -1) { 0056 m_maxResolve = rx.capturedTexts()[1].toInt(); 0057 break; 0058 } 0059 } 0060 } 0061 0062 const QStringList mimes{ 0063 QLatin1String("application/x-catalog"), QLatin1String("text/plain") 0064 }; 0065 m_introDialog = new IntroDialog(this); 0066 m_introDialog->acceptDrops(i18n("You can drop more catalogs in here")); 0067 m_model = new FilesModel(files, mimes, this); 0068 connect(m_model, &FilesModel::rowsInserted, this, &PkInstallCatalogs::modelChanged); 0069 m_introDialog->setModel(m_model); 0070 setMainWidget(m_introDialog); 0071 0072 modelChanged(); 0073 } 0074 0075 PkInstallCatalogs::~PkInstallCatalogs() 0076 { 0077 } 0078 0079 void PkInstallCatalogs::modelChanged() 0080 { 0081 const QStringList files = m_model->files(); 0082 enableButtonOk(!files.isEmpty()); 0083 QString description; 0084 if (files.isEmpty()) { 0085 description = i18n("No supported catalog was found"); 0086 } else { 0087 description = i18np("Do you want to install this catalog?", 0088 "Do you want to install these catalogs?", 0089 files.size()); 0090 } 0091 m_introDialog->setDescription(description); 0092 0093 QString title; 0094 // this will come from DBus interface 0095 if (parentTitle.isNull()) { 0096 title = i18np("An application wants to install a catalog", 0097 "An application wants to install catalogs", 0098 files.size()); 0099 } else { 0100 title = i18np("The application <i>%2</i> wants to install a catalog", 0101 "The application <i>%2</i> wants to install catalogs", 0102 files.size(), 0103 parentTitle); 0104 } 0105 setTitle(title); 0106 } 0107 0108 void PkInstallCatalogs::search() 0109 { 0110 const QString distroId = Daemon::global()->distroID(); 0111 const QStringList parts = distroId.split(QLatin1Char(';')); 0112 if (parts.size() != 3) { 0113 sendErrorFinished(Failed, QLatin1String("invalid distribution id, please fill a bug against you distribution backend")); 0114 return; 0115 } 0116 const QString distro = parts.at(0); 0117 const QString version = parts.at(1); 0118 const QString arch = parts.at(2); 0119 0120 QStringList rxActions; 0121 Transaction::Roles roles = Daemon::global()->roles(); 0122 if (roles & Transaction::RoleResolve) { 0123 rxActions << QLatin1String("InstallPackages"); 0124 } 0125 0126 if (roles & Transaction::RoleWhatProvides) { 0127 rxActions << QLatin1String("InstallProvides"); 0128 } 0129 0130 if (roles & Transaction::RoleSearchFile) { 0131 rxActions << QLatin1String("InstallFiles"); 0132 } 0133 0134 if (rxActions.isEmpty()) { 0135 if (showWarning()) { 0136 // TODO display a nicer message informing of already installed ones 0137 setInfo(i18n("Not supported"), 0138 i18n("Your backend does not support any of the needed " 0139 "methods to install a catalog")); 0140 } 0141 sendErrorFinished(Failed, QLatin1String("not supported by backend")); 0142 return; 0143 } 0144 0145 // matches at the beginning of line installPackages or InstallProvides or installFiles and capture it 0146 // matches an optional set of parenthesis 0147 // matches *%1* and or *%2* and or *%3* 0148 // matches after '=' but ';' at the end 0149 QString pattern; 0150 pattern = QString( 0151 QLatin1String("^(%1)(?:\\((?:.*%2[^;]*(?:;(?:.*%3[^;]*(?:;(?:.*%4[^;]*)?)?)?)?)?\\))?=(.*[^;$])")) 0152 .arg(rxActions.join(QLatin1Char('|')), distro, version, arch); 0153 QRegExp rx(pattern, Qt::CaseInsensitive); 0154 0155 QStringList filesFailedToOpen; 0156 const QStringList files = m_model->files(); 0157 if (!files.isEmpty()) { 0158 for (const QString &file : files) { 0159 QFile catalog(file); 0160 if (catalog.open(QIODevice::ReadOnly | QIODevice::Text)) { 0161 QTextStream in(&catalog); 0162 while (!in.atEnd()) { 0163 if (rx.indexIn(in.readLine()) != -1) { 0164 if (rx.cap(1).compare(QLatin1String("InstallPackages"), Qt::CaseInsensitive) == 0) { 0165 m_installPackages.append(rx.cap(2).split(QLatin1Char(';'))); 0166 } else if (rx.cap(1).compare(QLatin1String("InstallProvides"), Qt::CaseInsensitive) == 0) { 0167 m_installProvides.append(rx.cap(2).split(QLatin1Char(';'))); 0168 } else if (rx.cap(1).compare(QLatin1String("InstallFiles"), Qt::CaseInsensitive) == 0) { 0169 m_installFiles.append(rx.cap(2).split(QLatin1Char(';'))); 0170 } 0171 } 0172 } 0173 } else { 0174 filesFailedToOpen << file; 0175 } 0176 } 0177 } else { 0178 setInfo(i18n("Catalog not found"), 0179 i18n("Could not find a catalog to install")); 0180 return; 0181 } 0182 0183 if (showWarning() && filesFailedToOpen.size()) { 0184 // TODO display a nicer message informing of already installed ones 0185 KMessageBox::error(this, 0186 i18np("Catalog %2 failed to open", 0187 "Catalogs %2 failed to open", 0188 filesFailedToOpen.size(), 0189 filesFailedToOpen.join(QLatin1Char(','))), 0190 i18n("Failed to open")); 0191 } 0192 0193 if (m_installPackages.isEmpty() && 0194 m_installProvides.isEmpty() && 0195 m_installFiles.isEmpty()) { 0196 setInfo(i18n("Catalog is Empty"), 0197 i18n("Could not find any package to install in this catalog")); 0198 } else { 0199 // Start resolving 0200 searchFinished(PkTransaction::Success); 0201 } 0202 } 0203 0204 void PkInstallCatalogs::searchFinished(PkTransaction::ExitStatus status) 0205 { 0206 if (status == PkTransaction::Success) { 0207 if (!m_installPackages.isEmpty()) { 0208 // Continue resolving Install Packages 0209 QStringList resolve; 0210 int count = 0; 0211 while (!m_installPackages.isEmpty() && count < m_maxResolve) { 0212 // Remove the items from the list so next call we have less 0213 resolve.append(m_installPackages.takeFirst()); 0214 ++count; 0215 } 0216 qCDebug(APPER_SESSION) << "m_installPackages" << m_maxResolve << m_installPackages.size() << resolve.size(); 0217 0218 auto transaction = new PkTransaction(this); 0219 Transaction *t; 0220 t = Daemon::resolve(resolve, 0221 Transaction::FilterNotInstalled | Transaction::FilterArch | Transaction::FilterNewest); 0222 transaction->setupTransaction(t); 0223 setTransaction(Transaction::RoleResolve, transaction); 0224 connect(transaction, &PkTransaction::finished, this, &PkInstallCatalogs::searchFinished, Qt::UniqueConnection); 0225 connect(transaction, &PkTransaction::package, this, &PkInstallCatalogs::addPackage); 0226 } else if (!m_installProvides.isEmpty()) { 0227 // Continue resolving Install Provides 0228 QStringList provides; 0229 int count = 0; 0230 while (!m_installProvides.isEmpty() && count < m_maxResolve) { 0231 // Remove the items from the list so next call we have less 0232 provides.append(m_installProvides.takeFirst()); 0233 ++count; 0234 } 0235 qCDebug(APPER_SESSION) << "m_installProvides" << m_maxResolve << m_installProvides.size() << provides.size(); 0236 0237 auto transaction = new PkTransaction(this); 0238 Transaction *t; 0239 t = Daemon::whatProvides(provides, 0240 Transaction::FilterNotInstalled | Transaction::FilterArch | Transaction::FilterNewest); 0241 transaction->setupTransaction(t); 0242 setTransaction(Transaction::RoleWhatProvides, transaction); 0243 connect(transaction, &PkTransaction::finished, this, &PkInstallCatalogs::searchFinished, Qt::UniqueConnection); 0244 connect(transaction, &PkTransaction::package, this, &PkInstallCatalogs::addPackage); 0245 } else if (!m_installFiles.isEmpty()) { 0246 // Continue resolving Install Packages 0247 QStringList files; 0248 int count = 0; 0249 while (!m_installFiles.isEmpty() && count < m_maxResolve) { 0250 // Remove the items from the list so next call we have less 0251 files.append(m_installFiles.takeFirst()); 0252 ++count; 0253 } 0254 qCDebug(APPER_SESSION) << "m_installFiles" << m_maxResolve << m_installFiles.size() << files.size(); 0255 0256 auto transaction = new PkTransaction(this); 0257 Transaction *t; 0258 t = Daemon::searchFiles(files, 0259 Transaction::FilterNotInstalled | Transaction::FilterArch | Transaction::FilterNewest); 0260 transaction->setupTransaction(t); 0261 setTransaction(Transaction::RoleSearchFile, transaction); 0262 connect(transaction, &PkTransaction::finished, this, &PkInstallCatalogs::searchFinished, Qt::UniqueConnection); 0263 connect(transaction, &PkTransaction::package, this, &PkInstallCatalogs::addPackage); 0264 } else { 0265 // we are done resolving 0266 SessionTask::searchFinished(status); 0267 } 0268 } else { 0269 // we got an error... 0270 SessionTask::searchFinished(status); 0271 } 0272 } 0273 0274 #include "moc_PkInstallCatalogs.cpp"