void Q3DockArea::setFixedExtent(int d, Q3DockWindow *dw) { QList<Q3DockWindow *> lst; for (int i = 0; i < dockWindows.size(); ++i) { Q3DockWindow *w = dockWindows.at(i); if (w->isHidden()) continue; if (orientation() == Qt::Horizontal) { if (dw->y() != w->y()) continue; } else { if (dw->x() != w->x()) continue; } if (orientation() == Qt::Horizontal) d = qMax(d, w->minimumHeight()); else d = qMax(d, w->minimumWidth()); if (w->isResizeEnabled()) lst.append(w); } for (int i = 0; i < lst.size(); ++i) { Q3DockWindow *w = lst.at(i); if (orientation() == Qt::Horizontal) w->setFixedExtentHeight(d); else w->setFixedExtentWidth(d); } }
void tst_Q3DockWindow::parents() { // create 5 dock windows, one for each dock area // and one for the mainwindow, in the end they should // all except the one with the mainwindow as parent should // have the same dock() and parent() pointer. Q3MainWindow mw; QFrame *central = makeFrame( "Central", &mw ); mw.setCentralWidget( central ); Q3DockWindow *topDock = makeDock( "Top", mw.topDock() ); QVERIFY( topDock->area() == topDock->parent() ); Q3DockWindow *leftDock = makeDock( "Left", mw.leftDock() ); QVERIFY( leftDock->area() == leftDock->parent() ); Q3DockWindow *rightDock= makeDock( "Right", mw.rightDock() ); QVERIFY( rightDock->area() == rightDock->parent() ); Q3DockWindow *bottomDock = makeDock( "Bottom", mw.bottomDock() ); QVERIFY( bottomDock->area() == mw.bottomDock() ); Q3DockWindow *mainDock = makeDock( "MainWindow as parent", &mw ); QVERIFY( mainDock->parent() == mw.topDock() ); }
static void place_line(QList<Q3DockData> &lastLine, Qt::Orientation o, int linestrut, int fullextent, int tbstrut, int maxsize, Q3DockAreaLayout *) { Q3DockWindow *last = 0; QRect lastRect; for (QList<Q3DockData>::Iterator it = lastLine.begin(); it != lastLine.end(); ++it) { if (tbstrut != -1 && qobject_cast<Q3ToolBar*>((*it).w)) (*it).rect.setHeight(tbstrut); if (!last) { last = (*it).w; lastRect = (*it).rect; continue; } if (!last->isStretchable()) { int w = qMin(lastRect.width(), maxsize); set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o); } else { int w = qMin((*it).rect.x() - lastRect.x(), maxsize); set_geometry(last, lastRect.x(), lastRect.y(), w, last->isResizeEnabled() ? linestrut : lastRect.height(), o); } last = (*it).w; lastRect = (*it).rect; } if (!last) return; if (!last->isStretchable()) { int w = qMin(lastRect.width(), maxsize); set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o); } else { int w = qMin(fullextent - lastRect.x() - (o == Qt::Vertical ? 1 : 0), maxsize); set_geometry(last, lastRect.x(), lastRect.y(), w, last->isResizeEnabled() ? linestrut : lastRect.height(), o); } }
void Q3DockArea::invalidateFixedSizes() { for (int i = 0; i < dockWindows.size(); ++i) { Q3DockWindow *dw = dockWindows.at(i); if (orientation() == Qt::Horizontal) dw->setFixedExtentWidth(-1); else dw->setFixedExtentHeight(-1); } }
void Q3DockArea::lineUp(bool keepNewLines) { for (int i = 0; i < dockWindows.size(); ++i) { Q3DockWindow *dw = dockWindows.at(i); dw->setOffset(0); if (!keepNewLines) dw->setNewLine(false); } layout->invalidate(); layout->activate(); }
void Q3DockArea::dockWindow(Q3DockWindow *dockWindow, DockWindowData *data) { if (!data) return; dockWindow->setParent(this); dockWindow->move(0, 0); dockWindow->installEventFilter(this); dockWindow->dockArea = this; dockWindow->updateGui(); if (dockWindows.isEmpty()) { dockWindows.append(dockWindow); } else { QList<Q3DockWindow *> lineStarts = layout->lineStarts(); int index = 0; if (lineStarts.count() > data->line) index = dockWindows.indexOf(lineStarts.at(data->line)); if (index == -1) index = 0; bool firstTime = true; int offset = data->offset; for (int i = index; i < dockWindows.size(); ++i) { Q3DockWindow *dw = dockWindows.at(i); if (!firstTime && lineStarts.contains(dw)) break; if (offset < point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2) break; index++; firstTime = false; } if (index >= 0 && index < dockWindows.count() && dockWindows.at(index)->newLine() && lineOf(index) == data->line) { dockWindows.at(index)->setNewLine(false); dockWindow->setNewLine(true); } else { dockWindow->setNewLine(false); } dockWindows.insert(index, dockWindow); } dockWindow->show(); dockWindow->setFixedExtentWidth(data->fixedExtent.width()); dockWindow->setFixedExtentHeight(data->fixedExtent.height()); updateLayout(); setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum, orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum)); }
QTextStream &operator<<(QTextStream &ts, const Q3DockArea &dockArea) { QString str; QList<Q3DockWindow *> l = dockArea.dockWindowList(); for (int i = 0; i < l.size(); ++i) { Q3DockWindow *dw = l.at(i); str += QLatin1Char('[') + QString(dw->windowTitle()) + QLatin1Char(',') + QString::number((int)dw->offset()) + QLatin1Char(',') + QString::number((int)dw->newLine()) + QLatin1Char(',') + QString::number(dw->fixedExtent().width()) + QLatin1Char(',') + QString::number(dw->fixedExtent().height()) + QLatin1Char(',') + QString::number((int)!dw->isHidden()) + QLatin1Char(']'); } ts << str << endl; return ts; }
bool Q3DockArea::isLastDockWindow(Q3DockWindow *dw) { int i = dockWindows.indexOf(dw); if (i == -1 || i >= (int)dockWindows.count() - 1) return true; Q3DockWindow *w = 0; if ((w = dockWindows.at(++i))) { if (orientation() == Qt::Horizontal && dw->y() < w->y()) return true; if (orientation() == Qt::Vertical && dw->x() < w->x()) return true; } else { return true; } return false; }
void tst_Q3DockWindow::showChild() { // task 26225 // calling show dose not propergate to child widgets if // main window is already showing Q3MainWindow mw; mw.show(); Q3DockWindow * dock = new Q3DockWindow(&mw); QPushButton * qpb = new QPushButton("hi", dock); dock->setWidget(qpb); dock->show(); QVERIFY( mw.isVisible() ); QVERIFY( dock->isVisible() ); QVERIFY( qpb->isVisible() ); }
QSize Q3DockAreaLayout::minimumSize() const { if (dockWindows->isEmpty()) return QSize(0, 0); if (dirty) { Q3DockAreaLayout *that = (Q3DockAreaLayout *) this; that->layoutItems(geometry()); } int s = 0; for (int i = 0; i < dockWindows->size(); ++i) { Q3DockWindow *dw = dockWindows->at(i); if (dw->isHidden()) continue; s = qMax(s, dock_strut(dw, orientation())); } return orientation() == Qt::Horizontal ? QSize(0, s ? s+2 : 0) : QSize(s, 0); }
void Q3DockArea::moveDockWindow(Q3DockWindow *w, int index) { invalidateFixedSizes(); Q3DockWindow *dockWindow = 0; int dockWindowIndex = findDockWindow(w); if (dockWindowIndex == -1) { dockWindow = w; bool vis = dockWindow->isVisible(); dockWindow->setParent(this); dockWindow->move(0, 0); if(vis) dockWindow->show(); w->installEventFilter(this); updateLayout(); setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum, orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum)); dockWindows.append(w); } else { if (w->parent() != this) { bool vis = w->isVisible(); w->setParent(this); w->move(0, 0); if(vis) w->show(); } if (index == -1) { dockWindows.removeAll(w); dockWindows.append(w); } } w->dockArea = this; w->curPlace = Q3DockWindow::InDock; w->updateGui(); if (index != -1 && index < (int)dockWindows.count()) { dockWindows.removeAll(w); dockWindows.insert(index, w); } }
QSize Q3DockAreaLayout::sizeHint() const { if (dockWindows->isEmpty()) return QSize(0, 0); if (dirty) { Q3DockAreaLayout *that = (Q3DockAreaLayout *) this; that->layoutItems(geometry()); } int w = 0; int h = 0; int y = -1; int x = -1; int ph = 0; int pw = 0; for (int i = 0; i < dockWindows->size(); ++i) { Q3DockWindow *dw = dockWindows->at(i); int plush = 0, plusw = 0; if (dw->isHidden()) continue; if (hasHeightForWidth()) { if (y != dw->y()) plush = ph; y = dw->y(); ph = dw->height(); } else { if (x != dw->x()) plusw = pw; x = dw->x(); pw = dw->width(); } h = qMax(h, dw->height() + plush); w = qMax(w, dw->width() + plusw); } if (hasHeightForWidth()) return QSize(0, h); return QSize(w, 0); }
Q3DockWindow* makeDock( const char* text, QWidget* parent ) { Q3DockWindow* dock = new Q3DockWindow(Q3DockWindow::InDock, parent, text); dock->setResizeEnabled(true); dock->setCloseMode(Q3DockWindow::Always); dock->setCaption(text); dock->setWidget(makeFrame(text, dock)); dock->show(); return dock; }
void Q3DockArea::removeDockWindow(Q3DockWindow *w, bool makeFloating, bool swap, bool fixNewLines) { w->removeEventFilter(this); Q3DockWindow *dockWindow = 0; int i = findDockWindow(w); if (i == -1) return; dockWindow = dockWindows.at(i); dockWindows.removeAt(i); QList<Q3DockWindow *> lineStarts = layout->lineStarts(); if (fixNewLines && lineStarts.contains(dockWindow) && i < dockWindows.count()) dockWindows.at(i)->setNewLine(true); if (makeFloating) { QWidget *p = parentWidget() ? parentWidget() : window(); dockWindow->setParent(p, Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool); dockWindow->move(0, 0); } if (swap) dockWindow->resize(dockWindow->height(), dockWindow->width()); updateLayout(); if (dockWindows.isEmpty()) setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); }
void Q3DockArea::moveDockWindow(Q3DockWindow *w, const QPoint &p, const QRect &r, bool swap) { invalidateFixedSizes(); int mse = -10; bool hasResizable = false; for (int i = 0; i < dockWindows.size(); ++i) { Q3DockWindow *dw = dockWindows.at(i); if (dw->isHidden()) continue; if (dw->isResizeEnabled()) hasResizable = true; if (orientation() != Qt::Horizontal) mse = qMax(qMax(dw->fixedExtent().width(), dw->width()), mse); else mse = qMax(qMax(dw->fixedExtent().height(), dw->height()), mse); } if (!hasResizable && w->isResizeEnabled()) { if (orientation() != Qt::Horizontal) mse = qMax(w->fixedExtent().width(), mse); else mse = qMax(w->fixedExtent().height(), mse); } Q3DockWindow *dockWindow = 0; int dockWindowIndex = findDockWindow(w); QList<Q3DockWindow *> lineStarts = layout->lineStarts(); QList<QRect> lines = layout->lineList(); bool wasAloneInLine = false; QPoint pos = mapFromGlobal(p); int line = lineOf(dockWindowIndex); QRect lr; if (line < lines.size()) lr = lines.at(line); if (dockWindowIndex != -1) { if (lineStarts.contains(w) && ((dockWindowIndex < dockWindows.count() - 1 && lineStarts.contains(dockWindows.at(dockWindowIndex + 1))) || dockWindowIndex == dockWindows.count() - 1)) wasAloneInLine = true; dockWindow = dockWindows.takeAt(dockWindowIndex); if (!wasAloneInLine) { // only do the pre-layout if the widget isn't the only one in its line if (lineStarts.contains(dockWindow) && dockWindowIndex < dockWindows.count()) dockWindows.at(dockWindowIndex)->setNewLine(true); layout->layoutItems(QRect(0, 0, width(), height()), true); } } else { dockWindow = w; bool vis = dockWindow->isVisible(); dockWindow->setParent(this); dockWindow->move(0, 0); if(vis) dockWindow->show(); if (swap) dockWindow->resize(dockWindow->height(), dockWindow->width()); w->installEventFilter(this); } lineStarts = layout->lineStarts(); lines = layout->lineList(); QRect rect = QRect(mapFromGlobal(r.topLeft()), r.size()); if (orientation() == Qt::Horizontal && QApplication::reverseLayout()) { rect = QRect(width() - rect.x() - rect.width(), rect.y(), rect.width(), rect.height()); pos.rx() = width() - pos.x(); } dockWindow->setOffset(point_pos(rect.topLeft(), orientation())); if (orientation() == Qt::Horizontal) { int offs = dockWindow->offset(); if (width() - offs < dockWindow->minimumWidth()) dockWindow->setOffset(width() - dockWindow->minimumWidth()); } else { int offs = dockWindow->offset(); if (height() - offs < dockWindow->minimumHeight()) dockWindow->setOffset(height() - dockWindow->minimumHeight()); } if (dockWindows.isEmpty()) { dockWindows.append(dockWindow); } else { int dockLine = -1; bool insertLine = false; int i = 0; QRect lineRect; // find the line which we touched with the mouse for (QList<QRect>::Iterator it = lines.begin(); it != lines.end(); ++it, ++i) { if (point_pos(pos, orientation(), true) >= point_pos((*it).topLeft(), orientation(), true) && point_pos(pos, orientation(), true) <= point_pos((*it).topLeft(), orientation(), true) + size_extent((*it).size(), orientation(), true)) { dockLine = i; lineRect = *it; break; } } if (dockLine == -1) { // outside the dock... insertLine = true; if (point_pos(pos, orientation(), true) < 0) // insert as first line dockLine = 0; else dockLine = (int)lines.count(); // insert after the last line ### size_t/int cast } else { // inside the dock (we have found a dockLine) if (point_pos(pos, orientation(), true) < point_pos(lineRect.topLeft(), orientation(), true) + 4) { // mouse was at the very beginning of the line insertLine = true; // insert a new line before that with the docking widget } else if (point_pos(pos, orientation(), true) > point_pos(lineRect.topLeft(), orientation(), true) + size_extent(lineRect.size(), orientation(), true) - 4) { // mouse was at the very and of the line insertLine = true; // insert a line after that with the docking widget dockLine++; } } if (!insertLine && wasAloneInLine && lr.contains(pos)) // if we are alone in a line and just moved in there, re-insert it insertLine = true; #if defined(QDOCKAREA_DEBUG) qDebug("insert in line %d, and insert that line: %d", dockLine, insertLine); qDebug(" (btw, we have %d lines)", lines.count()); #endif Q3DockWindow *dw = 0; if (dockLine >= (int)lines.count()) { // insert after last line dockWindows.append(dockWindow); dockWindow->setNewLine(true); #if defined(QDOCKAREA_DEBUG) qDebug("insert at the end"); #endif } else if (dockLine == 0 && insertLine) { // insert before first line dockWindows.insert(0, dockWindow); dockWindows.at(1)->setNewLine(true); #if defined(QDOCKAREA_DEBUG) qDebug("insert at the begin"); #endif } else { // insert somewhere in between // make sure each line start has a new line for (int i = 0; i < lineStarts.size(); ++i) { dw = lineStarts.at(i); dw->setNewLine(true); } // find the index of the first widget in the search line int searchLine = dockLine; #if defined(QDOCKAREA_DEBUG) qDebug("search line start of %d", searchLine); #endif Q3DockWindow *lsw = lineStarts.at(searchLine); int index = dockWindows.indexOf(lsw); if (index == -1) { // the linestart widget hasn't been found, try to find it harder if (lsw == w && dockWindowIndex <= dockWindows.count()) index = dockWindowIndex; else index = 0; } #if defined(QDOCKAREA_DEBUG) qDebug(" which starts at %d", index); #endif if (!insertLine) { // if we insert the docking widget in the existing line // find the index for the widget bool inc = true; bool firstTime = true; for (int i = index; i < dockWindows.size(); ++i) { dw = dockWindows.at(i); if (orientation() == Qt::Horizontal) dw->setFixedExtentWidth(-1); else dw->setFixedExtentHeight(-1); if (!firstTime && lineStarts.contains(dw)) // we are in the next line, so break break; if (point_pos(pos, orientation()) < point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2) { inc = false; } if (inc) index++; firstTime = false; } #if defined(QDOCKAREA_DEBUG) qDebug("insert at index: %d", index); #endif // if we insert it just before a widget which has a new line, transfer the newline to the docking widget // but not if we didn't only mave a widget in its line which was alone in the line before if (!(wasAloneInLine && lr.contains(pos)) && index >= 0 && index < dockWindows.count() && dockWindows.at(index)->newLine() && lineOf(index) == dockLine) { #if defined(QDOCKAREA_DEBUG) qDebug("get rid of the old newline and get me one"); #endif dockWindows.at(index)->setNewLine(false); dockWindow->setNewLine(true); } else if (wasAloneInLine && lr.contains(pos)) { dockWindow->setNewLine(true); } else { // if we are somewhere in a line, get rid of the newline dockWindow->setNewLine(false); } } else { // insert in a new line, so make sure the dock widget and the widget which will be after it have a newline #if defined(QDOCKAREA_DEBUG) qDebug("insert a new line"); #endif if (index < dockWindows.count()) { #if defined(QDOCKAREA_DEBUG) qDebug("give the widget at %d a newline", index); #endif Q3DockWindow* nldw = dockWindows.at(index); if (nldw) nldw->setNewLine(true); } #if defined(QDOCKAREA_DEBUG) qDebug("give me a newline"); #endif dockWindow->setNewLine(true); } // finally insert the widget dockWindows.insert(index, dockWindow); } } if (mse != -10 && w->isResizeEnabled()) { if (orientation() != Qt::Horizontal) w->setFixedExtentWidth(qMin(qMax(w->minimumWidth(), mse), w->sizeHint().width())); else w->setFixedExtentHeight(qMin(qMax(w->minimumHeight(), mse), w->sizeHint().height())); } updateLayout(); setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum, orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum)); }
int Q3DockAreaLayout::layoutItems(const QRect &rect, bool testonly) { if (dockWindows->isEmpty()) return 0; dirty = false; // some corrections QRect r = rect; if (orientation() == Qt::Vertical) r.setHeight(r.height() - 3); // init lines.clear(); ls.clear(); int start = start_pos(r, orientation()); int pos = start; int sectionpos = 0; int linestrut = 0; QList<Q3DockData> lastLine; int tbstrut = -1; int maxsize = size_extent(rect.size(), orientation()); int visibleWindows = 0; // go through all widgets in the dock for (int i = 0; i < dockWindows->size(); ++i) { Q3DockWindow *dw = dockWindows->at(i); if (dw->isHidden()) continue; ++visibleWindows; // find position for the widget: This is the maximum of the // end of the previous widget and the offset of the widget. If // the position + the width of the widget dosn't fit into the // dock, try moving it a bit back, if possible. int op = pos; int dockExtend = dock_extent(dw, orientation(), maxsize); if (!dw->isStretchable()) { pos = qMax(pos, dw->offset()); if (pos + dockExtend > size_extent(r.size(), orientation()) - 1) pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend); } if (!lastLine.isEmpty() && !dw->newLine() && space_left(rect, pos, orientation()) < dockExtend) shrink_extend(dw, dockExtend, space_left(rect, pos, orientation()), orientation()); // if the current widget doesn't fit into the line anymore and it is not the first widget of the line if (!lastLine.isEmpty() && (space_left(rect, pos, orientation()) < dockExtend || dw->newLine())) { if (!testonly) // place the last line, if not in test mode place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this); // remember the line coordinats of the last line if (orientation() == Qt::Horizontal) lines.append(QRect(0, sectionpos, r.width(), linestrut)); else lines.append(QRect(sectionpos, 0, linestrut, r.height())); // do some clearing for the next line lastLine.clear(); sectionpos += linestrut; linestrut = 0; pos = start; tbstrut = -1; } // remember first widget of a line if (lastLine.isEmpty()) { ls.append(dw); // try to make the best position int op = pos; if (!dw->isStretchable()) pos = qMax(pos, dw->offset()); if (pos + dockExtend > size_extent(r.size(), orientation()) - 1) pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend); } // do some calculations and add the remember the rect which the docking widget requires for the placing QRect dwRect(pos, sectionpos, dockExtend, dock_strut(dw, orientation() )); lastLine.append(Q3DockData(dw, dwRect)); if (qobject_cast<Q3ToolBar*>(dw)) tbstrut = qMax(tbstrut, dock_strut(dw, orientation())); linestrut = qMax(dock_strut(dw, orientation()), linestrut); add_size(dockExtend, pos, orientation()); } // if some stuff was not placed/stored yet, do it now if (!testonly) place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this); if (orientation() == Qt::Horizontal) lines.append(QRect(0, sectionpos, r.width(), linestrut)); else lines.append(QRect(sectionpos, 0, linestrut, r.height())); if (lines.size() >= 2 && *(--lines.end()) == *(--(--lines.end()))) lines.removeLast(); bool hadResizable = false; for (int i = 0; i < dockWindows->size(); ++i) { Q3DockWindow *dw = dockWindows->at(i); if (!dw->isVisibleTo(parentWidget)) continue; hadResizable = hadResizable || dw->isResizeEnabled(); dw->updateSplitterVisibility(visibleWindows > 1); //!dw->area()->isLastDockWindow(dw)); if (Q3ToolBar *tb = qobject_cast<Q3ToolBar *>(dw)) tb->checkForExtension(dw->size()); } return sectionpos + linestrut; }
int Q3DockArea::maxSpace(int hint, Q3DockWindow *dw) { int index = findDockWindow(dw); if (index == -1 || index + 1 >= (int)dockWindows.count()) { if (orientation() == Qt::Horizontal) return dw->width(); return dw->height(); } Q3DockWindow *w = 0; int i = 0; do { w = dockWindows.at(index + (++i)); } while (i + 1 < (int)dockWindows.count() && (!w || w->isHidden())); if (!w || !w->isResizeEnabled() || i >= (int)dockWindows.count()) { if (orientation() == Qt::Horizontal) return dw->width(); return dw->height(); } int min = 0; Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(w); if (orientation() == Qt::Horizontal) { w->setFixedExtentWidth(-1); if (!tb) min = qMax(w->minimumSize().width(), w->minimumSizeHint().width()); else min = w->sizeHint().width(); } else { w->setFixedExtentHeight(-1); if (!tb) min = qMax(w->minimumSize().height(), w->minimumSizeHint().height()); else min = w->sizeHint().height(); } int diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height()); if ((orientation() == Qt::Horizontal ? w->width() : w->height()) - diff < min) hint = (orientation() == Qt::Horizontal ? dw->width() : dw->height()) + (orientation() == Qt::Horizontal ? w->width() : w->height()) - min; diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height()); if (orientation() == Qt::Horizontal) w->setFixedExtentWidth(w->width() - diff); else w->setFixedExtentHeight(w->height() - diff); return hint; }