00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "PaneStack.h"
00018
00019 #include "Pane.h"
00020 #include "widgets/PropertyStack.h"
00021 #include "widgets/IconLoader.h"
00022 #include "layer/Layer.h"
00023 #include "ViewManager.h"
00024
00025 #include <QApplication>
00026 #include <QHBoxLayout>
00027 #include <QVBoxLayout>
00028 #include <QPainter>
00029 #include <QPalette>
00030 #include <QLabel>
00031 #include <QPushButton>
00032 #include <QSplitter>
00033 #include <QStackedWidget>
00034
00035 #include <iostream>
00036
00037
00038
00039 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) :
00040 QFrame(parent),
00041 m_currentPane(0),
00042 m_splitter(new QSplitter),
00043 m_propertyStackStack(new QStackedWidget),
00044 m_viewManager(viewManager),
00045 m_layoutStyle(PropertyStackPerPaneLayout)
00046 {
00047 QHBoxLayout *layout = new QHBoxLayout;
00048 layout->setMargin(0);
00049 layout->setSpacing(0);
00050
00051 m_splitter->setOrientation(Qt::Vertical);
00052 m_splitter->setOpaqueResize(false);
00053
00054 layout->addWidget(m_splitter);
00055 layout->setStretchFactor(m_splitter, 1);
00056 layout->addWidget(m_propertyStackStack);
00057 m_propertyStackStack->hide();
00058
00059 setLayout(layout);
00060 }
00061
00062 Pane *
00063 PaneStack::addPane(bool suppressPropertyBox)
00064 {
00065 QFrame *frame = new QFrame;
00066 QHBoxLayout *layout = new QHBoxLayout;
00067 layout->setMargin(0);
00068 layout->setSpacing(2);
00069
00070 QVBoxLayout *vlayout = new QVBoxLayout;
00071 layout->addLayout(vlayout);
00072 layout->setStretchFactor(vlayout, 0);
00073
00074 QPushButton *xButton = new QPushButton(frame);
00075 xButton->setIcon(IconLoader().load("cross"));
00076 xButton->setFixedSize(QSize(16, 16));
00077 vlayout->addWidget(xButton);
00078 vlayout->setStretchFactor(xButton, 0);
00079 connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked()));
00080
00081 QLabel *currentIndicator = new QLabel(frame);
00082
00083 vlayout->addWidget(currentIndicator);
00084 vlayout->setStretchFactor(currentIndicator, 10);
00085 currentIndicator->setScaledContents(true);
00086
00087 Pane *pane = new Pane(frame);
00088 pane->setViewManager(m_viewManager);
00089 layout->addWidget(pane);
00090 layout->setStretchFactor(pane, 10);
00091
00092 m_xButtonMap[xButton] = pane;
00093
00094 QWidget *properties = 0;
00095 if (suppressPropertyBox) {
00096 properties = new QFrame();
00097 } else {
00098 properties = new PropertyStack(frame, pane);
00099 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
00100 this, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
00101 connect(properties, SIGNAL(viewSelected(View *)),
00102 this, SLOT(viewSelected(View *)));
00103 connect(properties, SIGNAL(contextHelpChanged(const QString &)),
00104 this, SIGNAL(contextHelpChanged(const QString &)));
00105 }
00106 if (m_layoutStyle == PropertyStackPerPaneLayout) {
00107 layout->addWidget(properties);
00108 } else {
00109 properties->setParent(m_propertyStackStack);
00110 m_propertyStackStack->addWidget(properties);
00111 }
00112 layout->setStretchFactor(properties, 1);
00113
00114 PaneRec rec;
00115 rec.pane = pane;
00116 rec.propertyStack = properties;
00117 rec.currentIndicator = currentIndicator;
00118 rec.frame = frame;
00119 rec.layout = layout;
00120 m_panes.push_back(rec);
00121
00122 frame->setLayout(layout);
00123 m_splitter->addWidget(frame);
00124
00125 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
00126 this, SLOT(propertyContainerAdded(PropertyContainer *)));
00127 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
00128 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
00129 connect(pane, SIGNAL(paneInteractedWith()),
00130 this, SLOT(paneInteractedWith()));
00131 connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)),
00132 this, SLOT(rightButtonMenuRequested(QPoint)));
00133 connect(pane, SIGNAL(dropAccepted(QStringList)),
00134 this, SLOT(paneDropAccepted(QStringList)));
00135 connect(pane, SIGNAL(dropAccepted(QString)),
00136 this, SLOT(paneDropAccepted(QString)));
00137
00138 emit paneAdded(pane);
00139 emit paneAdded();
00140
00141 if (!m_currentPane) {
00142 setCurrentPane(pane);
00143 }
00144
00145 return pane;
00146 }
00147
00148 void
00149 PaneStack::setPropertyStackMinWidth(int mw)
00150 {
00151 for (std::vector<PaneRec>::iterator i = m_panes.begin();
00152 i != m_panes.end(); ++i) {
00153 i->propertyStack->setMinimumWidth(mw);
00154 }
00155 m_propertyStackMinWidth = mw;
00156 }
00157
00158 void
00159 PaneStack::setLayoutStyle(LayoutStyle style)
00160 {
00161 if (style == m_layoutStyle) return;
00162 m_layoutStyle = style;
00163
00164 std::vector<PaneRec>::iterator i;
00165
00166 switch (style) {
00167
00168 case NoPropertyStacks:
00169 case SinglePropertyStackLayout:
00170
00171 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
00172 i->layout->removeWidget(i->propertyStack);
00173 i->propertyStack->setParent(m_propertyStackStack);
00174 m_propertyStackStack->addWidget(i->propertyStack);
00175 }
00176 m_propertyStackStack->setVisible(style != NoPropertyStacks);
00177 break;
00178
00179 case PropertyStackPerPaneLayout:
00180
00181 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
00182 m_propertyStackStack->removeWidget(i->propertyStack);
00183 i->propertyStack->setParent(i->frame);
00184 i->layout->addWidget(i->propertyStack);
00185 i->propertyStack->show();
00186 }
00187 m_propertyStackStack->hide();
00188 break;
00189 }
00190 }
00191
00192 Pane *
00193 PaneStack::getPane(int n)
00194 {
00195 if (n < m_panes.size()) {
00196 return m_panes[n].pane;
00197 } else {
00198 return 0;
00199 }
00200 }
00201
00202 int
00203 PaneStack::getPaneIndex(Pane *pane)
00204 {
00205 for (int i = 0; i < getPaneCount(); ++i) {
00206 if (pane == getPane(i)) {
00207 return i;
00208 }
00209 }
00210 return -1;
00211 }
00212
00213 Pane *
00214 PaneStack::getHiddenPane(int n)
00215 {
00216 return m_hiddenPanes[n].pane;
00217 }
00218
00219 void
00220 PaneStack::deletePane(Pane *pane)
00221 {
00222 std::vector<PaneRec>::iterator i;
00223 bool found = false;
00224
00225 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
00226 if (i->pane == pane) {
00227 m_panes.erase(i);
00228 found = true;
00229 break;
00230 }
00231 }
00232
00233 if (!found) {
00234
00235 for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) {
00236 if (i->pane == pane) {
00237 m_hiddenPanes.erase(i);
00238 found = true;
00239 break;
00240 }
00241 }
00242
00243 if (!found) {
00244 std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl;
00245 return;
00246 }
00247 }
00248
00249 emit paneAboutToBeDeleted(pane);
00250
00251 for (std::map<QWidget *, Pane *>::iterator i = m_xButtonMap.begin();
00252 i != m_xButtonMap.end(); ++i) {
00253
00254 if (i->second == pane) {
00255 m_xButtonMap.erase(i);
00256 break;
00257 }
00258 }
00259
00260 delete pane->parent();
00261
00262 if (m_currentPane == pane) {
00263 if (m_panes.size() > 0) {
00264 setCurrentPane(m_panes[0].pane);
00265 } else {
00266 setCurrentPane(0);
00267 }
00268 }
00269
00270 emit paneDeleted();
00271 }
00272
00273 int
00274 PaneStack::getPaneCount() const
00275 {
00276 return m_panes.size();
00277 }
00278
00279 int
00280 PaneStack::getHiddenPaneCount() const
00281 {
00282 return m_hiddenPanes.size();
00283 }
00284
00285 void
00286 PaneStack::hidePane(Pane *pane)
00287 {
00288 std::vector<PaneRec>::iterator i = m_panes.begin();
00289
00290 while (i != m_panes.end()) {
00291 if (i->pane == pane) {
00292
00293 m_hiddenPanes.push_back(*i);
00294 m_panes.erase(i);
00295
00296 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
00297 if (pw) pw->hide();
00298
00299 if (m_currentPane == pane) {
00300 if (m_panes.size() > 0) {
00301 setCurrentPane(m_panes[0].pane);
00302 } else {
00303 setCurrentPane(0);
00304 }
00305 }
00306
00307 return;
00308 }
00309 ++i;
00310 }
00311
00312 std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl;
00313 emit paneHidden(pane);
00314 emit paneHidden();
00315 }
00316
00317 void
00318 PaneStack::showPane(Pane *pane)
00319 {
00320 std::vector<PaneRec>::iterator i = m_hiddenPanes.begin();
00321
00322 while (i != m_hiddenPanes.end()) {
00323 if (i->pane == pane) {
00324 m_panes.push_back(*i);
00325 m_hiddenPanes.erase(i);
00326 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
00327 if (pw) pw->show();
00328
00330
00331 return;
00332 }
00333 ++i;
00334 }
00335
00336 std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl;
00337 }
00338
00339 void
00340 PaneStack::setCurrentPane(Pane *pane)
00341 {
00342 if (m_currentPane == pane) return;
00343
00344 std::vector<PaneRec>::iterator i = m_panes.begin();
00345
00346
00347
00348
00349
00350 QPixmap selectedMap(1, 1);
00351 selectedMap.fill(QApplication::palette().color(QPalette::Foreground));
00352
00353 QPixmap unselectedMap(1, 1);
00354 unselectedMap.fill(QApplication::palette().color(QPalette::Background));
00355
00356 bool found = false;
00357
00358 while (i != m_panes.end()) {
00359 if (i->pane == pane) {
00360 i->currentIndicator->setPixmap(selectedMap);
00361 if (m_layoutStyle != PropertyStackPerPaneLayout) {
00362 m_propertyStackStack->setCurrentWidget(i->propertyStack);
00363 }
00364 found = true;
00365 } else {
00366 i->currentIndicator->setPixmap(unselectedMap);
00367 }
00368 ++i;
00369 }
00370
00371 if (found || pane == 0) {
00372 m_currentPane = pane;
00373 emit currentPaneChanged(m_currentPane);
00374 } else {
00375 std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl;
00376 }
00377 }
00378
00379 void
00380 PaneStack::setCurrentLayer(Pane *pane, Layer *layer)
00381 {
00382 setCurrentPane(pane);
00383
00384 if (m_currentPane) {
00385
00386 std::vector<PaneRec>::iterator i = m_panes.begin();
00387
00388 while (i != m_panes.end()) {
00389
00390 if (i->pane == pane) {
00391 PropertyStack *stack = dynamic_cast<PropertyStack *>
00392 (i->propertyStack);
00393 if (stack) {
00394 if (stack->containsContainer(layer)) {
00395 stack->setCurrentIndex(stack->getContainerIndex(layer));
00396 emit currentLayerChanged(pane, layer);
00397 } else {
00398 stack->setCurrentIndex
00399 (stack->getContainerIndex
00400 (pane->getPropertyContainer(0)));
00401 emit currentLayerChanged(pane, 0);
00402 }
00403 }
00404 break;
00405 }
00406 ++i;
00407 }
00408 }
00409 }
00410
00411 Pane *
00412 PaneStack::getCurrentPane()
00413 {
00414 return m_currentPane;
00415 }
00416
00417 void
00418 PaneStack::propertyContainerAdded(PropertyContainer *)
00419 {
00420 sizePropertyStacks();
00421 }
00422
00423 void
00424 PaneStack::propertyContainerRemoved(PropertyContainer *)
00425 {
00426 sizePropertyStacks();
00427 }
00428
00429 void
00430 PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc)
00431 {
00432 std::vector<PaneRec>::iterator i = m_panes.begin();
00433
00434 while (i != m_panes.end()) {
00435 PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack);
00436 if (stack &&
00437 stack->getClient() == client &&
00438 stack->containsContainer(pc)) {
00439 setCurrentPane(i->pane);
00440 break;
00441 }
00442 ++i;
00443 }
00444
00445 Layer *layer = dynamic_cast<Layer *>(pc);
00446 if (layer) emit currentLayerChanged(m_currentPane, layer);
00447 else emit currentLayerChanged(m_currentPane, 0);
00448 }
00449
00450 void
00451 PaneStack::viewSelected(View *v)
00452 {
00453 Pane *p = dynamic_cast<Pane *>(v);
00454 if (p) setCurrentPane(p);
00455 }
00456
00457 void
00458 PaneStack::paneInteractedWith()
00459 {
00460 Pane *pane = dynamic_cast<Pane *>(sender());
00461 if (!pane) return;
00462 setCurrentPane(pane);
00463 }
00464
00465 void
00466 PaneStack::rightButtonMenuRequested(QPoint position)
00467 {
00468 Pane *pane = dynamic_cast<Pane *>(sender());
00469 if (!pane) return;
00470 emit rightButtonMenuRequested(pane, position);
00471 }
00472
00473 void
00474 PaneStack::sizePropertyStacks()
00475 {
00476 int maxMinWidth = 0;
00477
00478 if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth;
00479
00480 for (size_t i = 0; i < m_panes.size(); ++i) {
00481 if (!m_panes[i].propertyStack) continue;
00482 #ifdef DEBUG_PANE_STACK
00483 std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min "
00484 << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint "
00485 << m_panes[i].propertyStack->sizeHint().width() << ", current "
00486 << m_panes[i].propertyStack->width() << std::endl;
00487 #endif
00488
00489 if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) {
00490 maxMinWidth = m_panes[i].propertyStack->sizeHint().width();
00491 }
00492 }
00493
00494 #ifdef DEBUG_PANE_STACK
00495 std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl;
00496 #endif
00497
00498 int setWidth = maxMinWidth;
00499
00500 m_propertyStackStack->setMaximumWidth(setWidth + 10);
00501
00502 for (size_t i = 0; i < m_panes.size(); ++i) {
00503 if (!m_panes[i].propertyStack) continue;
00504 m_panes[i].propertyStack->setMinimumWidth(setWidth);
00505 }
00506
00507 emit propertyStacksResized(setWidth);
00508 emit propertyStacksResized();
00509 }
00510
00511 void
00512 PaneStack::paneDropAccepted(QStringList uriList)
00513 {
00514 Pane *pane = dynamic_cast<Pane *>(sender());
00515 emit dropAccepted(pane, uriList);
00516 }
00517
00518 void
00519 PaneStack::paneDropAccepted(QString text)
00520 {
00521 Pane *pane = dynamic_cast<Pane *>(sender());
00522 emit dropAccepted(pane, text);
00523 }
00524
00525 void
00526 PaneStack::paneDeleteButtonClicked()
00527 {
00528 QObject *s = sender();
00529 QWidget *w = dynamic_cast<QWidget *>(s);
00530 if (w) {
00531 if (m_xButtonMap.find(w) != m_xButtonMap.end()) {
00532 Pane *p = m_xButtonMap[w];
00533 emit paneDeleteButtonClicked(p);
00534 }
00535 }
00536 }
00537
00538 void
00539 PaneStack::sizePanesEqually()
00540 {
00541 QList<int> sizes = m_splitter->sizes();
00542 if (sizes.empty()) return;
00543
00544 int count = sizes.size();
00545
00546 int total = 0;
00547 for (int i = 0; i < count; ++i) {
00548 total += sizes[i];
00549 }
00550
00551 if (total == 0) return;
00552
00553 sizes.clear();
00554
00555 int each = total / count;
00556 int remaining = total;
00557
00558 for (int i = 0; i < count; ++i) {
00559 if (i == count - 1) {
00560 sizes.push_back(remaining);
00561 } else {
00562 sizes.push_back(each);
00563 remaining -= each;
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 m_splitter->setSizes(sizes);
00576 }
00577
00578