summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/createshortcutoperation.cpp
diff options
context:
space:
mode:
authorkh1 <karsten.heimrich@digia.com>2012-10-25 17:50:08 +0200
committerKarsten Heimrich <karsten.heimrich@digia.com>2012-10-29 08:55:42 +0100
commit0693cfb66dafd9d898d16a7394c7bb22f5ce91da (patch)
treeab6c98a95a19ca985949b466b80ac6244794a4c1 /src/libs/installer/createshortcutoperation.cpp
parent84c839be72671cfcc4e0babe62f1321fa6472151 (diff)
Make sure we remove all directories we created, nothing more.
Special case on windows, if we created a folder inside the start menu, try as long as we fail to remove all empty directories. Change-Id: Idf67a43cbbcfc44746438c523a63def0e07e7de9 Reviewed-by: Niels Weber <niels.weber@digia.com> Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
Diffstat (limited to 'src/libs/installer/createshortcutoperation.cpp')
-rw-r--r--src/libs/installer/createshortcutoperation.cpp105
1 files changed, 69 insertions, 36 deletions
diff --git a/src/libs/installer/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp
index 2dc035721..0eebc9bcd 100644
--- a/src/libs/installer/createshortcutoperation.cpp
+++ b/src/libs/installer/createshortcutoperation.cpp
@@ -32,9 +32,11 @@
#include "createshortcutoperation.h"
#include "fileutils.h"
+#include "utils.h"
#include <QDebug>
#include <QDir>
+#include <QSettings>
#include <cerrno>
@@ -59,6 +61,31 @@ struct DeCoInitializer
};
#endif
+struct StartsWithWorkingDirectory
+{
+ bool operator()(const QString &s)
+ {
+ return s.startsWith(QLatin1String("workingDirectory="));
+ }
+};
+
+static QString parentDirectory(const QString &current)
+{
+ return current.mid(0, current.lastIndexOf(QLatin1Char('/')));
+}
+
+static QString takeWorkingDirArgument(QStringList &args)
+{
+ // if the arguments contain an option in the form "workingDirectory=...", find it and consume it
+ QStringList::iterator wdiropt = std::find_if (args.begin(), args.end(), StartsWithWorkingDirectory());
+ if (wdiropt == args.end())
+ return QString();
+
+ const QString workingDir = wdiropt->mid(QString::fromLatin1("workingDirectory=").size());
+ args.erase(wdiropt);
+ return workingDir;
+}
+
static bool createLink(const QString &fileName, const QString &linkName, QString workingDir,
QString arguments = QString())
{
@@ -78,6 +105,7 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl)))
return success;
+ // TODO: implement this server side, since there's not Qt equivalent to set working dir and arguments
psl->SetPath((wchar_t *)QDir::toNativeSeparators(fileName).utf16());
psl->SetWorkingDirectory((wchar_t *)workingDir.utf16());
if (!arguments.isNull())
@@ -96,34 +124,26 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
return success;
}
-/*
-TRANSLATOR QInstaller::CreateShortcutOperation
-*/
+
+// -- CreateShortcutOperation
CreateShortcutOperation::CreateShortcutOperation()
{
setName(QLatin1String("CreateShortcut"));
}
-static bool isWorkingDirOption(const QString &s)
+void CreateShortcutOperation::backup()
{
- return s.startsWith(QLatin1String("workingDirectory="));
-}
+ QDir linkPath(QFileInfo(arguments().at(1)).absolutePath());
-static QString takeWorkingDirArgument(QStringList &args)
-{
- QString workingDir;
- // if the args contain an option in the form "workingDirectory=...", find it and consume it
- QStringList::iterator wdiropt = std::find_if(args.begin(), args.end(), isWorkingDirOption);
- if (wdiropt != args.end()) {
- workingDir = wdiropt->mid(QString::fromLatin1("workingDirectory=").size());
- args.erase(wdiropt);
+ QStringList directoriesToCreate;
+ while (!linkPath.exists() && linkPath != QDir::root()) {
+ const QString absolutePath = linkPath.absolutePath();
+ directoriesToCreate.append(absolutePath);
+ linkPath = parentDirectory(absolutePath);
}
- return workingDir;
-}
-void CreateShortcutOperation::backup()
-{
+ setValue(QLatin1String("createddirs"), directoriesToCreate);
}
bool CreateShortcutOperation::performOperation()
@@ -138,8 +158,8 @@ bool CreateShortcutOperation::performOperation()
return false;
}
- const QString& linkTarget = args.at(0);
- const QString& linkLocation = args.at(1);
+ const QString linkTarget = args.at(0);
+ const QString linkLocation = args.at(1);
const QString targetArguments = args.value(2); //used value because it could be not existing
const QString linkPath = QFileInfo(linkLocation).absolutePath();
@@ -154,7 +174,6 @@ bool CreateShortcutOperation::performOperation()
return false;
}
-
//remove a possible existing older one
QString errorString;
if (QFile::exists(linkLocation) && !deleteFileNowOrLater(linkLocation, &errorString)) {
@@ -176,26 +195,40 @@ bool CreateShortcutOperation::performOperation()
bool CreateShortcutOperation::undoOperation()
{
- const QStringList args = arguments();
-
- const QString& linkLocation = args.at(1);
-
- // first remove the link
- if (!deleteFileNowOrLater(linkLocation))
+ const QString &linkLocation = arguments().at(1);
+ if (!deleteFileNowOrLater(linkLocation) )
qDebug() << "Can't delete:" << linkLocation;
- const QString linkPath = QFileInfo(linkLocation).absolutePath();
-
- QStringList pathParts = QString(linkPath).remove(QDir::homePath()).split(QLatin1String("/"));
- for (int i = pathParts.count(); i > 0; --i) {
- QString possibleToDeleteDir = QDir::homePath() + QStringList(pathParts.mid(0, i)).join(QLatin1String("/"));
- QInstaller::removeSystemGeneratedFiles(possibleToDeleteDir);
- if (!possibleToDeleteDir.isEmpty() && QDir().rmdir(possibleToDeleteDir))
- qDebug() << "Deleted directory:" << possibleToDeleteDir;
- else
+ QDir dir; // remove all directories we created
+ const QStringList directoriesToDelete = value(QLatin1String("createddirs")).toStringList();
+ foreach (const QString &directory, directoriesToDelete) {
+ QInstaller::removeSystemGeneratedFiles(directory);
+ if (!dir.rmdir(directory))
break;
}
+#ifdef Q_OS_WIN
+ // special case on windows, multiple installations might leave empty folder inside the start menu
+ QSettings user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\User Shell Folders"), QSettings::NativeFormat);
+ QSettings system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\Shell Folders"), QSettings::NativeFormat);
+
+ const QString userStartMenu = QDir::fromNativeSeparators(replaceWindowsEnvironmentVariables(user
+ .value(QLatin1String("Programs"), QString()).toString())).toLower();
+ const QString systemStartMenu = QDir::fromNativeSeparators(system.value(QLatin1String("Common Programs"))
+ .toString()).toLower();
+
+ // try to remove every empty folder until we fail
+ QString linkPath = QFileInfo(linkLocation).absolutePath().toLower();
+ if (linkPath.startsWith(userStartMenu) || linkPath.startsWith(systemStartMenu)) {
+ QInstaller::removeSystemGeneratedFiles(linkPath);
+ while (QDir().rmdir(linkPath)) {
+ linkPath = parentDirectory(linkPath);
+ QInstaller::removeSystemGeneratedFiles(linkPath);
+ }
+ }
+#endif
return true;
}