Fix issue 298: Crash on quit with multiple viewports open

This commit is contained in:
David Capello 2014-01-26 11:22:23 -03:00
parent 11f864da12
commit c2e50acb0b
4 changed files with 64 additions and 23 deletions

View File

@ -71,10 +71,17 @@ void Workspace::removeView(WorkspaceView* view)
ASSERT(it != m_views.end());
m_views.erase(it);
m_activePart->removeView(view);
if (m_activePart->getViewCount() == 0 &&
m_activePart->getParent() != this) {
m_activePart = destroyPart(m_activePart);
WorkspacePart* part = getPartByView(view);
ASSERT(part != NULL);
part->removeView(view);
if (part->getViewCount() == 0 &&
part->getParent() != this) {
bool activePartRemoved = (m_activePart == part);
WorkspacePart* otherPart = destroyPart(part);
if (activePartRemoved)
m_activePart = otherPart;
}
App::instance()->getMainWindow()->getTabsBar()->removeTab(dynamic_cast<TabView*>(view));
@ -173,29 +180,18 @@ WorkspacePart* Workspace::destroyPart(WorkspacePart* part)
void Workspace::makeUnique(WorkspaceView* view)
{
std::vector<WorkspacePart*> parts;
std::queue<Widget*> remaining;
remaining.push(getFirstChild());
while (!remaining.empty()) {
Widget* widget = remaining.front();
remaining.pop();
WorkspaceParts parts;
enumAllParts(parts);
WorkspacePart* part = dynamic_cast<WorkspacePart*>(widget);
if (part && part->getParent() != this) {
while (part->getActiveView()) {
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->getParent() != this) {
while (part->getActiveView())
part->removeView(part->getActiveView());
}
parts.push_back(part);
}
else {
UI_FOREACH_WIDGET(widget->getChildren(), it) {
remaining.push(*it);
}
}
}
for (std::vector<WorkspacePart*>::iterator
it = parts.begin(), end = parts.end(); it != end; ++it) {
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->getParent() != this)
destroyPart(part);
@ -205,7 +201,7 @@ void Workspace::makeUnique(WorkspaceView* view)
ASSERT(uniquePart != NULL);
m_activePart = uniquePart;
for (WorkspaceViews::iterator it = m_views.begin(), end = m_views.end(); it != end; ++it) {
for (WorkspaceViews::iterator it=m_views.begin(), end=m_views.end(); it != end; ++it) {
WorkspaceView* v = *it;
if (!v->getContentWidget()->getParent())
uniquePart->addView(v);
@ -214,4 +210,38 @@ void Workspace::makeUnique(WorkspaceView* view)
setActiveView(view);
}
WorkspacePart* Workspace::getPartByView(WorkspaceView* view)
{
WorkspaceParts parts;
enumAllParts(parts);
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->hasView(view))
return part;
}
return NULL;
}
void Workspace::enumAllParts(WorkspaceParts& parts)
{
std::queue<Widget*> remaining;
remaining.push(getFirstChild());
while (!remaining.empty()) {
Widget* widget = remaining.front();
remaining.pop();
WorkspacePart* part = dynamic_cast<WorkspacePart*>(widget);
if (part) {
parts.push_back(part);
}
else {
UI_FOREACH_WIDGET(widget->getChildren(), it) {
remaining.push(*it);
}
}
}
}
} // namespace app

View File

@ -49,7 +49,11 @@ namespace app {
Signal0<void> ActiveViewChanged;
private:
typedef std::vector<WorkspacePart*> WorkspaceParts;
WorkspacePart* destroyPart(WorkspacePart* part);
WorkspacePart* getPartByView(WorkspaceView* view);
void enumAllParts(WorkspaceParts& parts);
// All views of all parts.
WorkspaceViews m_views;

View File

@ -87,4 +87,9 @@ void WorkspacePart::setActiveView(WorkspaceView* view)
layout();
}
bool WorkspacePart::hasView(WorkspaceView* view)
{
return (std::find(m_views.begin(), m_views.end(), view) != m_views.end());
}
} // namespace app

View File

@ -38,6 +38,8 @@ namespace app {
WorkspaceView* getActiveView() { return m_activeView; }
void setActiveView(WorkspaceView* view);
bool hasView(WorkspaceView* view);
private:
WorkspaceView* m_activeView;
WorkspaceViews m_views;