Chris@127: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@127: 
Chris@127: /*
Chris@127:     Sonic Visualiser
Chris@127:     An audio file viewer and annotation editor.
Chris@127:     Centre for Digital Music, Queen Mary, University of London.
Chris@182:     This file copyright 2006 Chris Cannam and QMUL.
Chris@127:     
Chris@127:     This program is free software; you can redistribute it and/or
Chris@127:     modify it under the terms of the GNU General Public License as
Chris@127:     published by the Free Software Foundation; either version 2 of the
Chris@127:     License, or (at your option) any later version.  See the file
Chris@127:     COPYING included with this distribution for more information.
Chris@127: */
Chris@127: 
Chris@127: #include "PaneStack.h"
Chris@127: 
Chris@128: #include "Pane.h"
Chris@127: #include "widgets/PropertyStack.h"
Chris@323: #include "widgets/IconLoader.h"
Chris@500: #include "widgets/ClickableLabel.h"
Chris@128: #include "layer/Layer.h"
Chris@128: #include "ViewManager.h"
Chris@127: 
Chris@127: #include <QApplication>
Chris@127: #include <QHBoxLayout>
Chris@323: #include <QVBoxLayout>
Chris@127: #include <QPainter>
Chris@127: #include <QPalette>
Chris@127: #include <QLabel>
Chris@323: #include <QPushButton>
Chris@127: #include <QSplitter>
Chris@127: #include <QStackedWidget>
Chris@127: 
Chris@127: #include <iostream>
Chris@127: 
Chris@247: //#define DEBUG_PANE_STACK 1
Chris@247: 
Chris@127: PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) :
Chris@127:     QFrame(parent),
Chris@127:     m_currentPane(0),
Chris@127:     m_splitter(new QSplitter),
Chris@127:     m_propertyStackStack(new QStackedWidget),
Chris@127:     m_viewManager(viewManager),
Chris@615:     m_propertyStackMinWidth(100),
Chris@127:     m_layoutStyle(PropertyStackPerPaneLayout)
Chris@127: {
Chris@127:     QHBoxLayout *layout = new QHBoxLayout;
Chris@127:     layout->setMargin(0);
Chris@127:     layout->setSpacing(0);
Chris@127: 
Chris@127:     m_splitter->setOrientation(Qt::Vertical);
Chris@127:     m_splitter->setOpaqueResize(false);
Chris@127: 
Chris@127:     layout->addWidget(m_splitter);
Chris@127:     layout->setStretchFactor(m_splitter, 1);
Chris@127:     layout->addWidget(m_propertyStackStack);
Chris@127:     m_propertyStackStack->hide();
Chris@127: 
Chris@127:     setLayout(layout);
Chris@127: }
Chris@127: 
Chris@127: Pane *
Chris@127: PaneStack::addPane(bool suppressPropertyBox)
Chris@127: {
Chris@539:     return insertPane(getPaneCount(), suppressPropertyBox);
Chris@539: }
Chris@539: 
Chris@539: Pane *
Chris@539: PaneStack::insertPane(int index, bool suppressPropertyBox)
Chris@539: {
Chris@127:     QFrame *frame = new QFrame;
Chris@495: 
Chris@495:     QGridLayout *layout = new QGridLayout;
Chris@127:     layout->setMargin(0);
Chris@127:     layout->setSpacing(2);
Chris@127: 
Chris@323:     QPushButton *xButton = new QPushButton(frame);
Chris@323:     xButton->setIcon(IconLoader().load("cross"));
Chris@323:     xButton->setFixedSize(QSize(16, 16));
Chris@497:     xButton->setFlat(true);
Chris@495:     layout->addWidget(xButton, 0, 0);
Chris@323:     connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked()));
Chris@323: 
Chris@500:     ClickableLabel *currentIndicator = new ClickableLabel(frame);
Chris@500:     connect(currentIndicator, SIGNAL(clicked()), this, SLOT(indicatorClicked()));
Chris@495:     layout->addWidget(currentIndicator, 1, 0);
Chris@495:     layout->setRowStretch(1, 20);
Chris@497:     currentIndicator->setMinimumWidth(8);
Chris@127:     currentIndicator->setScaledContents(true);
Chris@127: 
Chris@516:     long initialCentreFrame = -1;
Chris@516:     for (int i = 0; i < m_panes.size(); ++i) {
Chris@516:         long f = m_panes[i].pane->getCentreFrame();
Chris@516:         initialCentreFrame = f;
Chris@516:         break;
Chris@516:     }
Chris@516: 
Chris@127:     Pane *pane = new Pane(frame);
Chris@516:     if (initialCentreFrame >= 0) {
Chris@516:         pane->setViewManager(m_viewManager, initialCentreFrame);
Chris@516:     } else {
Chris@516:         pane->setViewManager(m_viewManager);
Chris@516:     }
Chris@495:     layout->addWidget(pane, 0, 1, 2, 1);
Chris@495:     layout->setColumnStretch(1, 20);
Chris@127: 
Chris@127:     QWidget *properties = 0;
Chris@127:     if (suppressPropertyBox) {
Chris@127: 	properties = new QFrame();
Chris@127:     } else {
Chris@127: 	properties = new PropertyStack(frame, pane);
Chris@127: 	connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@127: 		this, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@190:         connect(properties, SIGNAL(viewSelected(View  *)),
Chris@190:                 this, SLOT(viewSelected(View *)));
Chris@189:         connect(properties, SIGNAL(contextHelpChanged(const QString &)),
Chris@189:                 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@127:     }
Chris@127:     if (m_layoutStyle == PropertyStackPerPaneLayout) {
Chris@495:         layout->addWidget(properties, 0, 2, 2, 1);
Chris@127:     } else {
Chris@127:         properties->setParent(m_propertyStackStack);
Chris@127:         m_propertyStackStack->addWidget(properties);
Chris@127:     }
Chris@606:     layout->setColumnStretch(2, 0);
Chris@127: 
Chris@127:     PaneRec rec;
Chris@127:     rec.pane = pane;
Chris@127:     rec.propertyStack = properties;
Chris@605:     rec.xButton = xButton;
Chris@127:     rec.currentIndicator = currentIndicator;
Chris@127:     rec.frame = frame;
Chris@127:     rec.layout = layout;
Chris@127:     m_panes.push_back(rec);
Chris@127: 
Chris@127:     frame->setLayout(layout);
Chris@539:     m_splitter->insertWidget(index, frame);
Chris@127: 
Chris@127:     connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@127: 	    this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@127:     connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@127: 	    this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@127:     connect(pane, SIGNAL(paneInteractedWith()),
Chris@127: 	    this, SLOT(paneInteractedWith()));
Chris@127:     connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)),
Chris@127:             this, SLOT(rightButtonMenuRequested(QPoint)));
Chris@312:     connect(pane, SIGNAL(dropAccepted(QStringList)),
Chris@312:             this, SLOT(paneDropAccepted(QStringList)));
Chris@312:     connect(pane, SIGNAL(dropAccepted(QString)),
Chris@312:             this, SLOT(paneDropAccepted(QString)));
Chris@127: 
Chris@271:     emit paneAdded(pane);
Chris@271:     emit paneAdded();
Chris@271: 
Chris@127:     if (!m_currentPane) {
Chris@127: 	setCurrentPane(pane);
Chris@127:     }
Chris@127: 
Chris@605:     showOrHidePaneAccessories();
Chris@605: 
Chris@127:     return pane;
Chris@127: }
Chris@127: 
Chris@127: void
Chris@235: PaneStack::setPropertyStackMinWidth(int mw)
Chris@235: {
Chris@235:     for (std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@235:          i != m_panes.end(); ++i) {
Chris@235:         i->propertyStack->setMinimumWidth(mw);
Chris@235:     }
Chris@235:     m_propertyStackMinWidth = mw;
Chris@235: }
Chris@235: 
Chris@235: void
Chris@127: PaneStack::setLayoutStyle(LayoutStyle style)
Chris@127: {
Chris@127:     if (style == m_layoutStyle) return;
Chris@127:     m_layoutStyle = style;
Chris@127: 
Chris@127:     std::vector<PaneRec>::iterator i;
Chris@127: 
Chris@127:     switch (style) {
Chris@127: 
Chris@179:     case NoPropertyStacks:
Chris@127:     case SinglePropertyStackLayout:
Chris@127:         
Chris@127:         for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@127:             i->layout->removeWidget(i->propertyStack);
Chris@127:             i->propertyStack->setParent(m_propertyStackStack);
Chris@127:             m_propertyStackStack->addWidget(i->propertyStack);
Chris@127:         }
Chris@179:         m_propertyStackStack->setVisible(style != NoPropertyStacks);
Chris@127:         break;
Chris@127: 
Chris@127:     case PropertyStackPerPaneLayout:
Chris@127: 
Chris@127:         for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@127:             m_propertyStackStack->removeWidget(i->propertyStack);
Chris@127:             i->propertyStack->setParent(i->frame);
Chris@495:             i->layout->addWidget(i->propertyStack, 0, 2, 2, 1);
Chris@127:             i->propertyStack->show();
Chris@127:         }
Chris@127:         m_propertyStackStack->hide();
Chris@127:         break;
Chris@127:     }
Chris@127: }
Chris@127: 
Chris@127: Pane *
Chris@127: PaneStack::getPane(int n)
Chris@127: {
Chris@277:     if (n < m_panes.size()) {
Chris@277:         return m_panes[n].pane;
Chris@277:     } else {
Chris@277:         return 0;
Chris@277:     }
Chris@277: }
Chris@277: 
Chris@277: int
Chris@277: PaneStack::getPaneIndex(Pane *pane)
Chris@277: {
Chris@277:     for (int i = 0; i < getPaneCount(); ++i) {
Chris@277:         if (pane == getPane(i)) {
Chris@277:             return i;
Chris@277:         }
Chris@277:     }
Chris@277:     return -1;
Chris@127: }
Chris@127: 
Chris@127: Pane *
Chris@127: PaneStack::getHiddenPane(int n)
Chris@127: {
Chris@127:     return m_hiddenPanes[n].pane;
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::deletePane(Pane *pane)
Chris@127: {
Chris@127:     std::vector<PaneRec>::iterator i;
Chris@127:     bool found = false;
Chris@127: 
Chris@127:     for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@127: 	if (i->pane == pane) {
Chris@127: 	    m_panes.erase(i);
Chris@127: 	    found = true;
Chris@127: 	    break;
Chris@127: 	}
Chris@127:     }
Chris@127: 
Chris@127:     if (!found) {
Chris@127: 
Chris@127: 	for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) {
Chris@127: 	    if (i->pane == pane) {
Chris@127: 		m_hiddenPanes.erase(i);
Chris@127: 		found = true;
Chris@127: 		break;
Chris@127: 	    }
Chris@127: 	}
Chris@127: 
Chris@127: 	if (!found) {
Chris@127: 	    std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl;
Chris@127: 	    return;
Chris@127: 	}
Chris@127:     }
Chris@127: 
Chris@271:     emit paneAboutToBeDeleted(pane);
Chris@271: 
Chris@127:     delete pane->parent();
Chris@127: 
Chris@127:     if (m_currentPane == pane) {
Chris@127: 	if (m_panes.size() > 0) {
Chris@127:             setCurrentPane(m_panes[0].pane);
Chris@127: 	} else {
Chris@127: 	    setCurrentPane(0);
Chris@127: 	}
Chris@127:     }
Chris@271: 
Chris@605:     showOrHidePaneAccessories();
Chris@605: 
Chris@271:     emit paneDeleted();
Chris@127: }
Chris@127: 
Chris@605: void
Chris@605: PaneStack::showOrHidePaneAccessories()
Chris@605: {
Chris@605:     std::cerr << "PaneStack::showOrHidePaneAccessories: count == " << getPaneCount() << std::endl;
Chris@605: 
Chris@605:     bool multi = (getPaneCount() > 1);
Chris@605:     for (std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@605:          i != m_panes.end(); ++i) {
Chris@605:         i->xButton->setVisible(multi);
Chris@605:         i->currentIndicator->setVisible(multi);
Chris@605:     }
Chris@605: }
Chris@605: 
Chris@127: int
Chris@127: PaneStack::getPaneCount() const
Chris@127: {
Chris@127:     return m_panes.size();
Chris@127: }
Chris@127: 
Chris@127: int
Chris@127: PaneStack::getHiddenPaneCount() const
Chris@127: {
Chris@127:     return m_hiddenPanes.size();
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::hidePane(Pane *pane)
Chris@127: {
Chris@127:     std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127: 
Chris@127:     while (i != m_panes.end()) {
Chris@127: 	if (i->pane == pane) {
Chris@127: 
Chris@127: 	    m_hiddenPanes.push_back(*i);
Chris@127: 	    m_panes.erase(i);
Chris@127: 
Chris@127: 	    QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@127: 	    if (pw) pw->hide();
Chris@127: 
Chris@127: 	    if (m_currentPane == pane) {
Chris@127: 		if (m_panes.size() > 0) {
Chris@127: 		    setCurrentPane(m_panes[0].pane);
Chris@127: 		} else {
Chris@127: 		    setCurrentPane(0);
Chris@127: 		}
Chris@127: 	    }
Chris@127: 	    
Chris@605:             showOrHidePaneAccessories();
Chris@605:             emit paneHidden(pane);
Chris@605:             emit paneHidden();
Chris@127: 	    return;
Chris@127: 	}
Chris@127: 	++i;
Chris@127:     }
Chris@127: 
Chris@127:     std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl;
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::showPane(Pane *pane)
Chris@127: {
Chris@127:     std::vector<PaneRec>::iterator i = m_hiddenPanes.begin();
Chris@127: 
Chris@127:     while (i != m_hiddenPanes.end()) {
Chris@127: 	if (i->pane == pane) {
Chris@127: 	    m_panes.push_back(*i);
Chris@127: 	    m_hiddenPanes.erase(i);
Chris@127: 	    QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@127: 	    if (pw) pw->show();
Chris@127: 
Chris@127: 	    //!!! update current pane
Chris@127: 
Chris@605:             showOrHidePaneAccessories();
Chris@605: 
Chris@127: 	    return;
Chris@127: 	}
Chris@127: 	++i;
Chris@127:     }
Chris@127: 
Chris@127:     std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl;
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::setCurrentPane(Pane *pane) // may be null
Chris@127: {
Chris@127:     if (m_currentPane == pane) return;
Chris@127:     
Chris@127:     std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127: 
Chris@127:     // We used to do this by setting the foreground and background
Chris@127:     // role, but it seems the background role is ignored and the
Chris@127:     // background drawn transparent in Qt 4.1 -- I can't quite see why
Chris@127:     
Chris@127:     QPixmap selectedMap(1, 1);
Chris@127:     selectedMap.fill(QApplication::palette().color(QPalette::Foreground));
Chris@127:     
Chris@127:     QPixmap unselectedMap(1, 1);
Chris@127:     unselectedMap.fill(QApplication::palette().color(QPalette::Background));
Chris@127: 
Chris@127:     bool found = false;
Chris@127: 
Chris@127:     while (i != m_panes.end()) {
Chris@127: 	if (i->pane == pane) {
Chris@127: 	    i->currentIndicator->setPixmap(selectedMap);
Chris@179:             if (m_layoutStyle != PropertyStackPerPaneLayout) {
Chris@127:                 m_propertyStackStack->setCurrentWidget(i->propertyStack);
Chris@127:             }
Chris@127: 	    found = true;
Chris@127: 	} else {
Chris@127: 	    i->currentIndicator->setPixmap(unselectedMap);
Chris@127: 	}
Chris@127: 	++i;
Chris@127:     }
Chris@127: 
Chris@127:     if (found || pane == 0) {
Chris@127: 	m_currentPane = pane;
Chris@127: 	emit currentPaneChanged(m_currentPane);
Chris@127:     } else {
Chris@127: 	std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl;
Chris@127:     }
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null
Chris@127: {
Chris@127:     setCurrentPane(pane);
Chris@127: 
Chris@127:     if (m_currentPane) {
Chris@127: 
Chris@127: 	std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127: 
Chris@127: 	while (i != m_panes.end()) {
Chris@127: 
Chris@127: 	    if (i->pane == pane) {
Chris@127: 		PropertyStack *stack = dynamic_cast<PropertyStack *>
Chris@127: 		    (i->propertyStack);
Chris@127: 		if (stack) {
Chris@127: 		    if (stack->containsContainer(layer)) {
Chris@127: 			stack->setCurrentIndex(stack->getContainerIndex(layer));
Chris@127: 			emit currentLayerChanged(pane, layer);
Chris@127: 		    } else {
Chris@127: 			stack->setCurrentIndex
Chris@127: 			    (stack->getContainerIndex
Chris@127: 			     (pane->getPropertyContainer(0)));
Chris@127: 			emit currentLayerChanged(pane, 0);
Chris@127: 		    }
Chris@127: 		}
Chris@127: 		break;
Chris@127: 	    }
Chris@127: 	    ++i;
Chris@127: 	}
Chris@127:     }
Chris@127: }
Chris@127: 
Chris@127: Pane *
Chris@127: PaneStack::getCurrentPane() 
Chris@127: {
Chris@127:     return m_currentPane;
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::propertyContainerAdded(PropertyContainer *)
Chris@127: {
Chris@127:     sizePropertyStacks();
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::propertyContainerRemoved(PropertyContainer *)
Chris@127: {
Chris@127:     sizePropertyStacks();
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc)
Chris@127: {
Chris@127:     std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127: 
Chris@127:     while (i != m_panes.end()) {
Chris@127: 	PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack);
Chris@127: 	if (stack &&
Chris@127: 	    stack->getClient() == client &&
Chris@127: 	    stack->containsContainer(pc)) {
Chris@127: 	    setCurrentPane(i->pane);
Chris@127: 	    break;
Chris@127: 	}
Chris@127: 	++i;
Chris@127:     }
Chris@127: 
Chris@127:     Layer *layer = dynamic_cast<Layer *>(pc);
Chris@127:     if (layer) emit currentLayerChanged(m_currentPane, layer);
Chris@127:     else emit currentLayerChanged(m_currentPane, 0);
Chris@127: }
Chris@127: 
Chris@127: void
Chris@190: PaneStack::viewSelected(View *v)
Chris@190: {
Chris@190:     Pane *p = dynamic_cast<Pane *>(v);
Chris@190:     if (p) setCurrentPane(p);
Chris@190: }
Chris@190: 
Chris@190: void
Chris@127: PaneStack::paneInteractedWith()
Chris@127: {
Chris@127:     Pane *pane = dynamic_cast<Pane *>(sender());
Chris@127:     if (!pane) return;
Chris@127:     setCurrentPane(pane);
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::rightButtonMenuRequested(QPoint position)
Chris@127: {
Chris@127:     Pane *pane = dynamic_cast<Pane *>(sender());
Chris@127:     if (!pane) return;
Chris@127:     emit rightButtonMenuRequested(pane, position);
Chris@127: }
Chris@127: 
Chris@127: void
Chris@127: PaneStack::sizePropertyStacks()
Chris@127: {
Chris@127:     int maxMinWidth = 0;
Chris@127: 
Chris@235:     if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth;
Chris@235: 
Chris@127:     for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@127: 	if (!m_panes[i].propertyStack) continue;
Chris@247: #ifdef DEBUG_PANE_STACK
Chris@587: 	SVDEBUG << "PaneStack::sizePropertyStacks: " << i << ": min " 
Chris@243: 		  << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint "
Chris@243:                   << m_panes[i].propertyStack->sizeHint().width() << ", current "
Chris@585: 		  << m_panes[i].propertyStack->width() << endl;
Chris@247: #endif
Chris@127: 
Chris@246: 	if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) {
Chris@246: 	    maxMinWidth = m_panes[i].propertyStack->sizeHint().width();
Chris@127: 	}
Chris@127:     }
Chris@127: 
Chris@247: #ifdef DEBUG_PANE_STACK
Chris@587:     SVDEBUG << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << endl;
Chris@247: #endif
Chris@127: 
Chris@127:     int setWidth = maxMinWidth;
Chris@127: 
Chris@127:     m_propertyStackStack->setMaximumWidth(setWidth + 10);
Chris@127: 
Chris@127:     for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@127: 	if (!m_panes[i].propertyStack) continue;
Chris@127: 	m_panes[i].propertyStack->setMinimumWidth(setWidth);
Chris@127:     }
Chris@180: 
Chris@363:     emit propertyStacksResized(setWidth);
Chris@180:     emit propertyStacksResized();
Chris@127: }
Chris@127:     
Chris@312: void
Chris@312: PaneStack::paneDropAccepted(QStringList uriList)
Chris@312: {
Chris@312:     Pane *pane = dynamic_cast<Pane *>(sender());
Chris@312:     emit dropAccepted(pane, uriList);
Chris@312: }
Chris@312:     
Chris@312: void
Chris@312: PaneStack::paneDropAccepted(QString text)
Chris@312: {
Chris@312:     Pane *pane = dynamic_cast<Pane *>(sender());
Chris@312:     emit dropAccepted(pane, text);
Chris@312: }
Chris@127: 
Chris@320: void
Chris@323: PaneStack::paneDeleteButtonClicked()
Chris@323: {
Chris@323:     QObject *s = sender();
Chris@605:     for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@605: 	if (m_panes[i].xButton == s) {
Chris@605:             emit paneDeleteButtonClicked(m_panes[i].pane);
Chris@323:         }
Chris@323:     }
Chris@323: }
Chris@323: 
Chris@323: void
Chris@500: PaneStack::indicatorClicked()
Chris@500: {
Chris@500:     QObject *s = sender();
Chris@500: 
Chris@500:     for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@500: 	if (m_panes[i].currentIndicator == s) {
Chris@500:             setCurrentPane(m_panes[i].pane);
Chris@500:             return;
Chris@500:         }
Chris@500:     }
Chris@500: }
Chris@500: 
Chris@500: void
Chris@320: PaneStack::sizePanesEqually()
Chris@320: {
Chris@320:     QList<int> sizes = m_splitter->sizes();
Chris@320:     if (sizes.empty()) return;
Chris@320: 
Chris@320:     int count = sizes.size();
Chris@320: 
Chris@320:     int total = 0;
Chris@320:     for (int i = 0; i < count; ++i) {
Chris@320:         total += sizes[i];
Chris@320:     }
Chris@320: 
Chris@320:     if (total == 0) return;
Chris@320: 
Chris@320:     sizes.clear();
Chris@320: 
Chris@320:     int each = total / count;
Chris@320:     int remaining = total;
Chris@320: 
Chris@320:     for (int i = 0; i < count; ++i) {
Chris@320:         if (i == count - 1) {
Chris@320:             sizes.push_back(remaining);
Chris@320:         } else {
Chris@320:             sizes.push_back(each);
Chris@320:             remaining -= each;
Chris@320:         }
Chris@320:     }
Chris@320: 
Chris@320: /*
Chris@320:     std::cerr << "sizes: ";
Chris@320:     for (int i = 0; i < sizes.size(); ++i) {
Chris@320:         std::cerr << sizes[i] << " ";
Chris@320:     }
Chris@320:     std::cerr << std::endl;
Chris@320: */
Chris@320: 
Chris@320:     m_splitter->setSizes(sizes);
Chris@320: }
Chris@320: 
Chris@320: