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::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); } }
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; }
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; }