Files
qt-creator/src/plugins/projectexplorer/session.cpp

1093 lines
31 KiB
C++
Raw Normal View History

/**************************************************************************
2008-12-02 12:01:29 +01:00
**
** This file is part of Qt Creator
**
2010-03-05 11:25:49 +01:00
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
2008-12-02 12:01:29 +01:00
**
** Contact: Nokia Corporation (qt-info@nokia.com)
2008-12-02 12:01:29 +01:00
**
** 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
2009-08-14 09:30:56 +02:00
** contact the sales department at http://qt.nokia.com/contact.
2008-12-02 12:01:29 +01:00
**
**************************************************************************/
2008-12-02 16:19:05 +01:00
#include "session.h"
2008-12-02 12:01:29 +01:00
#include "project.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "nodesvisitor.h"
#include "editorconfiguration.h"
#include "persistentsettings.h"
2008-12-02 12:01:29 +01:00
#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
#include <coreplugin/filemanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/progressmanager/progressmanager.h>
2008-12-02 12:01:29 +01:00
#include <coreplugin/modemanager.h>
#include <texteditor/itexteditor.h>
2008-12-09 15:25:01 +01:00
#include <utils/listutils.h>
#include <utils/qtcassert.h>
2008-12-02 12:01:29 +01:00
#include <QtCore/QDebug>
2008-12-09 15:25:01 +01:00
#include <QtCore/QDir>
2008-12-02 12:01:29 +01:00
#include <QtCore/QFileInfo>
#include <QtCore/QFuture>
2008-12-09 15:25:01 +01:00
#include <QtCore/QSettings>
#include <QtCore/QTimer>
2008-12-09 15:25:01 +01:00
#include <QtGui/QApplication>
2008-12-02 12:01:29 +01:00
#include <QtGui/QMainWindow>
2008-12-09 15:25:01 +01:00
#include <QtGui/QMessageBox>
#include <QtCore/QTextCodec>
2008-12-02 12:01:29 +01:00
namespace {
bool debug = false;
}
/* SessionFile definitions */
namespace ProjectExplorer {
namespace Internal {
class SessionFile : QObject
2008-12-02 12:01:29 +01:00
{
Q_OBJECT
public:
2009-01-20 17:14:00 +01:00
SessionFile();
2008-12-02 12:01:29 +01:00
bool load(const QString &fileName);
bool save(const QString &fileName = QString());
QString fileName() const;
void setFileName(const QString &fileName);
public slots:
void sessionLoadingProgress();
private:
Core::ICore *m_core;
QString m_fileName;
QList<Project *> m_projects;
Project *m_startupProject;
QMap<QString, QStringList> m_depMap;
QMap<QString, QVariant> m_values;
QFutureInterface<void> future;
friend class ProjectExplorer::SessionManager;
};
} // namespace Internal
} // namespace ProjectExplorer
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
2008-12-02 12:01:29 +01:00
void SessionFile::sessionLoadingProgress()
{
future.setProgressValue(future.progressValue() + 1);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
2009-01-20 17:14:00 +01:00
SessionFile::SessionFile()
: m_core(Core::ICore::instance()),
2008-12-02 12:01:29 +01:00
m_startupProject(0)
{
}
bool SessionFile::load(const QString &fileName)
{
Q_ASSERT(!fileName.isEmpty());
2008-12-02 12:01:29 +01:00
if (debug)
qDebug() << "SessionFile::load " << fileName;
m_fileName = fileName;
// NPE: Load the session in the background?
// NPE: Let FileManager monitor filename
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
PersistentSettingsReader reader;
if (!reader.load(m_fileName)) {
qWarning() << "SessionManager::load failed!" << fileName;
QApplication::restoreOverrideCursor();
return false;
}
m_core->progressManager()->addTask(future.future(), tr("Session"),
QLatin1String("ProjectExplorer.SessionFile.Load"));
2008-12-02 12:01:29 +01:00
const QStringList &keys = reader.restoreValue(QLatin1String("valueKeys")).toStringList();
foreach (const QString &key, keys) {
QVariant value = reader.restoreValue("value-" + key);
m_values.insert(key, value);
}
QStringList fileList =
reader.restoreValue(QLatin1String("ProjectList")).toStringList();
QString configDir = QFileInfo(m_core->settings()->fileName()).path();
QMutableStringListIterator it(fileList);
while (it.hasNext()) {
const QString &file = it.next();
if (QFileInfo(file).isRelative()) {
// We used to write relative paths into the session file
// relative to the session files, and those were stored in the
// config dir
it.setValue(configDir + QLatin1Char('/') + file);
2008-12-02 12:01:29 +01:00
}
}
int openEditorsCount = reader.restoreValue(QLatin1String("OpenEditors")).toInt();
future.setProgressRange(0, fileList.count() + openEditorsCount + 2);
future.setProgressValue(1);
// indirectly adds projects to session
if (!fileList.isEmpty())
ProjectExplorerPlugin::instance()->openProjects(fileList);
sessionLoadingProgress();
// convert the relative paths in the dependency map to absolute paths
QMap<QString, QVariant> depMap = reader.restoreValue(QLatin1String("ProjectDependencies")).toMap();
QMap<QString, QVariant>::const_iterator i = depMap.constBegin();
while (i != depMap.constEnd()) {
const QString &key = i.key();
QStringList values;
foreach (const QString &value, i.value().toStringList()) {
values << value;
}
m_depMap.insert(key, values);
++i;
}
// find and set the startup project
const QString startupProject = reader.restoreValue(QLatin1String("StartupProject")).toString();
if (!startupProject.isEmpty()) {
const QString startupProjectPath = startupProject;
foreach (Project *pro, m_projects) {
if (QDir::cleanPath(pro->file()->fileName()) == startupProjectPath) {
m_startupProject = pro;
break;
}
}
if (!m_startupProject)
qWarning() << "Could not find startup project" << startupProjectPath;
}
const QVariant &editorsettings = reader.restoreValue(QLatin1String("EditorSettings"));
if (editorsettings.isValid()) {
connect(m_core->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
this, SLOT(sessionLoadingProgress()));
m_core->editorManager()->restoreState(
QByteArray::fromBase64(editorsettings.toByteArray()));
disconnect(m_core->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
this, SLOT(sessionLoadingProgress()));
}
if (debug)
qDebug() << "SessionFile::load finished" << fileName;
future.reportFinished();
QApplication::restoreOverrideCursor();
return true;
}
bool SessionFile::save(const QString &fileName)
{
if (!fileName.isEmpty())
m_fileName = fileName;
Q_ASSERT(!m_fileName.isEmpty());
2008-12-02 12:01:29 +01:00
if (debug)
qDebug() << "SessionFile - saving " << m_fileName;
PersistentSettingsWriter writer;
// save the startup project
if (m_startupProject) {
writer.saveValue(QLatin1String("StartupProject"), m_startupProject->file()->fileName());
}
QStringList projectFiles;
foreach (Project *pro, m_projects) {
projectFiles << pro->file()->fileName();
}
writer.saveValue(QLatin1String("ProjectList"), projectFiles);
QMap<QString, QVariant> depMap;
QMap<QString, QStringList>::const_iterator i = m_depMap.constBegin();
while (i != m_depMap.constEnd()) {
QString key = i.key();
QStringList values;
foreach (const QString &value, i.value()) {
values << value;
}
depMap.insert(key, values);
++i;
}
writer.saveValue(QLatin1String("ProjectDependencies"), QVariant(depMap));
2008-12-02 12:01:29 +01:00
writer.saveValue(QLatin1String("OpenEditors"),
m_core->editorManager()->openedEditors().count());
writer.saveValue(QLatin1String("EditorSettings"),
m_core->editorManager()->saveState().toBase64());
QMap<QString, QVariant>::const_iterator it, end;
end = m_values.constEnd();
QStringList keys;
for (it = m_values.constBegin(); it != end; ++it) {
writer.saveValue("value-" + it.key(), it.value());
keys << it.key();
}
writer.saveValue("valueKeys", keys);
if (writer.save(m_fileName, "QtCreatorSession"))
return true;
return false;
}
QString SessionFile::fileName() const
{
return m_fileName;
}
void SessionFile::setFileName(const QString &fileName)
{
m_fileName = fileName;
}
Internal::SessionNodeImpl::SessionNodeImpl(SessionManager *manager)
: ProjectExplorer::SessionNode(manager->currentSession(), manager)
2008-12-02 12:01:29 +01:00
{
setFileName("session");
}
void Internal::SessionNodeImpl::addProjectNode(ProjectNode *projectNode)
{
addProjectNodes(QList<ProjectNode*>() << projectNode);
}
void Internal::SessionNodeImpl::removeProjectNode(ProjectNode *projectNode)
{
removeProjectNodes(QList<ProjectNode*>() << projectNode);
}
void Internal::SessionNodeImpl::setFileName(const QString &fileName)
{
setPath(fileName);
setDisplayName(fileName);
2008-12-02 12:01:29 +01:00
}
/* --------------------------------- */
2009-01-20 17:14:00 +01:00
SessionManager::SessionManager(QObject *parent)
: QObject(parent),
m_core(Core::ICore::instance()),
m_file(new SessionFile),
m_sessionNode(new Internal::SessionNodeImpl(this)),
m_currentEditor(0),
m_virginSession(true)
2008-12-02 12:01:29 +01:00
{
// Create qtcreator dir if it doesn't yet exist
QString configDir = QFileInfo(m_core->settings()->fileName()).path();
QFileInfo fi(configDir + "/qtcreator/");
if (!fi.exists()) {
QDir dir;
dir.mkpath(configDir + "/qtcreator");
// Move sessions to that directory
2008-12-09 11:07:24 +01:00
foreach (const QString &session, sessions()) {
QFile file(configDir + QLatin1Char('/') + session + QLatin1String(".qws"));
2008-12-02 12:01:29 +01:00
if (file.exists())
if (file.copy(configDir + QLatin1String("/qtcreator/") + session + QLatin1String(".qws")))
2008-12-02 12:01:29 +01:00
file.remove();
}
}
connect(m_core->modeManager(), SIGNAL(currentModeChanged(Core::IMode*)),
this, SLOT(saveActiveMode(Core::IMode*)));
Core::EditorManager *em = m_core->editorManager();
connect(em, SIGNAL(editorCreated(Core::IEditor *, QString)),
2008-12-02 12:01:29 +01:00
this, SLOT(setEditorCodec(Core::IEditor *, QString)));
connect(ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project *)),
this, SLOT(updateWindowTitle()));
connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(handleCurrentEditorChange(Core::IEditor*)));
connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(handleCurrentEditorChange(Core::IEditor*)));
connect(em, SIGNAL(editorOpened(Core::IEditor*)),
this, SLOT(markSessionFileDirty()));
connect(em, SIGNAL(editorsClosed(QList<Core::IEditor*>)),
this, SLOT(markSessionFileDirty()));
m_autoSaveSessionTimer = new QTimer(this);
m_autoSaveSessionTimer->setSingleShot(true);
m_autoSaveSessionTimer->setInterval(10000);
connect(m_autoSaveSessionTimer, SIGNAL(timeout()),
m_core, SIGNAL(saveSettingsRequested()));
2009-01-20 17:14:00 +01:00
}
2008-12-02 12:01:29 +01:00
SessionManager::~SessionManager()
{
emit aboutToUnloadSession();
2008-12-02 12:01:29 +01:00
delete m_file;
}
bool SessionManager::isDefaultVirgin() const
{
return isDefaultSession(m_sessionName)
&& m_virginSession;
2008-12-02 12:01:29 +01:00
}
bool SessionManager::isDefaultSession(const QString &session) const
{
2008-12-09 11:07:24 +01:00
return session == QLatin1String("default");
2008-12-02 12:01:29 +01:00
}
void SessionManager::saveActiveMode(Core::IMode *mode)
{
setValue(QLatin1String("ActiveMode"), mode->id());
2008-12-02 12:01:29 +01:00
}
void SessionManager::clearProjectFileCache()
{
// If triggered by the fileListChanged signal of one project
// only invalidate cache for this project
Project *pro = qobject_cast<Project*>(sender());
if (pro)
m_projectFileCache.remove(pro);
else
m_projectFileCache.clear();
}
bool SessionManager::recursiveDependencyCheck(const QString &newDep, const QString &checkDep) const
{
if (newDep == checkDep)
return false;
foreach (const QString &dependency, m_file->m_depMap.value(checkDep)) {
if (!recursiveDependencyCheck(newDep, dependency))
return false;
}
return true;
}
/*
* TODO: The dependency management exposes an interface based on projects, but
* is internally purely string based. This is suboptimal. Probably it would be
* nicer to map the filenames to projects on load and only map it back to
* filenames when saving.
*/
QList<Project *> SessionManager::dependencies(const Project *project) const
{
const QString &proName = project->file()->fileName();
const QStringList &proDeps = m_file->m_depMap.value(proName);
QList<Project *> projects;
foreach (const QString &dep, proDeps) {
if (Project *pro = projectForFile(dep))
projects += pro;
}
return projects;
}
bool SessionManager::hasDependency(const Project *project, const Project *depProject) const
2008-12-02 12:01:29 +01:00
{
const QString &proName = project->file()->fileName();
const QString &depName = depProject->file()->fileName();
const QStringList &proDeps = m_file->m_depMap.value(proName);
return proDeps.contains(depName);
}
bool SessionManager::canAddDependency(const Project *project, const Project *depProject) const
2008-12-02 12:01:29 +01:00
{
const QString &newDep = project->file()->fileName();
const QString &checkDep = depProject->file()->fileName();
return recursiveDependencyCheck(newDep, checkDep);
}
bool SessionManager::addDependency(Project *project, Project *depProject)
2008-12-02 12:01:29 +01:00
{
const QString &proName = project->file()->fileName();
const QString &depName = depProject->file()->fileName();
// check if this dependency is valid
if (!recursiveDependencyCheck(proName, depName))
return false;
QStringList proDeps = m_file->m_depMap.value(proName);
if (!proDeps.contains(depName)) {
proDeps.append(depName);
m_file->m_depMap[proName] = proDeps;
}
emit dependencyChanged(project, depProject);
2008-12-02 12:01:29 +01:00
return true;
}
void SessionManager::removeDependency(Project *project, Project *depProject)
{
const QString &proName = project->file()->fileName();
const QString &depName = depProject->file()->fileName();
QStringList proDeps = m_file->m_depMap.value(proName);
proDeps.removeAll(depName);
if (proDeps.isEmpty()) {
m_file->m_depMap.remove(proName);
} else {
m_file->m_depMap[proName] = proDeps;
}
emit dependencyChanged(project, depProject);
}
2008-12-02 12:01:29 +01:00
void SessionManager::setStartupProject(Project *startupProject)
{
if (debug)
qDebug() << Q_FUNC_INFO << (startupProject ? startupProject->displayName() : "0");
2008-12-02 12:01:29 +01:00
if (startupProject) {
Q_ASSERT(m_file->m_projects.contains(startupProject));
2008-12-02 12:01:29 +01:00
}
if (m_file->m_startupProject == startupProject)
return;
2008-12-02 12:01:29 +01:00
m_file->m_startupProject = startupProject;
emit startupProjectChanged(startupProject);
}
Project *SessionManager::startupProject() const
{
return m_file->m_startupProject;
}
void SessionManager::addProject(Project *project)
{
addProjects(QList<Project*>() << project);
}
void SessionManager::addProjects(const QList<Project*> &projects)
{
m_virginSession = false;
2008-12-02 12:01:29 +01:00
QList<Project*> clearedList;
foreach (Project *pro, projects) {
if (!m_file->m_projects.contains(pro)) {
clearedList.append(pro);
m_file->m_projects.append(pro);
m_sessionNode->addProjectNode(pro->rootProjectNode());
connect(pro, SIGNAL(fileListChanged()),
this, SLOT(clearProjectFileCache()));
if (debug)
qDebug() << "SessionManager - adding project " << pro->displayName();
2008-12-02 12:01:29 +01:00
}
}
foreach (Project *pro, clearedList) {
emit projectAdded(pro);
}
if (clearedList.count() == 1)
emit singleProjectAdded(clearedList.first());
// maybe we have a new startup project?
if (!startupProject())
if (!m_file->m_projects.isEmpty())
setStartupProject(m_file->m_projects.first());
2008-12-02 12:01:29 +01:00
}
void SessionManager::removeProject(Project *project)
{
m_virginSession = false;
2008-12-02 12:01:29 +01:00
if (project == 0) {
qDebug() << "SessionManager::removeProject(0) ... THIS SHOULD NOT HAPPEN";
return;
}
removeProjects(QList<Project*>() << project);
}
bool SessionManager::createImpl(const QString &fileName)
{
Q_ASSERT(!fileName.isEmpty());
2008-12-02 12:01:29 +01:00
if (debug)
qDebug() << "SessionManager - creating new session " << fileName << " ...";
bool success = true;
if (!m_file->fileName().isEmpty()) {
2008-12-09 15:25:01 +01:00
if (!save() || !clear())
2008-12-02 12:01:29 +01:00
success = false;
}
if (success) {
emit aboutToUnloadSession();
2008-12-02 12:01:29 +01:00
delete m_file;
2009-01-20 17:14:00 +01:00
m_file = new SessionFile;
2008-12-02 12:01:29 +01:00
m_file->setFileName(fileName);
setStartupProject(0);
2008-12-02 12:01:29 +01:00
}
m_virginSession = true;
2008-12-02 12:01:29 +01:00
if (debug)
qDebug() << "SessionManager - creating new session returns " << success;
if (success)
emit sessionLoaded();
return success;
}
bool SessionManager::loadImpl(const QString &fileName)
{
Q_ASSERT(!fileName.isEmpty());
2008-12-02 12:01:29 +01:00
if (debug)
2009-05-11 14:09:52 +02:00
qDebug() << "SessionManager - restoring session " << fileName << " ...";
2008-12-02 12:01:29 +01:00
bool success = true;
if (!m_file->fileName().isEmpty()) {
if (isDefaultVirgin()) {
// do not save initial and virgin default session
} else if (!save() || !clear()) {
success = false;
}
}
m_virginSession = false;
2008-12-02 12:01:29 +01:00
if (success) {
emit aboutToUnloadSession();
2008-12-02 12:01:29 +01:00
delete m_file;
2009-01-20 17:14:00 +01:00
m_file = new SessionFile;
2008-12-02 12:01:29 +01:00
if (!m_file->load(fileName)) {
2009-05-11 14:09:52 +02:00
QMessageBox::warning(0, tr("Error while restoring session"),
tr("Could not restore session %1").arg(fileName));
2008-12-02 12:01:29 +01:00
success = false;
}
// m_file->load() sets the m_file->startupProject
// but doesn't emit this signal, so we do it here
emit startupProjectChanged(m_file->m_startupProject);
2008-12-02 12:01:29 +01:00
}
if (success) {
// restore the active mode
const QString &modeIdentifier = value(QLatin1String("ActiveMode")).toString();
if (!modeIdentifier.isEmpty()) {
2008-12-02 12:01:29 +01:00
m_core->modeManager()->activateMode(modeIdentifier);
m_core->modeManager()->setFocusToCurrentMode();
}
2008-12-02 12:01:29 +01:00
}
if (debug)
2009-05-11 14:09:52 +02:00
qDebug() << "SessionManager - restoring session returned " << success;
2008-12-02 12:01:29 +01:00
if (success)
emit sessionLoaded();
return success;
}
bool SessionManager::save()
{
if (debug)
qDebug() << "SessionManager - saving session" << m_sessionName;
emit aboutToSaveSession();
bool result = m_file->save();
if (!result) {
QMessageBox::warning(0, tr("Error while saving session"),
tr("Could not save session to file %1").arg(m_file->fileName()));
}
if (debug)
qDebug() << "SessionManager - saving session returned " << result;
return result;
}
/*!
\fn bool SessionManager::clear()
Returns whether the clear operation has been not cancelled & all projects could be closed.
*/
bool SessionManager::clear()
{
if (debug)
qDebug() << "SessionManager - clearing session ...";
bool success = m_core->editorManager()->closeAllEditors();
2008-12-02 12:01:29 +01:00
if (success) {
if (debug)
qDebug() << "SessionManager - Removing projects ...";
setStartupProject(0);
removeProjects(projects());
2008-12-02 12:01:29 +01:00
}
if (debug)
qDebug() << "SessionManager - clearing session result is " << success;
return success;
}
const QList<Project *> &SessionManager::projects() const
2008-12-02 12:01:29 +01:00
{
return m_file->m_projects;
}
QStringList SessionManager::dependencies(const QString &proName) const
{
QStringList result;
foreach (const QString &dep, m_file->m_depMap.value(proName))
result += dependencies(dep);
result << proName;
return result;
}
QStringList SessionManager::dependenciesOrder() const
{
QList<QPair<QString, QStringList> > unordered;
QStringList ordered;
// copy the map to a temporary list
foreach (Project *pro, projects()) {
const QString &proName = pro->file()->fileName();
unordered << QPair<QString, QStringList>
(proName, m_file->m_depMap.value(proName));
}
while (!unordered.isEmpty()) {
for (int i=(unordered.count()-1); i>=0; --i) {
if (unordered.at(i).second.isEmpty()) {
ordered << unordered.at(i).first;
unordered.removeAt(i);
}
}
// remove the handled projects from the dependency lists
// of the remaining unordered projects
for (int i = 0; i < unordered.count(); ++i) {
foreach (const QString &pro, ordered) {
QStringList depList = unordered.at(i).second;
depList.removeAll(pro);
unordered[i].second = depList;
}
}
}
return ordered;
}
QList<Project *> SessionManager::projectOrder(Project *project) const
{
QList<Project *> result;
QStringList pros;
if (project) {
pros = dependencies(project->file()->fileName());
} else {
pros = dependenciesOrder();
}
foreach (const QString &proFile, pros) {
foreach (Project *pro, projects()) {
if (pro->file()->fileName() == proFile) {
result << pro;
break;
}
}
}
return result;
}
Project *SessionManager::projectForNode(Node *node) const
{
if (!node)
return 0;
Project *project = 0;
FolderNode *rootProjectNode = qobject_cast<FolderNode*>(node);
if (!rootProjectNode)
rootProjectNode = node->parentFolderNode();
while (rootProjectNode && rootProjectNode->parentFolderNode() != m_sessionNode)
rootProjectNode = rootProjectNode->parentFolderNode();
Q_ASSERT(rootProjectNode);
2008-12-02 12:01:29 +01:00
QList<Project *> projectList = projects();
foreach (Project *p, projectList) {
if (p->rootProjectNode() == rootProjectNode) {
project = p;
break;
}
}
return project;
}
Node *SessionManager::nodeForFile(const QString &fileName, Project *project) const
2008-12-02 12:01:29 +01:00
{
Node *node = 0;
if (!project)
project = projectForFile(fileName);
if (project) {
2008-12-02 12:01:29 +01:00
FindNodesForFileVisitor findNodes(fileName);
project->rootProjectNode()->accept(&findNodes);
foreach (Node *n, findNodes.nodes()) {
// prefer file nodes
if (!node || (node->nodeType() != FileNodeType && n->nodeType() == FileNodeType))
node = n;
}
}
return node;
}
Project *SessionManager::projectForFile(const QString &fileName) const
{
if (debug)
qDebug() << "SessionManager::projectForFile(" << fileName << ")";
const QList<Project *> &projectList = projects();
2008-12-02 12:01:29 +01:00
// Check current project first
Project *currentProject = ProjectExplorerPlugin::instance()->currentProject();
if (currentProject && projectContainsFile(currentProject, fileName))
return currentProject;
2008-12-02 12:01:29 +01:00
foreach (Project *p, projectList)
if (p != currentProject && projectContainsFile(p, fileName))
return p;
return 0;
}
bool SessionManager::projectContainsFile(Project *p, const QString &fileName) const
{
if (!m_projectFileCache.contains(p))
m_projectFileCache.insert(p, p->files(Project::AllFiles));
return m_projectFileCache.value(p).contains(fileName);
2008-12-02 12:01:29 +01:00
}
void SessionManager::setEditorCodec(Core::IEditor *editor, const QString &fileName)
{
if (TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor))
if (Project *project = projectForFile(fileName)) {
if (QTextCodec *codec = project->editorConfiguration()->defaultTextCodec())
textEditor->setTextCodec(codec);
}
2008-12-02 12:01:29 +01:00
}
QString SessionManager::currentSession() const
2008-12-02 12:01:29 +01:00
{
return m_file->fileName();
2008-12-02 12:01:29 +01:00
}
void SessionManager::handleCurrentEditorChange(Core::IEditor *editor)
{
if (editor != m_currentEditor) {
if (m_currentEditor)
disconnect(m_currentEditor, SIGNAL(changed()), this, SLOT(updateWindowTitle()));
if (editor)
connect(editor, SIGNAL(changed()), this, SLOT(updateWindowTitle()));
m_currentEditor = editor;
}
updateWindowTitle();
}
2008-12-02 12:01:29 +01:00
void SessionManager::updateWindowTitle()
{
QString windowTitle = tr("Qt Creator");
if (!isDefaultSession(m_sessionName)) {
QString sessionName = m_sessionName;
if (sessionName.isEmpty())
sessionName = tr("Untitled");
windowTitle.prepend(sessionName + " - ");
} else {
if (Project *currentProject = ProjectExplorerPlugin::instance()->currentProject())
windowTitle.prepend(currentProject->displayName() + " - ");
2008-12-02 12:01:29 +01:00
}
if (m_core->editorManager()->currentEditor()) {
QFileInfo fi(m_core->editorManager()->currentEditor()->file()->fileName());
QString fileName = fi.fileName();
if (!fileName.isEmpty())
windowTitle.prepend(fileName + " - ");
m_core->mainWindow()->setWindowFilePath(fi.absoluteFilePath());
} else {
m_core->mainWindow()->setWindowFilePath(QString());
}
2008-12-02 12:01:29 +01:00
m_core->mainWindow()->setWindowTitle(windowTitle);
}
void SessionManager::updateName(const QString &session)
{
m_sessionName = session;
QString sessionName = m_sessionName;
if (sessionName.isEmpty())
sessionName = tr("Untitled");
m_displayName = tr("Session (\'%1\')").arg(sessionName);
updateWindowTitle();
}
void SessionManager::removeProjects(QList<Project *> remove)
{
QMap<QString, QStringList> resMap;
foreach (Project *pro, remove) {
if (debug)
qDebug() << "SessionManager - emitting aboutToRemoveProject(" << pro->displayName() << ")";
2008-12-02 12:01:29 +01:00
emit aboutToRemoveProject(pro);
}
// TODO: Clear m_modelProjectHash
// Delete projects
foreach (Project *pro, remove) {
2008-12-03 13:53:11 +01:00
pro->saveSettings();
2008-12-02 12:01:29 +01:00
m_file->m_projects.removeOne(pro);
if (pro == m_file->m_startupProject)
setStartupProject(0);
disconnect(pro, SIGNAL(fileListChanged()),
this, SLOT(clearProjectFileCache()));
m_projectFileCache.remove(pro);
if (debug)
qDebug() << "SessionManager - emitting projectRemoved(" << pro->displayName() << ")";
2008-12-02 12:01:29 +01:00
m_sessionNode->removeProjectNode(pro->rootProjectNode());
emit projectRemoved(pro);
delete pro;
}
// Refresh dependencies
QSet<QString> projectFiles;
foreach (Project *pro, projects()) {
if (!remove.contains(pro))
projectFiles.insert(pro->file()->fileName());
}
QSet<QString>::const_iterator i = projectFiles.begin();
while (i != projectFiles.end()) {
QStringList dependencies;
foreach (const QString &dependency, m_file->m_depMap.value(*i)) {
if (projectFiles.contains(dependency))
dependencies << dependency;
}
if (!dependencies.isEmpty())
resMap.insert(*i, dependencies);
++i;
}
m_file->m_depMap = resMap;
if (startupProject() == 0)
if (!m_file->m_projects.isEmpty())
setStartupProject(m_file->m_projects.first());
2008-12-02 12:01:29 +01:00
}
void SessionManager::setValue(const QString &name, const QVariant &value)
{
if (!m_file)
return;
if (m_file->m_values.value(name) == value)
return;
m_file->m_values.insert(name, value);
markSessionFileDirty(false);
2008-12-02 12:01:29 +01:00
}
QVariant SessionManager::value(const QString &name)
{
if (!m_file)
2008-12-02 12:01:29 +01:00
return QVariant();
QMap<QString, QVariant>::const_iterator it = m_file->m_values.find(name);
return (it == m_file->m_values.constEnd()) ? QVariant() : *it;
2008-12-02 12:01:29 +01:00
}
QString SessionManager::activeSession() const
{
return m_sessionName;
}
QStringList SessionManager::sessions() const
{
if (m_sessions.isEmpty()) {
2010-01-11 10:22:55 +01:00
// We are not initialized yet, so do that now
QDir sessionDir(QFileInfo(m_core->settings()->fileName()).path()+ "/qtcreator/");
QList<QFileInfo> sessionFiles = sessionDir.entryInfoList(QStringList() << QLatin1String("*.qws"), QDir::NoFilter, QDir::Time);
Q_FOREACH(const QFileInfo& fileInfo, sessionFiles) {
if (fileInfo.completeBaseName() != "default")
m_sessions << fileInfo.completeBaseName();
}
m_sessions.prepend("default");
}
return m_sessions;
2008-12-02 12:01:29 +01:00
}
QString SessionManager::sessionNameToFileName(const QString &session)
{
return m_core->userResourcePath() + '/' + session + ".qws";
2008-12-02 12:01:29 +01:00
}
void SessionManager::createAndLoadNewDefaultSession()
{
updateName("default");
createImpl(sessionNameToFileName(m_sessionName));
}
bool SessionManager::createSession(const QString &session)
{
if (sessions().contains(session))
return false;
Q_ASSERT(m_sessions.size() > 0);
m_sessions.insert(1, session);
2008-12-02 12:01:29 +01:00
return true;
}
bool SessionManager::renameSession(const QString &original, const QString &newName)
{
if (!cloneSession(original, newName))
return false;
if (original == activeSession())
loadSession(newName);
return deleteSession(original);
}
2008-12-02 12:01:29 +01:00
bool SessionManager::deleteSession(const QString &session)
{
if (!m_sessions.contains(session))
2008-12-02 12:01:29 +01:00
return false;
m_sessions.removeOne(session);
2008-12-02 12:01:29 +01:00
QFile fi(sessionNameToFileName(session));
if (fi.exists())
return fi.remove();
return false;
}
bool SessionManager::cloneSession(const QString &original, const QString &clone)
{
if (!m_sessions.contains(original))
2008-12-02 12:01:29 +01:00
return false;
QFile fi(sessionNameToFileName(original));
// If the file does not exist, we can still clone
if (!fi.exists() || fi.copy(sessionNameToFileName(clone))) {
Q_ASSERT(m_sessions.size() > 0);
m_sessions.insert(1, clone);
2008-12-02 12:01:29 +01:00
return true;
}
return false;
}
bool SessionManager::loadSession(const QString &session)
{
// Do nothing if we have that session already loaded,
// exception if the session is the default virgin session
// we still want to be able to load the default session
if (session == m_sessionName && !isDefaultVirgin())
return true;
if (!sessions().contains(session))
return false;
QString fileName = sessionNameToFileName(session);
if (QFileInfo(fileName).exists()) {
if (loadImpl(fileName)) {
updateName(session);
return true;
}
} else {
// Create a new session with that name
2008-12-09 11:07:24 +01:00
if (!createImpl(sessionNameToFileName(session)))
2008-12-02 12:01:29 +01:00
return false;
updateName(session);
return true;
}
return false;
}
QString SessionManager::lastSession() const
{
QSettings *settings = m_core->settings();
QString fileName = settings->value("ProjectExplorer/StartupSession").toString();
return QFileInfo(fileName).completeBaseName();
2008-12-02 12:01:29 +01:00
}
SessionNode *SessionManager::sessionNode() const
{
return m_sessionNode;
}
void SessionManager::reportProjectLoadingProgress()
{
m_file->sessionLoadingProgress();
}
void SessionManager::markSessionFileDirty(bool makeDefaultVirginDirty)
{
if (m_file && !m_file->fileName().isEmpty())
m_autoSaveSessionTimer->start();
if (makeDefaultVirginDirty)
m_virginSession = false;
}
2008-12-02 12:01:29 +01:00
#include "session.moc"