Commit 925182ff authored by ck's avatar ck
Browse files

Maemo: Create .desktop files for all application (sub-)projects.

parent e7a8cad1
...@@ -161,10 +161,8 @@ bool MaemoPackageCreationStep::createPackage() ...@@ -161,10 +161,8 @@ bool MaemoPackageCreationStep::createPackage()
.arg(debianDirPath)); .arg(debianDirPath));
return false; return false;
} }
const QString templatesDirPath const QString templatesDirPath = MaemoTemplatesManager::instance()
= buildConfiguration()->target()->project()->projectDirectory() ->debianDirPath(buildConfiguration()->target()->project());
+ QLatin1Char('/') + MaemoTemplatesManager::PackagingDirName
+ QLatin1String("/debian");
QDir templatesDir(templatesDirPath); QDir templatesDir(templatesDirPath);
const QStringList &files = templatesDir.entryList(QDir::Files); const QStringList &files = templatesDir.entryList(QDir::Files);
foreach (const QString &fileName, files) { foreach (const QString &fileName, files) {
......
...@@ -58,9 +58,10 @@ namespace Internal { ...@@ -58,9 +58,10 @@ namespace Internal {
namespace { namespace {
const QByteArray IconFieldName("XB-Maemo-Icon-26:"); const QByteArray IconFieldName("XB-Maemo-Icon-26:");
const QString MaemoDirName("maemo");
const QString PackagingDirName = MaemoDirName + QLatin1Char('/') + ("packaging");
} // anonymous namespace } // anonymous namespace
const QLatin1String MaemoTemplatesManager::PackagingDirName("packaging");
MaemoTemplatesManager *MaemoTemplatesManager::m_instance = 0; MaemoTemplatesManager *MaemoTemplatesManager::m_instance = 0;
...@@ -80,7 +81,7 @@ MaemoTemplatesManager::MaemoTemplatesManager(QObject *parent) : QObject(parent) ...@@ -80,7 +81,7 @@ MaemoTemplatesManager::MaemoTemplatesManager(QObject *parent) : QObject(parent)
this, SLOT(handleActiveProjectChanged(ProjectExplorer::Project*))); this, SLOT(handleActiveProjectChanged(ProjectExplorer::Project*)));
connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
this, SLOT(handleProjectToBeRemoved(ProjectExplorer::Project*))); this, SLOT(handleProjectToBeRemoved(ProjectExplorer::Project*)));
handleActiveProjectChanged(session->startupProject()); handleActiveProjectChanged(session->startupProject());
} }
void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project *project) void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project *project)
...@@ -91,43 +92,51 @@ void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project ...@@ -91,43 +92,51 @@ void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project
connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
this, SLOT(handleTarget(ProjectExplorer::Target*))); this, SLOT(handleTarget(ProjectExplorer::Target*)));
const QList<Target *> &targets = project->targets(); const QList<Target *> &targets = project->targets();
foreach (Target * const target, targets) foreach (Target * const target, targets) {
handleTarget(target); if (handleTarget(target)) {
QFileSystemWatcher * const fsWatcher
= new QFileSystemWatcher(this);
fsWatcher->addPath(debianDirPath(project));
fsWatcher->addPath(changeLogFilePath(project));
fsWatcher->addPath(controlFilePath(project));
connect(fsWatcher, SIGNAL(directoryChanged(QString)), this,
SLOT(handleDebianDirContentsChanged()));
connect(fsWatcher, SIGNAL(fileChanged(QString)), this,
SLOT(handleDebianFileChanged(QString)));
handleDebianDirContentsChanged();
handleDebianFileChanged(changeLogFilePath(project));
handleDebianFileChanged(controlFilePath(project));
connect(qobject_cast<Qt4Project *>(project),
SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(handleProFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
Qt::QueuedConnection);
m_maemoProjects.insert(project, fsWatcher);
}
}
} }
} }
void MaemoTemplatesManager::handleTarget(ProjectExplorer::Target *target) bool MaemoTemplatesManager::handleTarget(ProjectExplorer::Target *target)
{ {
if (!target if (!target
|| target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID)) || target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID))
return; return false;
if (!createTemplatesIfNecessary(target)) if (!createDebianTemplatesIfNecessary(target))
return; return false;
if (!syncDesktopFiles(target))
Project * const project = target->project(); return false;
QFileSystemWatcher * const fsWatcher = new QFileSystemWatcher(this); return true;
fsWatcher->addPath(debianDirPath(project));
fsWatcher->addPath(changeLogFilePath(project));
fsWatcher->addPath(controlFilePath(project));
connect(fsWatcher, SIGNAL(directoryChanged(QString)), this,
SLOT(handleDebianDirContentsChanged()));
connect(fsWatcher, SIGNAL(fileChanged(QString)), this,
SLOT(handleDebianFileChanged(QString)));
handleDebianDirContentsChanged();
handleDebianFileChanged(changeLogFilePath(project));
handleDebianFileChanged(controlFilePath(project));
m_maemoProjects.insert(project, fsWatcher);
} }
bool MaemoTemplatesManager::createTemplatesIfNecessary(const ProjectExplorer::Target *target) bool MaemoTemplatesManager::createDebianTemplatesIfNecessary(const ProjectExplorer::Target *target)
{ {
Project * const project = target->project(); Project * const project = target->project();
QDir projectDir(project->projectDirectory()); QDir projectDir(project->projectDirectory());
if (projectDir.exists(PackagingDirName)) if (projectDir.exists(MaemoDirName))
return true; return true;
const QString packagingTemplatesDir const QString packagingTemplatesDir
= projectDir.path() + QLatin1Char('/') + PackagingDirName; = projectDir.path() + QLatin1Char('/') + PackagingDirName;
if (!projectDir.mkdir(PackagingDirName)) { if (!projectDir.mkpath(PackagingDirName)) {
raiseError(tr("Could not create directory '%1'.") raiseError(tr("Could not create directory '%1'.")
.arg(QDir::toNativeSeparators(packagingTemplatesDir))); .arg(QDir::toNativeSeparators(packagingTemplatesDir)));
return false; return false;
...@@ -207,6 +216,80 @@ bool MaemoTemplatesManager::createTemplatesIfNecessary(const ProjectExplorer::Ta ...@@ -207,6 +216,80 @@ bool MaemoTemplatesManager::createTemplatesIfNecessary(const ProjectExplorer::Ta
return true; return true;
} }
bool MaemoTemplatesManager::syncDesktopFiles(const ProjectExplorer::Target *target)
{
const QByteArray desktopTemplate("[Desktop Entry]\nEncoding=UTF-8\n"
"Version=1.0\nType=Application\nTerminal=false\nName=topx\nExec=\n"
"Icon=\nX-Window-Icon=\nX-HildonDesk-ShowInToolbar=true\n"
"X-Osso-Type=application/x-executable\n");
const Qt4Target * const qt4Target = qobject_cast<const Qt4Target *>(target);
Q_ASSERT_X(qt4Target, Q_FUNC_INFO,
"Impossible: Target has Maemo id, but could not be cast to Qt4Target.");
const QList<Qt4ProFileNode *> &applicationProjects
= qt4Target->qt4Project()->applicationProFiles();
QList<QString> applicationProjectNames;
foreach (const Qt4ProFileNode * const subProject, applicationProjects)
applicationProjectNames << subProject->displayName();
const QString maemoDirPath = target->project()->projectDirectory()
+ QLatin1Char('/') + MaemoDirName;
QDir maemoDir(maemoDirPath);
const QStringList &desktopFiles
= maemoDir.entryList(QStringList() << QLatin1String("*.desktop"),
QDir::Files);
QStringList filesToAdd;
QStringList filesToRemove;
// Step 1: Remove all desktop files that refer to projects that don't exist anymore.
foreach (const QString &desktopFile, desktopFiles) {
const QString projectName = QFileInfo(desktopFile).completeBaseName();
if (!applicationProjectNames.contains(projectName)) {
const QString &absFilePath
= maemoDirPath + QLatin1Char('/') + desktopFile;
if (!QFile::remove(absFilePath)) {
qWarning("Failed to remove outdated project file %s.",
qPrintable(absFilePath));
}
filesToRemove << absFilePath;
}
}
// Step 2: Create a desktop file for every project that doesn't have one.
foreach (const QString &projectName, applicationProjectNames) {
const QString &desktopFileName
= projectName + QLatin1String(".desktop");
if (!desktopFiles.contains(desktopFileName)) {
const QString &absFilePath
= maemoDirPath + QLatin1Char('/') + desktopFileName;
QFile desktopFile(absFilePath);
if (!desktopFile.open(QIODevice::WriteOnly)) {
qWarning("Failed to create desktop file %s",
qPrintable(absFilePath));
continue;
}
filesToAdd << absFilePath;
if (desktopFile.write(desktopTemplate) != desktopTemplate.length()) {
qWarning("Failed to write to desktop file %s",
qPrintable(absFilePath));
continue;
}
}
}
if (!filesToAdd.isEmpty()) {
qt4Target->qt4Project()->rootProjectNode()
->addFiles(UnknownFileType, filesToAdd);
}
if (!filesToRemove.isEmpty()) {
qt4Target->qt4Project()->rootProjectNode()
->removeFiles(UnknownFileType, filesToRemove);
}
// TODO: Step 3: update the "Name" and "Exec" entries of all desktop files (name = subproject displayname, path = rhs of deployable)
return true;
}
void MaemoTemplatesManager::handleProjectToBeRemoved(ProjectExplorer::Project *project) void MaemoTemplatesManager::handleProjectToBeRemoved(ProjectExplorer::Project *project)
{ {
MaemoProjectMap::Iterator it = m_maemoProjects.find(project); MaemoProjectMap::Iterator it = m_maemoProjects.find(project);
...@@ -216,6 +299,23 @@ void MaemoTemplatesManager::handleProjectToBeRemoved(ProjectExplorer::Project *p ...@@ -216,6 +299,23 @@ void MaemoTemplatesManager::handleProjectToBeRemoved(ProjectExplorer::Project *p
} }
} }
void MaemoTemplatesManager::handleProFileUpdated(Qt4ProFileNode *proFileNode)
{
for (MaemoProjectMap::ConstIterator it = m_maemoProjects.begin();
it != m_maemoProjects.end(); ++it) {
const Qt4Project * const project = qobject_cast<Qt4Project *>(it.key());
if (isParent(project->rootProjectNode(), proFileNode)) {
// We assume here that the project configuratiion is identical for
// all Maemo targets. If that is not the case (e.g. the user has
// configured different deployment paths for Maemo5 vs. Maemo6,
// we can do things slightly wrong.
syncDesktopFiles(project->activeTarget());
break;
}
}
}
QString MaemoTemplatesManager::version(const Project *project, QString MaemoTemplatesManager::version(const Project *project,
QString *error) const QString *error) const
{ {
...@@ -431,5 +531,18 @@ Project *MaemoTemplatesManager::findProject(const QFileSystemWatcher *fsWatcher) ...@@ -431,5 +531,18 @@ Project *MaemoTemplatesManager::findProject(const QFileSystemWatcher *fsWatcher)
return 0; return 0;
} }
bool MaemoTemplatesManager::isParent(const ProjectNode *parent,
const ProjectNode *child) const
{
if (parent == child)
return true;
const QList<ProjectNode *> &directChildren = parent->subProjectNodes();
foreach (const ProjectNode * directChild, directChildren) {
if (isParent(directChild, child))
return true;
}
return false;
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager
...@@ -40,11 +40,15 @@ QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher); ...@@ -40,11 +40,15 @@ QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher);
namespace ProjectExplorer { namespace ProjectExplorer {
class Project; class Project;
class ProjectNode;
class Target; class Target;
} }
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
class Qt4Project;
namespace Internal { namespace Internal {
class Qt4ProFileNode;
class MaemoTemplatesManager : public QObject class MaemoTemplatesManager : public QObject
{ {
...@@ -66,8 +70,6 @@ public: ...@@ -66,8 +70,6 @@ public:
bool setPackageManagerIcon(const ProjectExplorer::Project *project, bool setPackageManagerIcon(const ProjectExplorer::Project *project,
const QString &iconFilePath, QString *error) const; const QString &iconFilePath, QString *error) const;
static const QLatin1String PackagingDirName;
signals: signals:
void debianDirContentsChanged(const ProjectExplorer::Project *project); void debianDirContentsChanged(const ProjectExplorer::Project *project);
void changeLogChanged(const ProjectExplorer::Project *project); void changeLogChanged(const ProjectExplorer::Project *project);
...@@ -75,18 +77,22 @@ signals: ...@@ -75,18 +77,22 @@ signals:
private slots: private slots:
void handleActiveProjectChanged(ProjectExplorer::Project *project); void handleActiveProjectChanged(ProjectExplorer::Project *project);
void handleTarget(ProjectExplorer::Target *target); bool handleTarget(ProjectExplorer::Target *target);
void handleDebianDirContentsChanged(); void handleDebianDirContentsChanged();
void handleDebianFileChanged(const QString &filePath); void handleDebianFileChanged(const QString &filePath);
void handleProjectToBeRemoved(ProjectExplorer::Project *project); void handleProjectToBeRemoved(ProjectExplorer::Project *project);
void handleProFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *proFileNode);
private: private:
explicit MaemoTemplatesManager(QObject *parent); explicit MaemoTemplatesManager(QObject *parent);
void raiseError(const QString &reason); void raiseError(const QString &reason);
QString changeLogFilePath(const ProjectExplorer::Project *project) const; QString changeLogFilePath(const ProjectExplorer::Project *project) const;
QString controlFilePath(const ProjectExplorer::Project *project) const; QString controlFilePath(const ProjectExplorer::Project *project) const;
bool createTemplatesIfNecessary(const ProjectExplorer::Target *target); bool createDebianTemplatesIfNecessary(const ProjectExplorer::Target *target);
bool syncDesktopFiles(const ProjectExplorer::Target *target);
ProjectExplorer::Project *findProject(const QFileSystemWatcher *fsWatcher) const; ProjectExplorer::Project *findProject(const QFileSystemWatcher *fsWatcher) const;
bool isParent(const ProjectExplorer::ProjectNode *parent,
const ProjectExplorer::ProjectNode *child) const;
QSharedPointer<QFile> openFile(const QString &filePath, QSharedPointer<QFile> openFile(const QString &filePath,
QIODevice::OpenMode mode, QString *error) const; QIODevice::OpenMode mode, QString *error) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment