diff --git a/src/core/engine.cpp b/src/core/engine.cpp --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -679,12 +679,10 @@ emit signalEntryChanged(entry); qCDebug(KNEWSTUFFCORE) << "about to uninstall entry " << entry.uniqueId(); - // FIXME: change the status? m_installation->uninstall(actualEntryForUninstall); - entry.setStatus(KNS3::Entry::Deleted); //status for actual entry gets set in m_installation->uninstall() + entry.setStatus(actualEntryForUninstall.status()); emit signalEntryChanged(entry); - } void Engine::loadDetails(const KNSCore::EntryInternal &entry) diff --git a/src/core/installation.h b/src/core/installation.h --- a/src/core/installation.h +++ b/src/core/installation.h @@ -105,16 +105,15 @@ * * The entry instance will be updated with any new information: * * * @param entry The entry to deinstall * - * @note FIXME: I don't believe this works yet :) */ - void uninstall(KNSCore::EntryInternal entry); + void uninstall(KNSCore::EntryInternal &entry); // TODO KF6: remove, was used with deprecated Security class. #if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(5, 31) diff --git a/src/core/installation.cpp b/src/core/installation.cpp --- a/src/core/installation.cpp +++ b/src/core/installation.cpp @@ -523,7 +523,7 @@ installfile = source.fileName(); } } - QString installpath = installdir + QLatin1Char('/') + installfile; + QString installpath = QDir(installdir).filePath(installfile); qCDebug(KNEWSTUFFCORE) << "Install to file " << installpath; // FIXME: copy goes here (including overwrite checking) @@ -593,32 +593,64 @@ return ret; } -void Installation::uninstall(EntryInternal entry) +void Installation::uninstall(EntryInternal &entry) { - entry.setStatus(KNS3::Entry::Deleted); + // If all the files are removed assume that the entry got manually removed + // otherwise there would be no way to delete the entry that editing the register + bool manuallyUninstalled = true; + const auto lst = entry.installedFiles(); + for (const auto &file : lst) { + if (QFile::exists(file)) { + manuallyUninstalled = false; + break; + } + } + if (manuallyUninstalled) { + entry.setStatus(KNS3::Entry::Deleted); + emit signalEntryChanged(entry); + return; + } + // If there is an uninstall script, make sure it runs without errors if (!uninstallCommand.isEmpty()) { - const auto lst = entry.installedFiles(); for (const QString &file : lst) { QFileInfo info(file); if (info.isFile()) { QString fileArg(KShell::quoteArg(file)); QString command(uninstallCommand); command.replace(QLatin1String("%f"), fileArg); - int exitcode = QProcess::execute(command, QStringList()); + QStringList args = KShell::splitArgs(command); + const QString program = args.takeFirst(); + QProcess process; + process.start(program, args); + process.waitForFinished(-1); + + if (process.exitCode()) { + const QString processOutput = QString::fromLocal8Bit(process.readAllStandardError()); + const QString err = i18n("The uninstallation process failed to successfully run the command %1\n" + "The output of was: \n%2\n" + "If you think this is incorrect, you can continue or cancel the uninstallation process", + KShell::quoteArg(command), processOutput); + emit signalInstallationError(err); + // Ask the user if he wants to continue, even though the script failed + Question question(Question::ContinueCancelQuestion); + question.setQuestion(err); + Question::Response response = question.ask(); + if (response == Question::CancelResponse) { + // Use can delete files manually + entry.setStatus(KNS3::Entry::Installed); + emit signalEntryChanged(entry); + return; + } - if (exitcode) { - emit signalInstallationError(i18n("The uninstallation process failed to successfully run the command %1", command)); - qCCritical(KNEWSTUFFCORE) << "Command failed" << command; } else { qCDebug(KNEWSTUFFCORE) << "Command executed successfully: " << command; } } } } - const auto lst = entry.installedFiles(); for (const QString &file : lst) { if (file.endsWith(QLatin1Char('/'))) { QDir dir; @@ -649,7 +681,7 @@ } entry.setUnInstalledFiles(entry.installedFiles()); entry.setInstalledFiles(QStringList()); - + entry.setStatus(KNS3::Entry::Deleted); emit signalEntryChanged(entry); }