Commit 0cd8da28 authored by dt's avatar dt
Browse files

Fixes: Crashes on switching sessions.

Task:     Reported on irc
Details:  Hopefully this new code is a little bit more robust, i tried
to untangle the code a bit.
parent 047e5af2
...@@ -1121,7 +1121,7 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node ...@@ -1121,7 +1121,7 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node
if (node) if (node)
filePath = node->path(); filePath = node->path();
else else
node = m_session->nodeForFile(filePath); node = m_session->nodeForFile(filePath, project);
Core::ICore *core = Core::ICore::instance(); Core::ICore *core = Core::ICore::instance();
......
...@@ -65,10 +65,9 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) ...@@ -65,10 +65,9 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent)
m_projectExplorer = ProjectExplorerPlugin::instance(); m_projectExplorer = ProjectExplorerPlugin::instance();
m_session = m_projectExplorer->session(); m_session = m_projectExplorer->session();
connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus()));
connect(m_session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus()));
m_treeWidget = new QTreeWidget(this); m_treeWidget = new QTreeWidget(this);
m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
m_treeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_treeWidget->setFrameStyle(QFrame::NoFrame); m_treeWidget->setFrameStyle(QFrame::NoFrame);
m_treeWidget->setRootIsDecorated(false); m_treeWidget->setRootIsDecorated(false);
m_treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); m_treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents);
...@@ -79,7 +78,7 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) ...@@ -79,7 +78,7 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent)
); );
connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
this, SLOT(handleItem(QTreeWidgetItem*, int)), Qt::QueuedConnection); this, SLOT(handleItem(QTreeWidgetItem*, int)));
connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem *)), connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem *)),
this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*))); this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*)));
...@@ -116,10 +115,14 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) ...@@ -116,10 +115,14 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent)
topLayout->setSpacing(0); topLayout->setSpacing(0);
topLayout->addWidget(splitter); topLayout->addWidget(splitter);
connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(updateTreeWidget())); connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus()));
connect(m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget())); connect(m_session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus()));
connect(m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget()));
connect(m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget())); connect(m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project*)));
connect(m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetProjectAdded(ProjectExplorer::Project*)));
connect(m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetProjectRemoved(ProjectExplorer::Project*)));
connect(m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project*)));
} }
ProjectWindow::~ProjectWindow() ProjectWindow::~ProjectWindow()
...@@ -128,12 +131,21 @@ ProjectWindow::~ProjectWindow() ...@@ -128,12 +131,21 @@ ProjectWindow::~ProjectWindow()
void ProjectWindow::restoreStatus() void ProjectWindow::restoreStatus()
{ {
m_panelsTabWidget->setFocus();
if (!m_treeWidget->currentItem() && m_treeWidget->topLevelItemCount()) {
m_treeWidget->setCurrentItem(m_treeWidget->topLevelItem(0), 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}
const QVariant lastPanel = m_session->value(QLatin1String("ProjectWindow/Panel")); const QVariant lastPanel = m_session->value(QLatin1String("ProjectWindow/Panel"));
if (lastPanel.isValid()) { if (lastPanel.isValid()) {
const int index = lastPanel.toInt(); const int index = lastPanel.toInt();
if (index < m_panelsTabWidget->count()) if (index < m_panelsTabWidget->count())
m_panelsTabWidget->setCurrentIndex(index); m_panelsTabWidget->setCurrentIndex(index);
} }
if ((m_panelsTabWidget->currentIndex() == -1) && m_panelsTabWidget->count())
m_panelsTabWidget->setCurrentIndex(0);
} }
void ProjectWindow::saveStatus() void ProjectWindow::saveStatus()
...@@ -172,52 +184,69 @@ void ProjectWindow::showProperties(ProjectExplorer::Project *project, const QMod ...@@ -172,52 +184,69 @@ void ProjectWindow::showProperties(ProjectExplorer::Project *project, const QMod
} }
} }
void ProjectWindow::updateTreeWidget() void ProjectWindow::updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project *startupProject)
{ {
// This setFocus prevents a crash, which I (daniel) spend the better part of a day tracking down. int count = m_treeWidget->topLevelItemCount();
// To explain: Consider the case that a widget on either the build or run settings has Focus for (int i = 0; i < count; ++i) {
// Us clearing the m_treewidget will emit a currentItemChanged(0) signal QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
// Which is connected to showProperties if (Project *project = findProject(item->text(2))) {
// showProperties will now remove the widget that has focus from m_panelsTabWidget, so the treewidget bool checked = (startupProject == project);
// gets focus, which will in focusIn select the first entry (due to QTreeWidget::clear() implementation, if (item->checkState(1) != (checked ? Qt::Checked : Qt::Unchecked))
// there are still items in the model) which emits another currentItemChanged() signal item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked);
// That one runs fully thorough and deletes all widgets, even that one that we are currently removing } else {
// from m_panelsTabWidget. item->setCheckState(1, Qt::Unchecked);
// To prevent that, we simply prevent the focus switching....
QWidget *focusWidget = qApp->focusWidget();
while (focusWidget) {
if (focusWidget == this) {
m_treeWidget->setFocus();
break;
} }
focusWidget = focusWidget->parentWidget();
} }
m_treeWidget->clear(); }
foreach(Project *project, m_session->projects()) { void ProjectWindow::updateTreeWidgetProjectAdded(ProjectExplorer::Project *projectAdded)
const QFileInfo fileInfo(project->file()->fileName()); {
int position = m_session->projects().indexOf(projectAdded);
const QFileInfo fileInfo(projectAdded->file()->fileName());
QTreeWidgetItem *item = new QTreeWidgetItem(); QTreeWidgetItem *item = new QTreeWidgetItem();
item->setText(0, fileInfo.baseName()); item->setText(0, fileInfo.baseName());
item->setIcon(0, Core::FileIconProvider::instance()->icon(fileInfo)); item->setIcon(0, Core::FileIconProvider::instance()->icon(fileInfo));
item->setText(2, fileInfo.filePath()); item->setText(2, fileInfo.filePath());
if (project->isApplication()) { if (projectAdded->isApplication()) {
bool checked = (m_session->startupProject() == project); bool checked = (m_session->startupProject() == projectAdded);
item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked); item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked);
} }
m_treeWidget->addTopLevelItem(item); m_treeWidget->insertTopLevelItem(position, item);
}
void ProjectWindow::updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project *projectRemoved) {
int count = m_treeWidget->topLevelItemCount();
for (int i = 0; i < count; ++i) {
QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
if (item->text(2) == QFileInfo(projectRemoved->file()->fileName()).filePath()) {
if (m_treeWidget->currentItem() == item) {
m_treeWidget->setCurrentItem(0);
}
}
} }
} }
void ProjectWindow::updateTreeWidgetProjectRemoved(ProjectExplorer::Project *projectRemoved)
{
int count = m_treeWidget->topLevelItemCount();
for (int i = 0; i < count; ++i) {
QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
if (item->text(2) == QFileInfo(projectRemoved->file()->fileName()).filePath()) {
QTreeWidgetItem *it = m_treeWidget->takeTopLevelItem(i);
delete it;
break;
}
}
}
Project *ProjectWindow::findProject(const QString &path) const Project *ProjectWindow::findProject(const QString &path) const
{ {
QList<Project*> projects = m_session->projects(); QList<Project*> projects = m_session->projects();
foreach (Project* project, projects) foreach (Project* project, projects)
if (project->file()->fileName() == path) if (QFileInfo(project->file()->fileName()).filePath() == path)
return project; return project;
return 0; return 0;
} }
...@@ -232,22 +261,26 @@ void ProjectWindow::handleCurrentItemChanged(QTreeWidgetItem *current) ...@@ -232,22 +261,26 @@ void ProjectWindow::handleCurrentItemChanged(QTreeWidgetItem *current)
showProperties(project, QModelIndex()); showProperties(project, QModelIndex());
return; return;
} }
} else {
showProperties(0, QModelIndex());
} }
} }
void ProjectWindow::handleItem(QTreeWidgetItem *item, int column) void ProjectWindow::handleItem(QTreeWidgetItem *item, int column)
{ {
if (!item || column != 1) // startup project if (!item || column != 1) // startup project
return; return;
const QString path = item->text(2); const QString path = item->text(2);
Project *project = findProject(path); Project *project = findProject(path);
if (project && project->isApplication()) { if (project && project->isApplication()) {
if (!(item->checkState(1) == Qt::Checked)) { if (!(item->checkState(1) == Qt::Checked)) { // is now unchecked
item->setCheckState(1, Qt::Checked); // uncheck not supported if (m_session->startupProject() == project) {
} else { item->setCheckState(1, Qt::Checked); // uncheck not supported
}
} else { // is now checked
m_session->setStartupProject(project); m_session->setStartupProject(project);
} }
} }
......
...@@ -62,6 +62,12 @@ private slots: ...@@ -62,6 +62,12 @@ private slots:
void saveStatus(); void saveStatus();
void updateTreeWidget(); void updateTreeWidget();
void updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project *startupProject);
void updateTreeWidgetProjectAdded(ProjectExplorer::Project *addedProject);
void updateTreeWidgetProjectRemoved(ProjectExplorer::Project *removedProject);
void updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project *removedProject);
void handleItem(QTreeWidgetItem *item, int column); void handleItem(QTreeWidgetItem *item, int column);
void handleCurrentItemChanged(QTreeWidgetItem *); void handleCurrentItemChanged(QTreeWidgetItem *);
......
...@@ -826,10 +826,12 @@ Project *SessionManager::projectForNode(Node *node) const ...@@ -826,10 +826,12 @@ Project *SessionManager::projectForNode(Node *node) const
return project; return project;
} }
Node *SessionManager::nodeForFile(const QString &fileName) const Node *SessionManager::nodeForFile(const QString &fileName, Project *project) const
{ {
Node *node = 0; Node *node = 0;
if (Project *project = projectForFile(fileName)) { if (!project)
project = projectForFile(fileName);
if (project) {
FindNodesForFileVisitor findNodes(fileName); FindNodesForFileVisitor findNodes(fileName);
project->rootProjectNode()->accept(&findNodes); project->rootProjectNode()->accept(&findNodes);
......
...@@ -144,7 +144,7 @@ public: ...@@ -144,7 +144,7 @@ public:
SessionNode *sessionNode() const; SessionNode *sessionNode() const;
Project *projectForNode(ProjectExplorer::Node *node) const; Project *projectForNode(ProjectExplorer::Node *node) const;
Node *nodeForFile(const QString &fileName) const; Node *nodeForFile(const QString &fileName, Project *project = 0) const;
Project *projectForFile(const QString &fileName) const; Project *projectForFile(const QString &fileName) 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