diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.cpp
index 1e84cfdf055ad558509c6a7cfba204ae856f9827..920a3408e9d511726a1d445c1a93ccf158c0f932 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.cpp
@@ -41,21 +41,6 @@
 #include <QtCore/QFile>
 #include <QtCore/QFileInfo>
 
-namespace {
-    QString pathVar(const QString &var)
-    {
-        return var + QLatin1String(".path");
-    }
-
-    QString filesVar(const QString &var)
-    {
-        return var + QLatin1String(".files");
-    }
-
-    const QLatin1String InstallsVar("INSTALLS");
-    const QLatin1String TargetVar("target");
-}
-
 namespace Qt4ProjectManager {
 namespace Internal {
 
@@ -77,35 +62,8 @@ bool MaemoPackageContents::buildModel() const
     m_deployables.clear();
     QSharedPointer<ProFileWrapper> proFileWrapper
         = m_packageStep->proFileWrapper();
-    const QStringList &elemList = proFileWrapper->varValues(InstallsVar);
-    bool targetFound = false;
-    foreach (const QString &elem, elemList) {
-        const QStringList &paths = proFileWrapper->varValues(pathVar(elem));
-        if (paths.count() != 1) {
-            qWarning("Error: Variable %s has %d values.",
-                qPrintable(pathVar(elem)), paths.count());
-            continue;
-        }
-
-        const QStringList &files = proFileWrapper->varValues(filesVar(elem));
-        if (files.isEmpty() && elem != TargetVar) {
-            qWarning("Error: Variable %s has no RHS.",
-                qPrintable(filesVar(elem)));
-            continue;
-        }
-
-        if (elem == TargetVar) {
-            m_deployables.prepend(MaemoDeployable(m_packageStep->localExecutableFilePath(),
-                paths.first()));
-            targetFound = true;
-        } else {
-            foreach (const QString &file, files)
-                m_deployables << MaemoDeployable(
-                    proFileWrapper->absFilePath(file), paths.first());
-        }
-    }
-
-    if (!targetFound) {
+    const ProFileWrapper::InstallsList &installs = proFileWrapper->installs();
+    if (installs.targetPath.isEmpty()) {
         const Qt4ProFileNode * const proFileNode
             = m_packageStep->qt4BuildConfiguration()->qt4Target()
                 ->qt4Project()->rootProjectNode();
@@ -114,16 +72,23 @@ bool MaemoPackageContents::buildModel() const
             : QLatin1String("/usr/local/bin");
         m_deployables.prepend(MaemoDeployable(m_packageStep->localExecutableFilePath(),
             remoteDir));
-
-        if (!proFileWrapper->addVarValue(pathVar(TargetVar), remoteDir)
-            || !proFileWrapper->addVarValue(InstallsVar, TargetVar)) {
+        if (!proFileWrapper->addInstallsTarget(remoteDir)) {
             qWarning("Error updating .pro file.");
             return false;
         }
+    } else {
+        m_deployables.prepend(MaemoDeployable(m_packageStep->localExecutableFilePath(),
+            installs.targetPath));
+    }
+    foreach (const ProFileWrapper::InstallsElem &elem, installs.normalElems) {
+        foreach (const QString &file, elem.files) {
+            m_deployables << MaemoDeployable(proFileWrapper->absFilePath(file),
+                elem.path);
+        }
     }
 
     m_initialized = true;
-    m_modified = true;
+    m_modified = true; // ???
     return true;
 }
 
@@ -140,14 +105,12 @@ bool MaemoPackageContents::addDeployable(const MaemoDeployable &deployable,
         *error = tr("File already in list.");
         return false;
     }
-    const QSharedPointer<ProFileWrapper> proFileWrapper
-        = m_packageStep->proFileWrapper();
-    QCryptographicHash elemHash(QCryptographicHash::Md5);
-    elemHash.addData(deployable.localFilePath.toUtf8());
-    const QString elemName = QString::fromAscii(elemHash.result().toHex());
-    proFileWrapper->addFile(filesVar(elemName), deployable.localFilePath);
-    proFileWrapper->addVarValue(pathVar(elemName), deployable.remoteDir);
-    proFileWrapper->addVarValue(InstallsVar, elemName);
+
+    if (!m_packageStep->proFileWrapper()->addInstallsElem(deployable.remoteDir,
+        deployable.localFilePath)) {
+        *error = tr("Failed to update .pro file.");
+        return false;
+    }
 
     beginInsertRows(QModelIndex(), rowCount(), rowCount());
     m_deployables << deployable;
@@ -160,32 +123,14 @@ bool MaemoPackageContents::removeDeployableAt(int row, QString *error)
     Q_ASSERT(row > 0 && row < rowCount());
 
     const MaemoDeployable &deployable = deployableAt(row);
-    const QString elemToRemove = findInstallsElem(deployable);
-    if (elemToRemove.isEmpty()) {
-        *error = tr("Inconsistent model: Deployable not found in  .pro file.");
-        return false;
-    }
-
-    const QString &filesVarName = filesVar(elemToRemove);
-    QSharedPointer<ProFileWrapper> proFileWrapper
-        = m_packageStep->proFileWrapper();
-    const bool isOnlyElem
-        = proFileWrapper->varValues(filesVarName).count() == 1;
-    bool success
-        = proFileWrapper->removeFile(filesVarName, deployable.localFilePath);
-    if (success && isOnlyElem) {
-        success = proFileWrapper->removeVarValue(pathVar(elemToRemove),
-            deployable.remoteDir);
-        if (success)
-            success = proFileWrapper->removeVarValue(InstallsVar, elemToRemove);
-    }
-    if (!success) {
-        *error = tr("Could not remove deployable from .pro file.");
+    if (!m_packageStep->proFileWrapper()
+        ->removeInstallsElem(deployable.remoteDir, deployable.localFilePath)) {
+        *error = tr("Could not update .pro file.");
         return false;
     }
 
     beginRemoveRows(QModelIndex(), row, row);
-    m_deployables.removeAt(row - 1);
+    m_deployables.removeAt(row);
     endRemoveRows();
     return true;
 }
@@ -230,19 +175,10 @@ bool MaemoPackageContents::setData(const QModelIndex &index,
         return false;
 
     MaemoDeployable &deployable = m_deployables[index.row()];
-    const QString elemToChange = findInstallsElem(deployable);
-    if (elemToChange.isEmpty()) {
-        qWarning("Error: Inconsistent model. "
-            "INSTALLS element not found in .pro file");
-        return false;
-    }
-
     const QString &newRemoteDir = value.toString();
-    QSharedPointer<ProFileWrapper> proFileWrapper
-        = m_packageStep->proFileWrapper();
-    if (!proFileWrapper->replaceVarValue(pathVar(elemToChange),
-        deployable.remoteDir, newRemoteDir)) {
-        qWarning("Error: Could not change remote path in .pro file.");
+    if (!m_packageStep->proFileWrapper()->replaceInstallPath(deployable.remoteDir,
+        deployable.localFilePath, newRemoteDir)) {
+        qWarning("Error: Could not update .pro file");
         return false;
     }
 
@@ -265,25 +201,5 @@ QString MaemoPackageContents::remoteExecutableFilePath() const
         + m_packageStep->executableFileName() : QString();
 }
 
-QString MaemoPackageContents::findInstallsElem(const MaemoDeployable &deployable) const
-{
-    QSharedPointer<ProFileWrapper> proFileWrapper
-        = m_packageStep->proFileWrapper();
-    const QStringList &elems = proFileWrapper->varValues(InstallsVar);
-    foreach (const QString &elem, elems) {
-        const QStringList elemPaths = proFileWrapper->varValues(pathVar(elem));
-        if (elemPaths.count() != 1 || elemPaths.first() != deployable.remoteDir)
-            continue;
-        if (elem == TargetVar)
-            return elem;
-        const QStringList elemFiles = proFileWrapper->varValues(filesVar(elem));
-        foreach (const QString &file, elemFiles) {
-            if (proFileWrapper->absFilePath(file) == deployable.localFilePath)
-                return elem;
-        }
-    }
-    return QString();
-}
-
 } // namespace Qt4ProjectManager
 } // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.h
index 079cd325a9dc46f1c7227f0ae42cd21334b423a6..c74f4c1fd841c3104a99399935f603206db09173 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecontents.h
@@ -87,9 +87,6 @@ private:
                          int role = Qt::EditRole);
 
     bool buildModel() const;
-    void resetProFileContents() const;
-
-    QString findInstallsElem(const MaemoDeployable &deployable) const;
 
     const MaemoPackageCreationStep * const m_packageStep;
     mutable QList<MaemoDeployable> m_deployables;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.cpp b/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.cpp
index 392660006568d2281e0f7c8df77276065585ef4f..e874972e64171e29b1acba39db96f12c4ed36d06 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.cpp
@@ -3,12 +3,29 @@
 #include <prowriter.h>
 #include <qt4projectmanager/profilereader.h>
 
+#include <QtCore/QCryptographicHash>
 #include <QtCore/QFile>
 #include <QtCore/QFileInfo>
 
 namespace Qt4ProjectManager {
 namespace Internal {
 
+namespace {
+    QString pathVar(const QString &var)
+    {
+        return var + QLatin1String(".path");
+    }
+
+    QString filesVar(const QString &var)
+    {
+        return var + QLatin1String(".files");
+    }
+
+    const QLatin1String InstallsVar("INSTALLS");
+    const QLatin1String TargetVar("target");
+}
+
+
 ProFileWrapper::ProFileWrapper(const QString &proFileName)
     : m_proFileName(proFileName), m_proDir(QFileInfo(m_proFileName).dir()),
       m_proFileOption(new ProFileOption)
@@ -18,6 +35,100 @@ ProFileWrapper::ProFileWrapper(const QString &proFileName)
 
 ProFileWrapper::~ProFileWrapper() {}
 
+
+ProFileWrapper::InstallsList ProFileWrapper::installs() const
+{
+    InstallsList list;
+
+    const QStringList &elemList = varValues(InstallsVar);
+    foreach (const QString &elem, elemList) {
+        const QStringList &paths = varValues(pathVar(elem));
+        if (paths.count() != 1) {
+            qWarning("Error: Variable %s has %d values.",
+                qPrintable(pathVar(elem)), paths.count());
+            continue;
+        }
+
+        const QStringList &files = varValues(filesVar(elem));
+
+        if (elem == TargetVar) {
+            if (!list.targetPath.isEmpty()) {
+                qWarning("Error: More than one target in INSTALLS list.");
+                continue;
+            }
+            list.targetPath = paths.first();
+        } else {
+            if (files.isEmpty()) {
+                qWarning("Error: Variable %s has no RHS.",
+                    qPrintable(filesVar(elem)));
+                continue;
+            }
+            list.normalElems << InstallsElem(elem, paths.first(), files);
+        }
+    }
+
+    return list;
+}
+
+bool ProFileWrapper::addInstallsElem(const QString &path,
+    const QString &absFilePath, const QString &var)
+{
+    QString varName = var;
+    if (varName.isEmpty()) {
+        QCryptographicHash elemHash(QCryptographicHash::Md5);
+        elemHash.addData(absFilePath.toUtf8());
+        varName = QString::fromAscii(elemHash.result().toHex());
+    }
+
+    // TODO: Use lower-level calls here to make operation atomic.
+    if (varName != TargetVar && !addFile(filesVar(varName), absFilePath))
+        return false;
+    return addVarValue(pathVar(varName), path)
+        && addVarValue(InstallsVar, varName);
+}
+
+bool ProFileWrapper::addInstallsTarget(const QString &path)
+{
+    return addInstallsElem(path, QString(), TargetVar);
+}
+
+bool ProFileWrapper::removeInstallsElem(const QString &path,
+    const QString &file)
+{
+    const InstallsElem &elem = findInstallsElem(path, file);
+    if (elem.varName.isEmpty())
+        return false;
+
+    // TODO: Use lower-level calls here to make operation atomic.
+    if (elem.varName != TargetVar && !removeFile(filesVar(elem.varName), file))
+        return false;
+    if (elem.files.count() <= 1) {
+        if (!removeVarValue(pathVar(elem.varName), path))
+            return false;
+        if (!removeVarValue(InstallsVar, elem.varName))
+            return false;
+    }
+    return true;
+}
+
+bool ProFileWrapper::replaceInstallPath(const QString &oldPath,
+    const QString &file, const QString &newPath)
+{
+    const InstallsElem &elem = findInstallsElem(oldPath, file);
+    if (elem.varName.isEmpty())
+        return false;
+
+    // Simple case: Variable has only one file, so just replace the path.
+    if (elem.varName == TargetVar || elem.files.count() == 1)
+        return replaceVarValue(pathVar(elem.varName), oldPath, newPath);
+
+    // Complicated case: Variable has other files, so remove our file from it
+    // and introduce a new one.
+    if (!removeInstallsElem(oldPath, file))
+        return false;
+    return addInstallsElem(newPath, file);
+}
+
 QStringList ProFileWrapper::varValues(const QString &var) const
 {
     return m_proFileReader->values(var, m_proFile);
@@ -155,5 +266,24 @@ bool ProFileWrapper::readProFileContents()
     return true;
 }
 
+ProFileWrapper::InstallsElem ProFileWrapper::findInstallsElem(const QString &path,
+    const QString &file) const
+{
+    const QStringList &elems = varValues(InstallsVar);
+    foreach (const QString &elem, elems) {
+        const QStringList &elemPaths = varValues(pathVar(elem));
+        if (elemPaths.count() != 1 || elemPaths.first() != path)
+            continue;
+        if (elem == TargetVar)
+            return InstallsElem(elem, path, QStringList());
+        const QStringList &elemFiles = varValues(filesVar(elem));
+        foreach (const QString &elemFile, elemFiles) {
+            if (absFilePath(elemFile) == file)
+                return InstallsElem(elem, path, elemFiles);
+        }
+    }
+    return InstallsElem(QString(), QString(), QStringList());
+}
+
 } // namespace Internal
 } // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.h b/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.h
index 60a72c30c097ca95c03546d965d455b534dc9428..e82c03c2231762d91a7924bd79f8f8ebb8d7bb7a 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/profilewrapper.h
@@ -21,7 +21,29 @@ public:
     ProFileWrapper(const QString &proFileName);
     ~ProFileWrapper();
 
-    // TODO: Higher-level versions of these specifically for INSTALLS vars
+    struct InstallsElem {
+        InstallsElem(QString v, QString p, QStringList f)
+            : varName(v), path(p), files(f) {}
+        QString varName;
+        QString path;
+        QStringList files;
+    };
+
+    struct InstallsList {
+        QString targetPath;
+        QList<InstallsElem> normalElems;
+    };
+
+    // High-level functions for dealing with INSTALLS stuff.
+    InstallsList installs() const;
+    bool addInstallsElem(const QString &path, const QString &file,
+        const QString &var = QString()); // Empty var means make the name up.
+    bool addInstallsTarget(const QString &path);
+    bool removeInstallsElem(const QString &path, const QString &file);
+    bool replaceInstallPath(const QString &oldPath, const QString &file,
+        const QString &newPath);
+
+    // Lower-level functions working on arbitrary variables.
     QStringList varValues(const QString &var) const;
     bool addVarValue(const QString &var, const QString &value);
     bool addFile(const QString &var, const QString &absFilePath);
@@ -29,6 +51,7 @@ public:
     bool removeFile(const QString &var, const QString &absFilePath);
     bool replaceVarValue(const QString &var, const QString &oldValue,
         const QString &newValue);
+
     QString absFilePath(const QString &relFilePath) const;
 
 private:
@@ -36,6 +59,8 @@ private:
     void parseProFile(ParseType type) const;
     bool writeProFileContents();
     bool readProFileContents();
+    InstallsElem findInstallsElem(const QString &path,
+        const QString &file) const;
 
     const QString m_proFileName;
     const QDir m_proDir;