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;