2010-08-03 16:27:34 +02:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
|
|
|
|
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
|
**
|
|
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
|
**
|
|
|
|
|
** Commercial Usage
|
|
|
|
|
**
|
|
|
|
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
|
|
|
|
** accordance with the Qt Commercial License Agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Nokia.
|
|
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
|
**
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** If you are unsure which license is appropriate for your use, please
|
|
|
|
|
** contact the sales department at qt-sales@nokia.com.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "maemotemplatesmanager.h"
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
#include "maemodeployablelistmodel.h"
|
|
|
|
|
#include "maemodeployables.h"
|
|
|
|
|
#include "maemodeploystep.h"
|
|
|
|
|
#include "maemoglobal.h"
|
2010-08-03 16:27:34 +02:00
|
|
|
#include "maemopackagecreationstep.h"
|
|
|
|
|
#include "maemotoolchain.h"
|
|
|
|
|
|
|
|
|
|
#include <projectexplorer/project.h>
|
|
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
#include <projectexplorer/session.h>
|
|
|
|
|
#include <projectexplorer/target.h>
|
2010-08-03 17:20:34 +02:00
|
|
|
#include <qt4projectmanager/qt4nodes.h>
|
|
|
|
|
#include <qt4projectmanager/qt4project.h>
|
2010-08-03 16:27:34 +02:00
|
|
|
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
|
|
|
|
#include <qt4projectmanager/qt4target.h>
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
#include <QtCore/QBuffer>
|
2010-08-03 16:27:34 +02:00
|
|
|
#include <QtCore/QDir>
|
2010-08-04 16:38:37 +02:00
|
|
|
#include <QtCore/QFileSystemWatcher>
|
2010-08-03 16:27:34 +02:00
|
|
|
#include <QtCore/QList>
|
2010-08-05 11:22:07 +02:00
|
|
|
#include <QtGui/QPixmap>
|
2010-08-03 16:27:34 +02:00
|
|
|
#include <QtCore/QProcess>
|
|
|
|
|
#include <QtGui/QMessageBox>
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
#include <cctype>
|
|
|
|
|
|
2010-08-03 16:27:34 +02:00
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
|
|
|
|
|
namespace Qt4ProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
namespace {
|
|
|
|
|
const QByteArray IconFieldName("XB-Maemo-Icon-26:");
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
2010-08-03 16:27:34 +02:00
|
|
|
|
|
|
|
|
MaemoTemplatesManager *MaemoTemplatesManager::m_instance = 0;
|
|
|
|
|
|
|
|
|
|
MaemoTemplatesManager *MaemoTemplatesManager::instance(QObject *parent)
|
|
|
|
|
{
|
|
|
|
|
Q_ASSERT(!m_instance != !parent);
|
|
|
|
|
if (!m_instance)
|
|
|
|
|
m_instance = new MaemoTemplatesManager(parent);
|
|
|
|
|
return m_instance;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-05 15:09:23 +02:00
|
|
|
MaemoTemplatesManager::MaemoTemplatesManager(QObject *parent) : QObject(parent)
|
2010-08-03 16:27:34 +02:00
|
|
|
{
|
|
|
|
|
SessionManager * const session
|
|
|
|
|
= ProjectExplorerPlugin::instance()->session();
|
|
|
|
|
connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
|
|
|
|
|
this, SLOT(handleActiveProjectChanged(ProjectExplorer::Project*)));
|
2010-08-05 15:09:23 +02:00
|
|
|
connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
|
|
|
|
|
this, SLOT(handleProjectToBeRemoved(ProjectExplorer::Project*)));
|
2010-08-06 17:31:13 +02:00
|
|
|
handleActiveProjectChanged(session->startupProject());
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project *project)
|
|
|
|
|
{
|
2010-08-09 11:49:44 +02:00
|
|
|
if (!project || m_maemoProjects.contains(project))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
|
|
|
|
|
this, SLOT(handleTarget(ProjectExplorer::Target*)));
|
|
|
|
|
connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
|
|
|
|
|
this, SLOT(handleTarget(ProjectExplorer::Target*)));
|
|
|
|
|
const QList<Target *> &targets = project->targets();
|
|
|
|
|
foreach (Target * const target, targets)
|
|
|
|
|
handleTarget(target);
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-06 17:31:13 +02:00
|
|
|
bool MaemoTemplatesManager::handleTarget(ProjectExplorer::Target *target)
|
2010-08-03 16:27:34 +02:00
|
|
|
{
|
|
|
|
|
if (!target
|
|
|
|
|
|| target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID))
|
2010-08-06 17:31:13 +02:00
|
|
|
return false;
|
|
|
|
|
if (!createDebianTemplatesIfNecessary(target))
|
|
|
|
|
return false;
|
2010-08-09 11:49:44 +02:00
|
|
|
|
|
|
|
|
const Qt4Target * const qt4Target = qobject_cast<Qt4Target *>(target);
|
|
|
|
|
const MaemoDeployStep * const deployStep
|
|
|
|
|
= MaemoGlobal::buildStep<MaemoDeployStep>(qt4Target->activeDeployConfiguration());
|
|
|
|
|
connect(deployStep->deployables(), SIGNAL(modelsCreated()), this,
|
|
|
|
|
SLOT(handleProFileUpdated()), Qt::QueuedConnection);
|
|
|
|
|
|
|
|
|
|
Project * const project = target->project();
|
|
|
|
|
if (m_maemoProjects.contains(project))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
m_maemoProjects.insert(project, fsWatcher);
|
|
|
|
|
|
2010-08-06 17:31:13 +02:00
|
|
|
return true;
|
2010-08-05 15:09:23 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-06 17:31:13 +02:00
|
|
|
bool MaemoTemplatesManager::createDebianTemplatesIfNecessary(const ProjectExplorer::Target *target)
|
2010-08-05 15:09:23 +02:00
|
|
|
{
|
|
|
|
|
Project * const project = target->project();
|
|
|
|
|
QDir projectDir(project->projectDirectory());
|
2010-08-27 11:46:54 +02:00
|
|
|
if (projectDir.exists(QLatin1String("debian")))
|
2010-08-05 15:09:23 +02:00
|
|
|
return true;
|
2010-08-03 16:27:34 +02:00
|
|
|
|
|
|
|
|
QProcess dh_makeProc;
|
|
|
|
|
QString error;
|
2010-08-05 15:09:23 +02:00
|
|
|
const Qt4Target * const qt4Target = qobject_cast<const Qt4Target *>(target);
|
2010-08-03 16:27:34 +02:00
|
|
|
Q_ASSERT_X(qt4Target, Q_FUNC_INFO, "Target ID does not match actual type.");
|
|
|
|
|
const MaemoToolChain * const tc
|
|
|
|
|
= dynamic_cast<MaemoToolChain *>(qt4Target->activeBuildConfiguration()->toolChain());
|
|
|
|
|
Q_ASSERT_X(tc, Q_FUNC_INFO, "Maemo target has no maemo toolchain.");
|
|
|
|
|
if (!MaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, tc,
|
2010-08-27 11:46:54 +02:00
|
|
|
projectDir.path(), &error)) {
|
2010-08-03 16:27:34 +02:00
|
|
|
raiseError(error);
|
2010-08-05 15:09:23 +02:00
|
|
|
return false;
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString command = QLatin1String("dh_make -s -n -p ")
|
2010-08-06 12:57:01 +02:00
|
|
|
+ MaemoPackageCreationStep::packageName(project) + QLatin1Char('_')
|
2010-08-03 16:27:34 +02:00
|
|
|
+ MaemoPackageCreationStep::DefaultVersionNumber;
|
|
|
|
|
dh_makeProc.start(MaemoPackageCreationStep::packagingCommand(tc, command));
|
|
|
|
|
if (!dh_makeProc.waitForStarted()) {
|
|
|
|
|
raiseError(tr("Unable to create debian templates: dh_make failed (%1)")
|
|
|
|
|
.arg(dh_makeProc.errorString()));
|
2010-08-05 15:09:23 +02:00
|
|
|
return false;
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
dh_makeProc.write("\n"); // Needs user input.
|
|
|
|
|
dh_makeProc.waitForFinished(-1);
|
|
|
|
|
if (dh_makeProc.error() != QProcess::UnknownError
|
|
|
|
|
|| dh_makeProc.exitCode() != 0) {
|
|
|
|
|
raiseError(tr("Unable to create debian templates: dh_make failed (%1)")
|
|
|
|
|
.arg(dh_makeProc.errorString()));
|
2010-08-05 15:09:23 +02:00
|
|
|
return false;
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-23 14:47:28 +02:00
|
|
|
QDir debianDir(debianDirPath(project));
|
2010-08-03 17:20:34 +02:00
|
|
|
const QStringList &files = debianDir.entryList(QDir::Files);
|
|
|
|
|
QStringList filesToAddToProject;
|
|
|
|
|
foreach (const QString &fileName, files) {
|
2010-08-04 12:22:48 +02:00
|
|
|
if (fileName.endsWith(QLatin1String(".ex"), Qt::CaseInsensitive)
|
|
|
|
|
|| fileName.compare(QLatin1String("README.debian"), Qt::CaseInsensitive) == 0
|
|
|
|
|
|| fileName.compare(QLatin1String("dirs"), Qt::CaseInsensitive) == 0
|
|
|
|
|
|| fileName.compare(QLatin1String("docs"), Qt::CaseInsensitive) == 0) {
|
2010-08-03 17:20:34 +02:00
|
|
|
debianDir.remove(fileName);
|
|
|
|
|
} else
|
|
|
|
|
filesToAddToProject << debianDir.absolutePath()
|
|
|
|
|
+ QLatin1Char('/') + fileName;
|
|
|
|
|
}
|
2010-08-05 15:09:23 +02:00
|
|
|
qobject_cast<Qt4Project *>(project)->rootProjectNode()
|
2010-08-03 17:20:34 +02:00
|
|
|
->addFiles(UnknownFileType, filesToAddToProject);
|
2010-08-03 16:27:34 +02:00
|
|
|
|
2010-08-23 14:47:28 +02:00
|
|
|
return adaptRulesFile(project) && adaptControlFile(project);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MaemoTemplatesManager::adaptRulesFile(const Project *project)
|
|
|
|
|
{
|
|
|
|
|
const QString rulesFilePath = debianDirPath(project) + "/rules";
|
2010-08-03 16:27:34 +02:00
|
|
|
QFile rulesFile(rulesFilePath);
|
|
|
|
|
if (!rulesFile.open(QIODevice::ReadWrite)) {
|
|
|
|
|
raiseError(tr("Packaging Error: Cannot open file '%1'.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(rulesFilePath)));
|
2010-08-05 15:09:23 +02:00
|
|
|
return false;
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
QByteArray rulesContents = rulesFile.readAll();
|
|
|
|
|
rulesContents.replace("DESTDIR", "INSTALL_ROOT");
|
|
|
|
|
rulesContents.replace("dh_shlibdeps", "# dh_shlibdeps");
|
2010-08-19 17:37:49 +02:00
|
|
|
rulesContents.replace("dh_strip", "# dh_strip");
|
2010-08-27 13:37:45 +02:00
|
|
|
rulesContents.replace("$(MAKE) clean", "# $(MAKE) clean");
|
|
|
|
|
const Qt4Project * const qt4Project
|
|
|
|
|
= static_cast<const Qt4Project *>(project);
|
|
|
|
|
const QString proFileName
|
|
|
|
|
= QFileInfo(qt4Project->rootProjectNode()->path()).fileName();
|
|
|
|
|
rulesContents.replace("# Add here commands to configure the package.",
|
|
|
|
|
"qmake " + proFileName.toLocal8Bit());
|
2010-08-03 16:27:34 +02:00
|
|
|
|
|
|
|
|
// Would be the right solution, but does not work (on Windows),
|
|
|
|
|
// because dpkg-genchanges doesn't know about it (and can't be told).
|
|
|
|
|
// rulesContents.replace("dh_builddeb", "dh_builddeb --destdir=.");
|
|
|
|
|
|
|
|
|
|
rulesFile.resize(0);
|
|
|
|
|
rulesFile.write(rulesContents);
|
2010-08-23 14:47:28 +02:00
|
|
|
rulesFile.close();
|
2010-08-03 16:27:34 +02:00
|
|
|
if (rulesFile.error() != QFile::NoError) {
|
|
|
|
|
raiseError(tr("Packaging Error: Cannot write file '%1'.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(rulesFilePath)));
|
2010-08-05 15:09:23 +02:00
|
|
|
return false;
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
2010-08-05 15:09:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2010-08-05 11:33:39 +02:00
|
|
|
|
2010-08-23 14:47:28 +02:00
|
|
|
bool MaemoTemplatesManager::adaptControlFile(const Project *project)
|
|
|
|
|
{
|
|
|
|
|
QFile controlFile(controlFilePath(project));
|
|
|
|
|
if (!controlFile.open(QIODevice::ReadWrite)) {
|
|
|
|
|
raiseError(tr("Packaging Error: Cannot open file '%1'.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(controlFilePath(project))));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-08-27 13:37:45 +02:00
|
|
|
|
2010-08-23 14:47:28 +02:00
|
|
|
QByteArray controlContents = controlFile.readAll();
|
2010-08-27 13:37:45 +02:00
|
|
|
|
|
|
|
|
adaptControlFileField(controlContents, "Section", "user/hidden");
|
|
|
|
|
adaptControlFileField(controlContents, "Priority", "optional");
|
|
|
|
|
|
2010-08-23 14:47:28 +02:00
|
|
|
controlFile.resize(0);
|
|
|
|
|
controlFile.write(controlContents);
|
|
|
|
|
controlFile.close();
|
|
|
|
|
if (controlFile.error() != QFile::NoError) {
|
|
|
|
|
raiseError(tr("Packaging Error: Cannot write file '%1'.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(controlFilePath(project))));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-27 13:37:45 +02:00
|
|
|
void MaemoTemplatesManager::adaptControlFileField(QByteArray &document,
|
|
|
|
|
const QByteArray &fieldName, const QByteArray &newFieldValue)
|
|
|
|
|
{
|
|
|
|
|
QByteArray adaptedLine = fieldName + ": " + newFieldValue;
|
|
|
|
|
const int lineOffset = document.indexOf(fieldName + ":");
|
|
|
|
|
if (lineOffset == -1) {
|
|
|
|
|
document.append(adaptedLine).append('\n');
|
|
|
|
|
} else {
|
|
|
|
|
int newlineOffset = document.indexOf('\n', lineOffset);
|
|
|
|
|
if (newlineOffset == -1) {
|
|
|
|
|
newlineOffset = document.length();
|
|
|
|
|
adaptedLine += '\n';
|
|
|
|
|
}
|
|
|
|
|
document.replace(lineOffset, newlineOffset - lineOffset, adaptedLine);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
bool MaemoTemplatesManager::updateDesktopFiles(const Qt4Target *target)
|
2010-08-06 17:31:13 +02:00
|
|
|
{
|
|
|
|
|
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();
|
2010-08-09 11:49:44 +02:00
|
|
|
bool success = true;
|
|
|
|
|
foreach (Qt4ProFileNode *proFileNode, applicationProjects)
|
|
|
|
|
success &= updateDesktopFile(qt4Target, proFileNode);
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MaemoTemplatesManager::updateDesktopFile(const Qt4Target *target,
|
|
|
|
|
Qt4ProFileNode *proFileNode)
|
|
|
|
|
{
|
|
|
|
|
const QString appName = proFileNode->targetInformation().target;
|
|
|
|
|
const QString desktopFilePath = QFileInfo(proFileNode->path()).path()
|
|
|
|
|
+ QLatin1Char('/') + appName + QLatin1String(".desktop");
|
|
|
|
|
QFile desktopFile(desktopFilePath);
|
|
|
|
|
const bool existsAlready = desktopFile.exists();
|
|
|
|
|
if (!desktopFile.open(QIODevice::ReadWrite)) {
|
|
|
|
|
qWarning("Failed to open '%s': %s", qPrintable(desktopFilePath),
|
|
|
|
|
qPrintable(desktopFile.errorString()));
|
|
|
|
|
return false;
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
const QByteArray desktopTemplate("[Desktop Entry]\nEncoding=UTF-8\n"
|
|
|
|
|
"Version=1.0\nType=Application\nTerminal=false\nName=\nExec=\n"
|
|
|
|
|
"Icon=\nX-Window-Icon=\nX-HildonDesk-ShowInToolbar=true\n"
|
|
|
|
|
"X-Osso-Type=application/x-executable\n");
|
2010-08-23 16:40:46 +02:00
|
|
|
QByteArray desktopFileContents
|
2010-08-09 11:49:44 +02:00
|
|
|
= existsAlready ? desktopFile.readAll() : desktopTemplate;
|
|
|
|
|
|
|
|
|
|
QString executable;
|
|
|
|
|
const MaemoDeployables * const deployables
|
|
|
|
|
= MaemoGlobal::buildStep<MaemoDeployStep>(target->activeDeployConfiguration())
|
|
|
|
|
->deployables();
|
|
|
|
|
for (int i = 0; i < deployables->modelCount(); ++i) {
|
|
|
|
|
const MaemoDeployableListModel * const model = deployables->modelAt(i);
|
|
|
|
|
if (model->proFileNode() == proFileNode) {
|
|
|
|
|
executable = model->remoteExecutableFilePath();
|
|
|
|
|
break;
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
2010-08-09 11:49:44 +02:00
|
|
|
if (executable.isEmpty()) {
|
|
|
|
|
qWarning("Strange: Project file node not managed by MaemoDeployables.");
|
|
|
|
|
} else {
|
|
|
|
|
int execNewLinePos, execValuePos;
|
2010-08-23 16:40:46 +02:00
|
|
|
findLine("Exec=", desktopFileContents, execNewLinePos, execValuePos);
|
|
|
|
|
desktopFileContents.replace(execValuePos, execNewLinePos - execValuePos,
|
2010-08-09 11:49:44 +02:00
|
|
|
executable.toUtf8());
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
2010-08-09 11:49:44 +02:00
|
|
|
|
|
|
|
|
int nameNewLinePos, nameValuePos;
|
2010-08-23 16:40:46 +02:00
|
|
|
findLine("Name=", desktopFileContents, nameNewLinePos, nameValuePos);
|
2010-08-09 11:49:44 +02:00
|
|
|
if (nameNewLinePos == nameValuePos)
|
2010-08-23 16:40:46 +02:00
|
|
|
desktopFileContents.insert(nameValuePos, appName.toUtf8());
|
2010-08-09 11:49:44 +02:00
|
|
|
|
|
|
|
|
desktopFile.resize(0);
|
2010-08-23 16:40:46 +02:00
|
|
|
desktopFile.write(desktopFileContents);
|
2010-08-09 11:49:44 +02:00
|
|
|
desktopFile.close();
|
|
|
|
|
if (desktopFile.error() != QFile::NoError) {
|
|
|
|
|
qWarning("Could not write '%s': %s", qPrintable(desktopFilePath),
|
|
|
|
|
qPrintable(desktopFile.errorString()));
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
if (!existsAlready) {
|
|
|
|
|
proFileNode->addFiles(UnknownFileType,
|
|
|
|
|
QStringList() << desktopFilePath);
|
2010-08-23 16:40:46 +02:00
|
|
|
QFile proFile(proFileNode->path());
|
|
|
|
|
if (!proFile.open(QIODevice::ReadWrite)) {
|
|
|
|
|
qWarning("Failed to open '%s': %s", qPrintable(proFileNode->path()),
|
|
|
|
|
qPrintable(proFile.errorString()));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
QByteArray proFileContents = proFile.readAll();
|
|
|
|
|
proFileContents += "\nmaemo5|maemp6{\n"
|
|
|
|
|
" desktopfile.files = $${TARGET}.desktop\n"
|
|
|
|
|
" desktopfile.path = /usr/share/applications/hildon\n"
|
|
|
|
|
" INSTALLS += desktopfile\n}\n";
|
|
|
|
|
proFile.resize(0);
|
|
|
|
|
proFile.write(proFileContents);
|
|
|
|
|
proFile.close();
|
|
|
|
|
if (proFile.error() != QFile::NoError) {
|
|
|
|
|
qWarning("Could not write '%s': %s", qPrintable(proFileNode->path()),
|
|
|
|
|
qPrintable(proFile.errorString()));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-08-09 11:49:44 +02:00
|
|
|
}
|
2010-08-06 17:31:13 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-05 15:09:23 +02:00
|
|
|
void MaemoTemplatesManager::handleProjectToBeRemoved(ProjectExplorer::Project *project)
|
|
|
|
|
{
|
|
|
|
|
MaemoProjectMap::Iterator it = m_maemoProjects.find(project);
|
|
|
|
|
if (it != m_maemoProjects.end()) {
|
|
|
|
|
delete it.value();
|
|
|
|
|
m_maemoProjects.erase(it);
|
|
|
|
|
}
|
2010-08-03 16:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
void MaemoTemplatesManager::handleProFileUpdated()
|
2010-08-06 17:31:13 +02:00
|
|
|
{
|
2010-08-09 11:49:44 +02:00
|
|
|
const MaemoDeployables * const deployables
|
|
|
|
|
= qobject_cast<MaemoDeployables *>(sender());
|
|
|
|
|
if (!deployables)
|
|
|
|
|
return;
|
|
|
|
|
const Target * const target = deployables->buildStep()->target();
|
|
|
|
|
if (m_maemoProjects.contains(target->project()))
|
|
|
|
|
updateDesktopFiles(qobject_cast<const Qt4Target *>(target));
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-03 16:27:34 +02:00
|
|
|
QString MaemoTemplatesManager::version(const Project *project,
|
|
|
|
|
QString *error) const
|
|
|
|
|
{
|
2010-08-05 11:22:07 +02:00
|
|
|
QSharedPointer<QFile> changeLog
|
|
|
|
|
= openFile(changeLogFilePath(project), QIODevice::ReadOnly, error);
|
|
|
|
|
if (!changeLog)
|
2010-08-03 16:27:34 +02:00
|
|
|
return QString();
|
2010-08-05 11:22:07 +02:00
|
|
|
const QByteArray &firstLine = changeLog->readLine();
|
2010-08-03 16:27:34 +02:00
|
|
|
const int openParenPos = firstLine.indexOf('(');
|
|
|
|
|
if (openParenPos == -1) {
|
|
|
|
|
*error = tr("Debian changelog file '%1' has unexpected format.")
|
2010-08-05 11:22:07 +02:00
|
|
|
.arg(QDir::toNativeSeparators(changeLog->fileName()));
|
2010-08-03 16:27:34 +02:00
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
const int closeParenPos = firstLine.indexOf(')', openParenPos);
|
|
|
|
|
if (closeParenPos == -1) {
|
|
|
|
|
*error = tr("Debian changelog file '%1' has unexpected format.")
|
2010-08-05 11:22:07 +02:00
|
|
|
.arg(QDir::toNativeSeparators(changeLog->fileName()));
|
2010-08-03 16:27:34 +02:00
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
return QString::fromUtf8(firstLine.mid(openParenPos + 1,
|
|
|
|
|
closeParenPos - openParenPos - 1).data());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MaemoTemplatesManager::setVersion(const Project *project,
|
|
|
|
|
const QString &version, QString *error) const
|
|
|
|
|
{
|
2010-08-05 11:22:07 +02:00
|
|
|
QSharedPointer<QFile> changeLog
|
|
|
|
|
= openFile(changeLogFilePath(project), QIODevice::ReadWrite, error);
|
|
|
|
|
if (!changeLog)
|
2010-08-03 16:27:34 +02:00
|
|
|
return false;
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
QString content = QString::fromUtf8(changeLog->readAll());
|
2010-08-03 16:27:34 +02:00
|
|
|
content.replace(QRegExp(QLatin1String("\\([a-zA-Z0-9_\\.]+\\)")),
|
2010-08-03 18:14:24 +02:00
|
|
|
QLatin1Char('(') + version + QLatin1Char(')'));
|
2010-08-05 11:22:07 +02:00
|
|
|
changeLog->resize(0);
|
|
|
|
|
changeLog->write(content.toUtf8());
|
|
|
|
|
changeLog->close();
|
|
|
|
|
if (changeLog->error() != QFile::NoError) {
|
2010-08-03 16:27:34 +02:00
|
|
|
*error = tr("Error writing Debian changelog file '%1': %2")
|
2010-08-05 11:22:07 +02:00
|
|
|
.arg(QDir::toNativeSeparators(changeLog->fileName()),
|
|
|
|
|
changeLog->errorString());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QIcon MaemoTemplatesManager::packageManagerIcon(const Project *project,
|
|
|
|
|
QString *error) const
|
|
|
|
|
{
|
|
|
|
|
QSharedPointer<QFile> controlFile
|
|
|
|
|
= openFile(controlFilePath(project), QIODevice::ReadOnly, error);
|
|
|
|
|
if (!controlFile)
|
|
|
|
|
return QIcon();
|
|
|
|
|
|
|
|
|
|
bool iconFieldFound = false;
|
|
|
|
|
QByteArray currentLine;
|
|
|
|
|
while (!iconFieldFound && !controlFile->atEnd()) {
|
|
|
|
|
currentLine = controlFile->readLine();
|
|
|
|
|
iconFieldFound = currentLine.startsWith(IconFieldName);
|
|
|
|
|
}
|
|
|
|
|
if (!iconFieldFound)
|
|
|
|
|
return QIcon();
|
|
|
|
|
|
|
|
|
|
int pos = IconFieldName.length();
|
|
|
|
|
currentLine = currentLine.trimmed();
|
|
|
|
|
QByteArray base64Icon;
|
|
|
|
|
do {
|
|
|
|
|
while (pos < currentLine.length())
|
|
|
|
|
base64Icon += currentLine.at(pos++);
|
|
|
|
|
do
|
|
|
|
|
currentLine = controlFile->readLine();
|
|
|
|
|
while (currentLine.startsWith('#'));
|
|
|
|
|
if (currentLine.isEmpty() || !isspace(currentLine.at(0)))
|
|
|
|
|
break;
|
|
|
|
|
currentLine = currentLine.trimmed();
|
|
|
|
|
if (currentLine.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
pos = 0;
|
|
|
|
|
} while (true);
|
|
|
|
|
QPixmap pixmap;
|
|
|
|
|
if (!pixmap.loadFromData(QByteArray::fromBase64(base64Icon))) {
|
|
|
|
|
*error = tr("Invalid icon data in Debian control file.");
|
|
|
|
|
return QIcon();
|
|
|
|
|
}
|
|
|
|
|
return QIcon(pixmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MaemoTemplatesManager::setPackageManagerIcon(const Project *project,
|
|
|
|
|
const QString &iconFilePath, QString *error) const
|
|
|
|
|
{
|
|
|
|
|
const QSharedPointer<QFile> controlFile
|
|
|
|
|
= openFile(controlFilePath(project), QIODevice::ReadWrite, error);
|
|
|
|
|
if (!controlFile)
|
|
|
|
|
return false;
|
|
|
|
|
const QPixmap pixmap(iconFilePath);
|
|
|
|
|
if (pixmap.isNull()) {
|
|
|
|
|
*error = tr("Could not read image file '%1'.").arg(iconFilePath);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray iconAsBase64;
|
|
|
|
|
QBuffer buffer(&iconAsBase64);
|
|
|
|
|
buffer.open(QIODevice::WriteOnly);
|
|
|
|
|
if (!pixmap.scaled(48, 48).save(&buffer,
|
|
|
|
|
QFileInfo(iconFilePath).suffix().toAscii())) {
|
|
|
|
|
*error = tr("Could not export image file '%1'.").arg(iconFilePath);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
buffer.close();
|
|
|
|
|
iconAsBase64 = iconAsBase64.toBase64();
|
|
|
|
|
QByteArray contents = controlFile->readAll();
|
|
|
|
|
const int iconFieldPos = contents.startsWith(IconFieldName)
|
|
|
|
|
? 0 : contents.indexOf('\n' + IconFieldName);
|
|
|
|
|
if (iconFieldPos == -1) {
|
|
|
|
|
if (!contents.endsWith('\n'))
|
|
|
|
|
contents += '\n';
|
|
|
|
|
contents.append(IconFieldName).append(' ').append(iconAsBase64)
|
|
|
|
|
.append('\n');
|
|
|
|
|
} else {
|
|
|
|
|
const int oldIconStartPos
|
|
|
|
|
= (iconFieldPos != 0) + iconFieldPos + IconFieldName.length();
|
|
|
|
|
int nextEolPos = contents.indexOf('\n', oldIconStartPos);
|
|
|
|
|
while (nextEolPos != -1 && nextEolPos != contents.length() - 1
|
|
|
|
|
&& contents.at(nextEolPos + 1) != '\n'
|
|
|
|
|
&& (contents.at(nextEolPos + 1) == '#'
|
|
|
|
|
|| std::isspace(contents.at(nextEolPos + 1))))
|
|
|
|
|
nextEolPos = contents.indexOf('\n', nextEolPos + 1);
|
|
|
|
|
if (nextEolPos == -1)
|
|
|
|
|
nextEolPos = contents.length();
|
|
|
|
|
contents.replace(oldIconStartPos, nextEolPos - oldIconStartPos,
|
|
|
|
|
' ' + iconAsBase64);
|
|
|
|
|
}
|
|
|
|
|
controlFile->resize(0);
|
|
|
|
|
controlFile->write(contents);
|
|
|
|
|
if (controlFile->error() != QFile::NoError) {
|
|
|
|
|
*error = tr("Error writing file '%1': %2")
|
|
|
|
|
.arg(QDir::toNativeSeparators(controlFile->fileName()),
|
|
|
|
|
controlFile->errorString());
|
2010-08-03 16:27:34 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:22:48 +02:00
|
|
|
QStringList MaemoTemplatesManager::debianFiles(const Project *project) const
|
|
|
|
|
{
|
|
|
|
|
return QDir(debianDirPath(project))
|
|
|
|
|
.entryList(QDir::Files, QDir::Name | QDir::IgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString MaemoTemplatesManager::debianDirPath(const Project *project) const
|
|
|
|
|
{
|
|
|
|
|
return project->projectDirectory() + QLatin1Char('/')
|
2010-08-27 11:46:54 +02:00
|
|
|
+ QLatin1String("/debian");
|
2010-08-04 12:22:48 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
QString MaemoTemplatesManager::changeLogFilePath(const Project *project) const
|
|
|
|
|
{
|
|
|
|
|
return debianDirPath(project) + QLatin1String("/changelog");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString MaemoTemplatesManager::controlFilePath(const Project *project) const
|
|
|
|
|
{
|
|
|
|
|
return debianDirPath(project) + QLatin1String("/control");
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-03 16:27:34 +02:00
|
|
|
void MaemoTemplatesManager::raiseError(const QString &reason)
|
|
|
|
|
{
|
|
|
|
|
QMessageBox::critical(0, tr("Error creating Maemo templates"), reason);
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
void MaemoTemplatesManager::handleDebianFileChanged(const QString &filePath)
|
2010-08-04 16:38:37 +02:00
|
|
|
{
|
2010-08-05 15:09:23 +02:00
|
|
|
const Project * const project
|
|
|
|
|
= findProject(qobject_cast<QFileSystemWatcher *>(sender()));
|
|
|
|
|
if (project) {
|
|
|
|
|
if (filePath == changeLogFilePath(project))
|
|
|
|
|
emit changeLogChanged(project);
|
|
|
|
|
else if (filePath == controlFilePath(project))
|
|
|
|
|
emit controlChanged(project);
|
|
|
|
|
}
|
2010-08-04 16:38:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaemoTemplatesManager::handleDebianDirContentsChanged()
|
|
|
|
|
{
|
2010-08-05 15:09:23 +02:00
|
|
|
const Project * const project
|
|
|
|
|
= findProject(qobject_cast<QFileSystemWatcher *>(sender()));
|
|
|
|
|
if (project)
|
|
|
|
|
emit debianDirContentsChanged(project);
|
2010-08-04 16:38:37 +02:00
|
|
|
}
|
|
|
|
|
|
2010-08-05 11:22:07 +02:00
|
|
|
QSharedPointer<QFile> MaemoTemplatesManager::openFile(const QString &filePath,
|
|
|
|
|
QIODevice::OpenMode mode, QString *error) const
|
|
|
|
|
{
|
|
|
|
|
const QString nativePath = QDir::toNativeSeparators(filePath);
|
|
|
|
|
QSharedPointer<QFile> file(new QFile(filePath));
|
|
|
|
|
if (!file->exists()) {
|
|
|
|
|
*error = tr("File '%1' does not exist").arg(nativePath);
|
|
|
|
|
} else if (!file->open(mode)) {
|
|
|
|
|
*error = tr("Cannot open file '%1': %2")
|
|
|
|
|
.arg(nativePath, file->errorString());
|
|
|
|
|
}
|
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-05 15:09:23 +02:00
|
|
|
Project *MaemoTemplatesManager::findProject(const QFileSystemWatcher *fsWatcher) const
|
|
|
|
|
{
|
|
|
|
|
for (MaemoProjectMap::ConstIterator it = m_maemoProjects.constBegin();
|
|
|
|
|
it != m_maemoProjects.constEnd(); ++it) {
|
|
|
|
|
if (it.value() == fsWatcher)
|
|
|
|
|
return it.key();
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-09 11:49:44 +02:00
|
|
|
void MaemoTemplatesManager::findLine(const QByteArray &string,
|
|
|
|
|
QByteArray &document, int &lineEndPos, int &valuePos)
|
2010-08-06 17:31:13 +02:00
|
|
|
{
|
2010-08-09 11:49:44 +02:00
|
|
|
int lineStartPos = document.indexOf(string);
|
|
|
|
|
if (lineStartPos == -1) {
|
|
|
|
|
lineStartPos = document.length();
|
|
|
|
|
document += string + '\n';
|
|
|
|
|
}
|
|
|
|
|
valuePos = lineStartPos + string.length();
|
|
|
|
|
lineEndPos = document.indexOf('\n', lineStartPos);
|
|
|
|
|
if (lineEndPos == -1) {
|
|
|
|
|
lineEndPos = document.length();
|
|
|
|
|
document += '\n';
|
2010-08-06 17:31:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-03 16:27:34 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Qt4ProjectManager
|