| Chris@127 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@127 | 2 | 
| Chris@127 | 3 /* | 
| Chris@127 | 4     Sonic Visualiser | 
| Chris@127 | 5     An audio file viewer and annotation editor. | 
| Chris@127 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@182 | 7     This file copyright 2006 Chris Cannam and QMUL. | 
| Chris@127 | 8 | 
| Chris@127 | 9     This program is free software; you can redistribute it and/or | 
| Chris@127 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@127 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@127 | 12     License, or (at your option) any later version.  See the file | 
| Chris@127 | 13     COPYING included with this distribution for more information. | 
| Chris@127 | 14 */ | 
| Chris@127 | 15 | 
| Chris@127 | 16 #include "PaneStack.h" | 
| Chris@127 | 17 | 
| Chris@128 | 18 #include "Pane.h" | 
| Chris@127 | 19 #include "widgets/PropertyStack.h" | 
| Chris@323 | 20 #include "widgets/IconLoader.h" | 
| Chris@500 | 21 #include "widgets/ClickableLabel.h" | 
| Chris@128 | 22 #include "layer/Layer.h" | 
| Chris@128 | 23 #include "ViewManager.h" | 
| Chris@127 | 24 | 
| Chris@127 | 25 #include <QApplication> | 
| Chris@127 | 26 #include <QHBoxLayout> | 
| Chris@323 | 27 #include <QVBoxLayout> | 
| Chris@127 | 28 #include <QPainter> | 
| Chris@127 | 29 #include <QPalette> | 
| Chris@127 | 30 #include <QLabel> | 
| Chris@323 | 31 #include <QPushButton> | 
| Chris@127 | 32 #include <QSplitter> | 
| Chris@127 | 33 #include <QStackedWidget> | 
| Chris@127 | 34 | 
| Chris@127 | 35 #include <iostream> | 
| Chris@127 | 36 | 
| Chris@247 | 37 //#define DEBUG_PANE_STACK 1 | 
| Chris@247 | 38 | 
| Chris@127 | 39 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : | 
| Chris@127 | 40     QFrame(parent), | 
| Chris@127 | 41     m_currentPane(0), | 
| Chris@127 | 42     m_splitter(new QSplitter), | 
| Chris@127 | 43     m_propertyStackStack(new QStackedWidget), | 
| Chris@127 | 44     m_viewManager(viewManager), | 
| Chris@127 | 45     m_layoutStyle(PropertyStackPerPaneLayout) | 
| Chris@127 | 46 { | 
| Chris@127 | 47     QHBoxLayout *layout = new QHBoxLayout; | 
| Chris@127 | 48     layout->setMargin(0); | 
| Chris@127 | 49     layout->setSpacing(0); | 
| Chris@127 | 50 | 
| Chris@127 | 51     m_splitter->setOrientation(Qt::Vertical); | 
| Chris@127 | 52     m_splitter->setOpaqueResize(false); | 
| Chris@127 | 53 | 
| Chris@127 | 54     layout->addWidget(m_splitter); | 
| Chris@127 | 55     layout->setStretchFactor(m_splitter, 1); | 
| Chris@127 | 56     layout->addWidget(m_propertyStackStack); | 
| Chris@127 | 57     m_propertyStackStack->hide(); | 
| Chris@127 | 58 | 
| Chris@127 | 59     setLayout(layout); | 
| Chris@127 | 60 } | 
| Chris@127 | 61 | 
| Chris@127 | 62 Pane * | 
| Chris@127 | 63 PaneStack::addPane(bool suppressPropertyBox) | 
| Chris@127 | 64 { | 
| Chris@127 | 65     QFrame *frame = new QFrame; | 
| Chris@495 | 66 | 
| Chris@495 | 67     QGridLayout *layout = new QGridLayout; | 
| Chris@127 | 68     layout->setMargin(0); | 
| Chris@127 | 69     layout->setSpacing(2); | 
| Chris@127 | 70 | 
| Chris@323 | 71     QPushButton *xButton = new QPushButton(frame); | 
| Chris@323 | 72     xButton->setIcon(IconLoader().load("cross")); | 
| Chris@323 | 73     xButton->setFixedSize(QSize(16, 16)); | 
| Chris@497 | 74     xButton->setFlat(true); | 
| Chris@495 | 75     layout->addWidget(xButton, 0, 0); | 
| Chris@323 | 76     connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked())); | 
| Chris@323 | 77 | 
| Chris@500 | 78     ClickableLabel *currentIndicator = new ClickableLabel(frame); | 
| Chris@500 | 79     connect(currentIndicator, SIGNAL(clicked()), this, SLOT(indicatorClicked())); | 
| Chris@495 | 80     layout->addWidget(currentIndicator, 1, 0); | 
| Chris@495 | 81     layout->setRowStretch(1, 20); | 
| Chris@497 | 82     currentIndicator->setMinimumWidth(8); | 
| Chris@127 | 83     currentIndicator->setScaledContents(true); | 
| Chris@127 | 84 | 
| Chris@516 | 85     long initialCentreFrame = -1; | 
| Chris@516 | 86     for (int i = 0; i < m_panes.size(); ++i) { | 
| Chris@516 | 87         long f = m_panes[i].pane->getCentreFrame(); | 
| Chris@516 | 88         initialCentreFrame = f; | 
| Chris@516 | 89         break; | 
| Chris@516 | 90     } | 
| Chris@516 | 91 | 
| Chris@127 | 92     Pane *pane = new Pane(frame); | 
| Chris@516 | 93     if (initialCentreFrame >= 0) { | 
| Chris@516 | 94         pane->setViewManager(m_viewManager, initialCentreFrame); | 
| Chris@516 | 95     } else { | 
| Chris@516 | 96         pane->setViewManager(m_viewManager); | 
| Chris@516 | 97     } | 
| Chris@495 | 98     layout->addWidget(pane, 0, 1, 2, 1); | 
| Chris@495 | 99     layout->setColumnStretch(1, 20); | 
| Chris@127 | 100 | 
| Chris@323 | 101     m_xButtonMap[xButton] = pane; | 
| Chris@323 | 102 | 
| Chris@127 | 103     QWidget *properties = 0; | 
| Chris@127 | 104     if (suppressPropertyBox) { | 
| Chris@127 | 105 	properties = new QFrame(); | 
| Chris@127 | 106     } else { | 
| Chris@127 | 107 	properties = new PropertyStack(frame, pane); | 
| Chris@127 | 108 	connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), | 
| Chris@127 | 109 		this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); | 
| Chris@190 | 110         connect(properties, SIGNAL(viewSelected(View  *)), | 
| Chris@190 | 111                 this, SLOT(viewSelected(View *))); | 
| Chris@189 | 112         connect(properties, SIGNAL(contextHelpChanged(const QString &)), | 
| Chris@189 | 113                 this, SIGNAL(contextHelpChanged(const QString &))); | 
| Chris@127 | 114     } | 
| Chris@127 | 115     if (m_layoutStyle == PropertyStackPerPaneLayout) { | 
| Chris@495 | 116         layout->addWidget(properties, 0, 2, 2, 1); | 
| Chris@127 | 117     } else { | 
| Chris@127 | 118         properties->setParent(m_propertyStackStack); | 
| Chris@127 | 119         m_propertyStackStack->addWidget(properties); | 
| Chris@127 | 120     } | 
| Chris@495 | 121     layout->setColumnStretch(2, 1); | 
| Chris@127 | 122 | 
| Chris@127 | 123     PaneRec rec; | 
| Chris@127 | 124     rec.pane = pane; | 
| Chris@127 | 125     rec.propertyStack = properties; | 
| Chris@127 | 126     rec.currentIndicator = currentIndicator; | 
| Chris@127 | 127     rec.frame = frame; | 
| Chris@127 | 128     rec.layout = layout; | 
| Chris@127 | 129     m_panes.push_back(rec); | 
| Chris@127 | 130 | 
| Chris@127 | 131     frame->setLayout(layout); | 
| Chris@127 | 132     m_splitter->addWidget(frame); | 
| Chris@127 | 133 | 
| Chris@127 | 134     connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), | 
| Chris@127 | 135 	    this, SLOT(propertyContainerAdded(PropertyContainer *))); | 
| Chris@127 | 136     connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), | 
| Chris@127 | 137 	    this, SLOT(propertyContainerRemoved(PropertyContainer *))); | 
| Chris@127 | 138     connect(pane, SIGNAL(paneInteractedWith()), | 
| Chris@127 | 139 	    this, SLOT(paneInteractedWith())); | 
| Chris@127 | 140     connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), | 
| Chris@127 | 141             this, SLOT(rightButtonMenuRequested(QPoint))); | 
| Chris@312 | 142     connect(pane, SIGNAL(dropAccepted(QStringList)), | 
| Chris@312 | 143             this, SLOT(paneDropAccepted(QStringList))); | 
| Chris@312 | 144     connect(pane, SIGNAL(dropAccepted(QString)), | 
| Chris@312 | 145             this, SLOT(paneDropAccepted(QString))); | 
| Chris@127 | 146 | 
| Chris@271 | 147     emit paneAdded(pane); | 
| Chris@271 | 148     emit paneAdded(); | 
| Chris@271 | 149 | 
| Chris@127 | 150     if (!m_currentPane) { | 
| Chris@127 | 151 	setCurrentPane(pane); | 
| Chris@127 | 152     } | 
| Chris@127 | 153 | 
| Chris@127 | 154     return pane; | 
| Chris@127 | 155 } | 
| Chris@127 | 156 | 
| Chris@127 | 157 void | 
| Chris@235 | 158 PaneStack::setPropertyStackMinWidth(int mw) | 
| Chris@235 | 159 { | 
| Chris@235 | 160     for (std::vector<PaneRec>::iterator i = m_panes.begin(); | 
| Chris@235 | 161          i != m_panes.end(); ++i) { | 
| Chris@235 | 162         i->propertyStack->setMinimumWidth(mw); | 
| Chris@235 | 163     } | 
| Chris@235 | 164     m_propertyStackMinWidth = mw; | 
| Chris@235 | 165 } | 
| Chris@235 | 166 | 
| Chris@235 | 167 void | 
| Chris@127 | 168 PaneStack::setLayoutStyle(LayoutStyle style) | 
| Chris@127 | 169 { | 
| Chris@127 | 170     if (style == m_layoutStyle) return; | 
| Chris@127 | 171     m_layoutStyle = style; | 
| Chris@127 | 172 | 
| Chris@127 | 173     std::vector<PaneRec>::iterator i; | 
| Chris@127 | 174 | 
| Chris@127 | 175     switch (style) { | 
| Chris@127 | 176 | 
| Chris@179 | 177     case NoPropertyStacks: | 
| Chris@127 | 178     case SinglePropertyStackLayout: | 
| Chris@127 | 179 | 
| Chris@127 | 180         for (i = m_panes.begin(); i != m_panes.end(); ++i) { | 
| Chris@127 | 181             i->layout->removeWidget(i->propertyStack); | 
| Chris@127 | 182             i->propertyStack->setParent(m_propertyStackStack); | 
| Chris@127 | 183             m_propertyStackStack->addWidget(i->propertyStack); | 
| Chris@127 | 184         } | 
| Chris@179 | 185         m_propertyStackStack->setVisible(style != NoPropertyStacks); | 
| Chris@127 | 186         break; | 
| Chris@127 | 187 | 
| Chris@127 | 188     case PropertyStackPerPaneLayout: | 
| Chris@127 | 189 | 
| Chris@127 | 190         for (i = m_panes.begin(); i != m_panes.end(); ++i) { | 
| Chris@127 | 191             m_propertyStackStack->removeWidget(i->propertyStack); | 
| Chris@127 | 192             i->propertyStack->setParent(i->frame); | 
| Chris@495 | 193             i->layout->addWidget(i->propertyStack, 0, 2, 2, 1); | 
| Chris@127 | 194             i->propertyStack->show(); | 
| Chris@127 | 195         } | 
| Chris@127 | 196         m_propertyStackStack->hide(); | 
| Chris@127 | 197         break; | 
| Chris@127 | 198     } | 
| Chris@127 | 199 } | 
| Chris@127 | 200 | 
| Chris@127 | 201 Pane * | 
| Chris@127 | 202 PaneStack::getPane(int n) | 
| Chris@127 | 203 { | 
| Chris@277 | 204     if (n < m_panes.size()) { | 
| Chris@277 | 205         return m_panes[n].pane; | 
| Chris@277 | 206     } else { | 
| Chris@277 | 207         return 0; | 
| Chris@277 | 208     } | 
| Chris@277 | 209 } | 
| Chris@277 | 210 | 
| Chris@277 | 211 int | 
| Chris@277 | 212 PaneStack::getPaneIndex(Pane *pane) | 
| Chris@277 | 213 { | 
| Chris@277 | 214     for (int i = 0; i < getPaneCount(); ++i) { | 
| Chris@277 | 215         if (pane == getPane(i)) { | 
| Chris@277 | 216             return i; | 
| Chris@277 | 217         } | 
| Chris@277 | 218     } | 
| Chris@277 | 219     return -1; | 
| Chris@127 | 220 } | 
| Chris@127 | 221 | 
| Chris@127 | 222 Pane * | 
| Chris@127 | 223 PaneStack::getHiddenPane(int n) | 
| Chris@127 | 224 { | 
| Chris@127 | 225     return m_hiddenPanes[n].pane; | 
| Chris@127 | 226 } | 
| Chris@127 | 227 | 
| Chris@127 | 228 void | 
| Chris@127 | 229 PaneStack::deletePane(Pane *pane) | 
| Chris@127 | 230 { | 
| Chris@127 | 231     std::vector<PaneRec>::iterator i; | 
| Chris@127 | 232     bool found = false; | 
| Chris@127 | 233 | 
| Chris@127 | 234     for (i = m_panes.begin(); i != m_panes.end(); ++i) { | 
| Chris@127 | 235 	if (i->pane == pane) { | 
| Chris@127 | 236 	    m_panes.erase(i); | 
| Chris@127 | 237 	    found = true; | 
| Chris@127 | 238 	    break; | 
| Chris@127 | 239 	} | 
| Chris@127 | 240     } | 
| Chris@127 | 241 | 
| Chris@127 | 242     if (!found) { | 
| Chris@127 | 243 | 
| Chris@127 | 244 	for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { | 
| Chris@127 | 245 	    if (i->pane == pane) { | 
| Chris@127 | 246 		m_hiddenPanes.erase(i); | 
| Chris@127 | 247 		found = true; | 
| Chris@127 | 248 		break; | 
| Chris@127 | 249 	    } | 
| Chris@127 | 250 	} | 
| Chris@127 | 251 | 
| Chris@127 | 252 	if (!found) { | 
| Chris@127 | 253 	    std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl; | 
| Chris@127 | 254 	    return; | 
| Chris@127 | 255 	} | 
| Chris@127 | 256     } | 
| Chris@127 | 257 | 
| Chris@271 | 258     emit paneAboutToBeDeleted(pane); | 
| Chris@271 | 259 | 
| Chris@323 | 260     for (std::map<QWidget *, Pane *>::iterator i = m_xButtonMap.begin(); | 
| Chris@323 | 261          i != m_xButtonMap.end(); ++i) { | 
| Chris@323 | 262 | 
| Chris@323 | 263         if (i->second == pane) { | 
| Chris@323 | 264             m_xButtonMap.erase(i); | 
| Chris@323 | 265             break; | 
| Chris@323 | 266         } | 
| Chris@323 | 267     } | 
| Chris@323 | 268 | 
| Chris@127 | 269     delete pane->parent(); | 
| Chris@127 | 270 | 
| Chris@127 | 271     if (m_currentPane == pane) { | 
| Chris@127 | 272 	if (m_panes.size() > 0) { | 
| Chris@127 | 273             setCurrentPane(m_panes[0].pane); | 
| Chris@127 | 274 	} else { | 
| Chris@127 | 275 	    setCurrentPane(0); | 
| Chris@127 | 276 	} | 
| Chris@127 | 277     } | 
| Chris@271 | 278 | 
| Chris@271 | 279     emit paneDeleted(); | 
| Chris@127 | 280 } | 
| Chris@127 | 281 | 
| Chris@127 | 282 int | 
| Chris@127 | 283 PaneStack::getPaneCount() const | 
| Chris@127 | 284 { | 
| Chris@127 | 285     return m_panes.size(); | 
| Chris@127 | 286 } | 
| Chris@127 | 287 | 
| Chris@127 | 288 int | 
| Chris@127 | 289 PaneStack::getHiddenPaneCount() const | 
| Chris@127 | 290 { | 
| Chris@127 | 291     return m_hiddenPanes.size(); | 
| Chris@127 | 292 } | 
| Chris@127 | 293 | 
| Chris@127 | 294 void | 
| Chris@127 | 295 PaneStack::hidePane(Pane *pane) | 
| Chris@127 | 296 { | 
| Chris@127 | 297     std::vector<PaneRec>::iterator i = m_panes.begin(); | 
| Chris@127 | 298 | 
| Chris@127 | 299     while (i != m_panes.end()) { | 
| Chris@127 | 300 	if (i->pane == pane) { | 
| Chris@127 | 301 | 
| Chris@127 | 302 	    m_hiddenPanes.push_back(*i); | 
| Chris@127 | 303 	    m_panes.erase(i); | 
| Chris@127 | 304 | 
| Chris@127 | 305 	    QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); | 
| Chris@127 | 306 	    if (pw) pw->hide(); | 
| Chris@127 | 307 | 
| Chris@127 | 308 	    if (m_currentPane == pane) { | 
| Chris@127 | 309 		if (m_panes.size() > 0) { | 
| Chris@127 | 310 		    setCurrentPane(m_panes[0].pane); | 
| Chris@127 | 311 		} else { | 
| Chris@127 | 312 		    setCurrentPane(0); | 
| Chris@127 | 313 		} | 
| Chris@127 | 314 	    } | 
| Chris@127 | 315 | 
| Chris@127 | 316 	    return; | 
| Chris@127 | 317 	} | 
| Chris@127 | 318 	++i; | 
| Chris@127 | 319     } | 
| Chris@127 | 320 | 
| Chris@127 | 321     std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl; | 
| Chris@319 | 322     emit paneHidden(pane); | 
| Chris@319 | 323     emit paneHidden(); | 
| Chris@127 | 324 } | 
| Chris@127 | 325 | 
| Chris@127 | 326 void | 
| Chris@127 | 327 PaneStack::showPane(Pane *pane) | 
| Chris@127 | 328 { | 
| Chris@127 | 329     std::vector<PaneRec>::iterator i = m_hiddenPanes.begin(); | 
| Chris@127 | 330 | 
| Chris@127 | 331     while (i != m_hiddenPanes.end()) { | 
| Chris@127 | 332 	if (i->pane == pane) { | 
| Chris@127 | 333 	    m_panes.push_back(*i); | 
| Chris@127 | 334 	    m_hiddenPanes.erase(i); | 
| Chris@127 | 335 	    QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); | 
| Chris@127 | 336 	    if (pw) pw->show(); | 
| Chris@127 | 337 | 
| Chris@127 | 338 	    //!!! update current pane | 
| Chris@127 | 339 | 
| Chris@127 | 340 	    return; | 
| Chris@127 | 341 	} | 
| Chris@127 | 342 	++i; | 
| Chris@127 | 343     } | 
| Chris@127 | 344 | 
| Chris@127 | 345     std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl; | 
| Chris@127 | 346 } | 
| Chris@127 | 347 | 
| Chris@127 | 348 void | 
| Chris@127 | 349 PaneStack::setCurrentPane(Pane *pane) // may be null | 
| Chris@127 | 350 { | 
| Chris@127 | 351     if (m_currentPane == pane) return; | 
| Chris@127 | 352 | 
| Chris@127 | 353     std::vector<PaneRec>::iterator i = m_panes.begin(); | 
| Chris@127 | 354 | 
| Chris@127 | 355     // We used to do this by setting the foreground and background | 
| Chris@127 | 356     // role, but it seems the background role is ignored and the | 
| Chris@127 | 357     // background drawn transparent in Qt 4.1 -- I can't quite see why | 
| Chris@127 | 358 | 
| Chris@127 | 359     QPixmap selectedMap(1, 1); | 
| Chris@127 | 360     selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); | 
| Chris@127 | 361 | 
| Chris@127 | 362     QPixmap unselectedMap(1, 1); | 
| Chris@127 | 363     unselectedMap.fill(QApplication::palette().color(QPalette::Background)); | 
| Chris@127 | 364 | 
| Chris@127 | 365     bool found = false; | 
| Chris@127 | 366 | 
| Chris@127 | 367     while (i != m_panes.end()) { | 
| Chris@127 | 368 	if (i->pane == pane) { | 
| Chris@127 | 369 	    i->currentIndicator->setPixmap(selectedMap); | 
| Chris@179 | 370             if (m_layoutStyle != PropertyStackPerPaneLayout) { | 
| Chris@127 | 371                 m_propertyStackStack->setCurrentWidget(i->propertyStack); | 
| Chris@127 | 372             } | 
| Chris@127 | 373 	    found = true; | 
| Chris@127 | 374 	} else { | 
| Chris@127 | 375 	    i->currentIndicator->setPixmap(unselectedMap); | 
| Chris@127 | 376 	} | 
| Chris@127 | 377 	++i; | 
| Chris@127 | 378     } | 
| Chris@127 | 379 | 
| Chris@127 | 380     if (found || pane == 0) { | 
| Chris@127 | 381 	m_currentPane = pane; | 
| Chris@127 | 382 	emit currentPaneChanged(m_currentPane); | 
| Chris@127 | 383     } else { | 
| Chris@127 | 384 	std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl; | 
| Chris@127 | 385     } | 
| Chris@127 | 386 } | 
| Chris@127 | 387 | 
| Chris@127 | 388 void | 
| Chris@127 | 389 PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null | 
| Chris@127 | 390 { | 
| Chris@127 | 391     setCurrentPane(pane); | 
| Chris@127 | 392 | 
| Chris@127 | 393     if (m_currentPane) { | 
| Chris@127 | 394 | 
| Chris@127 | 395 	std::vector<PaneRec>::iterator i = m_panes.begin(); | 
| Chris@127 | 396 | 
| Chris@127 | 397 	while (i != m_panes.end()) { | 
| Chris@127 | 398 | 
| Chris@127 | 399 	    if (i->pane == pane) { | 
| Chris@127 | 400 		PropertyStack *stack = dynamic_cast<PropertyStack *> | 
| Chris@127 | 401 		    (i->propertyStack); | 
| Chris@127 | 402 		if (stack) { | 
| Chris@127 | 403 		    if (stack->containsContainer(layer)) { | 
| Chris@127 | 404 			stack->setCurrentIndex(stack->getContainerIndex(layer)); | 
| Chris@127 | 405 			emit currentLayerChanged(pane, layer); | 
| Chris@127 | 406 		    } else { | 
| Chris@127 | 407 			stack->setCurrentIndex | 
| Chris@127 | 408 			    (stack->getContainerIndex | 
| Chris@127 | 409 			     (pane->getPropertyContainer(0))); | 
| Chris@127 | 410 			emit currentLayerChanged(pane, 0); | 
| Chris@127 | 411 		    } | 
| Chris@127 | 412 		} | 
| Chris@127 | 413 		break; | 
| Chris@127 | 414 	    } | 
| Chris@127 | 415 	    ++i; | 
| Chris@127 | 416 	} | 
| Chris@127 | 417     } | 
| Chris@127 | 418 } | 
| Chris@127 | 419 | 
| Chris@127 | 420 Pane * | 
| Chris@127 | 421 PaneStack::getCurrentPane() | 
| Chris@127 | 422 { | 
| Chris@127 | 423     return m_currentPane; | 
| Chris@127 | 424 } | 
| Chris@127 | 425 | 
| Chris@127 | 426 void | 
| Chris@127 | 427 PaneStack::propertyContainerAdded(PropertyContainer *) | 
| Chris@127 | 428 { | 
| Chris@127 | 429     sizePropertyStacks(); | 
| Chris@127 | 430 } | 
| Chris@127 | 431 | 
| Chris@127 | 432 void | 
| Chris@127 | 433 PaneStack::propertyContainerRemoved(PropertyContainer *) | 
| Chris@127 | 434 { | 
| Chris@127 | 435     sizePropertyStacks(); | 
| Chris@127 | 436 } | 
| Chris@127 | 437 | 
| Chris@127 | 438 void | 
| Chris@127 | 439 PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc) | 
| Chris@127 | 440 { | 
| Chris@127 | 441     std::vector<PaneRec>::iterator i = m_panes.begin(); | 
| Chris@127 | 442 | 
| Chris@127 | 443     while (i != m_panes.end()) { | 
| Chris@127 | 444 	PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack); | 
| Chris@127 | 445 	if (stack && | 
| Chris@127 | 446 	    stack->getClient() == client && | 
| Chris@127 | 447 	    stack->containsContainer(pc)) { | 
| Chris@127 | 448 	    setCurrentPane(i->pane); | 
| Chris@127 | 449 	    break; | 
| Chris@127 | 450 	} | 
| Chris@127 | 451 	++i; | 
| Chris@127 | 452     } | 
| Chris@127 | 453 | 
| Chris@127 | 454     Layer *layer = dynamic_cast<Layer *>(pc); | 
| Chris@127 | 455     if (layer) emit currentLayerChanged(m_currentPane, layer); | 
| Chris@127 | 456     else emit currentLayerChanged(m_currentPane, 0); | 
| Chris@127 | 457 } | 
| Chris@127 | 458 | 
| Chris@127 | 459 void | 
| Chris@190 | 460 PaneStack::viewSelected(View *v) | 
| Chris@190 | 461 { | 
| Chris@190 | 462     Pane *p = dynamic_cast<Pane *>(v); | 
| Chris@190 | 463     if (p) setCurrentPane(p); | 
| Chris@190 | 464 } | 
| Chris@190 | 465 | 
| Chris@190 | 466 void | 
| Chris@127 | 467 PaneStack::paneInteractedWith() | 
| Chris@127 | 468 { | 
| Chris@127 | 469     Pane *pane = dynamic_cast<Pane *>(sender()); | 
| Chris@127 | 470     if (!pane) return; | 
| Chris@127 | 471     setCurrentPane(pane); | 
| Chris@127 | 472 } | 
| Chris@127 | 473 | 
| Chris@127 | 474 void | 
| Chris@127 | 475 PaneStack::rightButtonMenuRequested(QPoint position) | 
| Chris@127 | 476 { | 
| Chris@127 | 477     Pane *pane = dynamic_cast<Pane *>(sender()); | 
| Chris@127 | 478     if (!pane) return; | 
| Chris@127 | 479     emit rightButtonMenuRequested(pane, position); | 
| Chris@127 | 480 } | 
| Chris@127 | 481 | 
| Chris@127 | 482 void | 
| Chris@127 | 483 PaneStack::sizePropertyStacks() | 
| Chris@127 | 484 { | 
| Chris@127 | 485     int maxMinWidth = 0; | 
| Chris@127 | 486 | 
| Chris@235 | 487     if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth; | 
| Chris@235 | 488 | 
| Chris@127 | 489     for (size_t i = 0; i < m_panes.size(); ++i) { | 
| Chris@127 | 490 	if (!m_panes[i].propertyStack) continue; | 
| Chris@247 | 491 #ifdef DEBUG_PANE_STACK | 
| Chris@243 | 492 	std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " | 
| Chris@243 | 493 		  << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint " | 
| Chris@243 | 494                   << m_panes[i].propertyStack->sizeHint().width() << ", current " | 
| Chris@243 | 495 		  << m_panes[i].propertyStack->width() << std::endl; | 
| Chris@247 | 496 #endif | 
| Chris@127 | 497 | 
| Chris@246 | 498 	if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) { | 
| Chris@246 | 499 	    maxMinWidth = m_panes[i].propertyStack->sizeHint().width(); | 
| Chris@127 | 500 	} | 
| Chris@127 | 501     } | 
| Chris@127 | 502 | 
| Chris@247 | 503 #ifdef DEBUG_PANE_STACK | 
| Chris@247 | 504     std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; | 
| Chris@247 | 505 #endif | 
| Chris@127 | 506 | 
| Chris@127 | 507     int setWidth = maxMinWidth; | 
| Chris@127 | 508 | 
| Chris@127 | 509     m_propertyStackStack->setMaximumWidth(setWidth + 10); | 
| Chris@127 | 510 | 
| Chris@127 | 511     for (size_t i = 0; i < m_panes.size(); ++i) { | 
| Chris@127 | 512 	if (!m_panes[i].propertyStack) continue; | 
| Chris@127 | 513 	m_panes[i].propertyStack->setMinimumWidth(setWidth); | 
| Chris@127 | 514     } | 
| Chris@180 | 515 | 
| Chris@363 | 516     emit propertyStacksResized(setWidth); | 
| Chris@180 | 517     emit propertyStacksResized(); | 
| Chris@127 | 518 } | 
| Chris@127 | 519 | 
| Chris@312 | 520 void | 
| Chris@312 | 521 PaneStack::paneDropAccepted(QStringList uriList) | 
| Chris@312 | 522 { | 
| Chris@312 | 523     Pane *pane = dynamic_cast<Pane *>(sender()); | 
| Chris@312 | 524     emit dropAccepted(pane, uriList); | 
| Chris@312 | 525 } | 
| Chris@312 | 526 | 
| Chris@312 | 527 void | 
| Chris@312 | 528 PaneStack::paneDropAccepted(QString text) | 
| Chris@312 | 529 { | 
| Chris@312 | 530     Pane *pane = dynamic_cast<Pane *>(sender()); | 
| Chris@312 | 531     emit dropAccepted(pane, text); | 
| Chris@312 | 532 } | 
| Chris@127 | 533 | 
| Chris@320 | 534 void | 
| Chris@323 | 535 PaneStack::paneDeleteButtonClicked() | 
| Chris@323 | 536 { | 
| Chris@323 | 537     QObject *s = sender(); | 
| Chris@323 | 538     QWidget *w = dynamic_cast<QWidget *>(s); | 
| Chris@323 | 539     if (w) { | 
| Chris@323 | 540         if (m_xButtonMap.find(w) != m_xButtonMap.end()) { | 
| Chris@323 | 541             Pane *p = m_xButtonMap[w]; | 
| Chris@323 | 542             emit paneDeleteButtonClicked(p); | 
| Chris@323 | 543         } | 
| Chris@323 | 544     } | 
| Chris@323 | 545 } | 
| Chris@323 | 546 | 
| Chris@323 | 547 void | 
| Chris@500 | 548 PaneStack::indicatorClicked() | 
| Chris@500 | 549 { | 
| Chris@500 | 550     QObject *s = sender(); | 
| Chris@500 | 551 | 
| Chris@500 | 552     for (size_t i = 0; i < m_panes.size(); ++i) { | 
| Chris@500 | 553 	if (m_panes[i].currentIndicator == s) { | 
| Chris@500 | 554             setCurrentPane(m_panes[i].pane); | 
| Chris@500 | 555             return; | 
| Chris@500 | 556         } | 
| Chris@500 | 557     } | 
| Chris@500 | 558 } | 
| Chris@500 | 559 | 
| Chris@500 | 560 void | 
| Chris@320 | 561 PaneStack::sizePanesEqually() | 
| Chris@320 | 562 { | 
| Chris@320 | 563     QList<int> sizes = m_splitter->sizes(); | 
| Chris@320 | 564     if (sizes.empty()) return; | 
| Chris@320 | 565 | 
| Chris@320 | 566     int count = sizes.size(); | 
| Chris@320 | 567 | 
| Chris@320 | 568     int total = 0; | 
| Chris@320 | 569     for (int i = 0; i < count; ++i) { | 
| Chris@320 | 570         total += sizes[i]; | 
| Chris@320 | 571     } | 
| Chris@320 | 572 | 
| Chris@320 | 573     if (total == 0) return; | 
| Chris@320 | 574 | 
| Chris@320 | 575     sizes.clear(); | 
| Chris@320 | 576 | 
| Chris@320 | 577     int each = total / count; | 
| Chris@320 | 578     int remaining = total; | 
| Chris@320 | 579 | 
| Chris@320 | 580     for (int i = 0; i < count; ++i) { | 
| Chris@320 | 581         if (i == count - 1) { | 
| Chris@320 | 582             sizes.push_back(remaining); | 
| Chris@320 | 583         } else { | 
| Chris@320 | 584             sizes.push_back(each); | 
| Chris@320 | 585             remaining -= each; | 
| Chris@320 | 586         } | 
| Chris@320 | 587     } | 
| Chris@320 | 588 | 
| Chris@320 | 589 /* | 
| Chris@320 | 590     std::cerr << "sizes: "; | 
| Chris@320 | 591     for (int i = 0; i < sizes.size(); ++i) { | 
| Chris@320 | 592         std::cerr << sizes[i] << " "; | 
| Chris@320 | 593     } | 
| Chris@320 | 594     std::cerr << std::endl; | 
| Chris@320 | 595 */ | 
| Chris@320 | 596 | 
| Chris@320 | 597     m_splitter->setSizes(sizes); | 
| Chris@320 | 598 } | 
| Chris@320 | 599 | 
| Chris@320 | 600 |