void QDockArea::setFixedExtent( int d, QDockWindow *dw ) { QPtrList<QDockWindow> lst; QDockWindow *w; for ( w = dockWindows->first(); w; w = dockWindows->next() ) { if ( w->isHidden() ) continue; if ( orientation() == Horizontal ) { if ( dw->y() != w->y() ) continue; } else { if ( dw->x() != w->x() ) continue; } if ( orientation() == Horizontal ) d = QMAX( d, w->minimumHeight() ); else d = QMAX( d, w->minimumWidth() ); if ( w->isResizeEnabled() ) lst.append( w ); } for ( w = lst.first(); w; w = lst.next() ) { if ( orientation() == Horizontal ) w->setFixedExtentHeight( d ); else w->setFixedExtentWidth( d ); } }
int QDockArea::maxSpace( int hint, QDockWindow *dw ) { int index = findDockWindow( dw ); if ( index == -1 || index + 1 >= (int)dockWindows->count() ) { if ( orientation() == Horizontal ) return dw->width(); return dw->height(); } QDockWindow *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() == Horizontal ) return dw->width(); return dw->height(); } int min = 0; QToolBar *tb = ::qt_cast<QToolBar*>(w); if ( orientation() == 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() == Horizontal ? dw->width() : dw->height() ); if ( ( orientation() == Horizontal ? w->width() : w->height() ) - diff < min ) hint = ( orientation() == Horizontal ? dw->width() : dw->height() ) + ( orientation() == Horizontal ? w->width() : w->height() ) - min; diff = hint - ( orientation() == Horizontal ? dw->width() : dw->height() ); if ( orientation() == Horizontal ) w->setFixedExtentWidth( w->width() - diff ); else w->setFixedExtentHeight( w->height() - diff ); return hint; }
QSize QDockAreaLayout::sizeHint() const { if ( !dockWindows || !dockWindows->first() ) return QSize( 0, 0 ); if ( dirty ) { QDockAreaLayout *that = (QDockAreaLayout *) this; that->layoutItems( geometry() ); } int w = 0; int h = 0; QPtrListIterator<QDockWindow> it( *dockWindows ); QDockWindow *dw = 0; it.toFirst(); int y = -1; int x = -1; int ph = 0; int pw = 0; while ( ( dw = it.current() ) != 0 ) { int plush = 0, plusw = 0; ++it; 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 ); }
QSize QDockAreaLayout::minimumSize() const { if ( !dockWindows || !dockWindows->first() ) return QSize( 0, 0 ); if ( dirty ) { QDockAreaLayout *that = (QDockAreaLayout *) this; that->layoutItems( geometry() ); } int s = 0; QPtrListIterator<QDockWindow> it( *dockWindows ); QDockWindow *dw = 0; while ( ( dw = it.current() ) != 0 ) { ++it; if ( dw->isHidden() ) continue; s = QMAX( s, dock_strut( dw, orientation() ) ); } return orientation() == Horizontal ? QSize( 0, s ? s+2 : 0 ) : QSize( s, 0 ); }
void QDockArea::moveDockWindow( QDockWindow *w, const QPoint &p, const QRect &r, bool swap ) { invalidateFixedSizes(); int mse = -10; bool hasResizable = FALSE; for ( QDockWindow *dw = dockWindows->first(); dw; dw = dockWindows->next() ) { 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 ); } QDockWindow *dockWindow = 0; int dockWindowIndex = findDockWindow( w ); QPtrList<QDockWindow> lineStarts = layout->lineStarts(); QValueList<QRect> lines = layout->lineList(); bool wasAloneInLine = FALSE; QPoint pos = mapFromGlobal( p ); QRect lr = *lines.at( lineOf( dockWindowIndex ) ); if ( dockWindowIndex != -1 ) { if ( lineStarts.find( w ) != -1 && ( dockWindowIndex < (int)dockWindows->count() - 1 && lineStarts.find( dockWindows->at( dockWindowIndex + 1 ) ) != -1 || dockWindowIndex == (int)dockWindows->count() - 1 ) ) wasAloneInLine = TRUE; dockWindow = dockWindows->take( dockWindowIndex ); if ( !wasAloneInLine ) { // only do the pre-layout if the widget isn't the only one in its line if ( lineStarts.findRef( dockWindow ) != -1 && dockWindowIndex < (int)dockWindows->count() ) dockWindows->at( dockWindowIndex )->setNewLine( TRUE ); layout->layoutItems( QRect( 0, 0, width(), height() ), TRUE ); } } else { dockWindow = w; dockWindow->reparent( this, QPoint( 0, 0 ), TRUE ); 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() == 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() == 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 ( QValueList<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 QDockWindow *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 ( dw = lineStarts.first(); dw; dw = lineStarts.next() ) 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 QDockWindow *lsw = lineStarts.at( searchLine ); int index = dockWindows->find( lsw ); if ( index == -1 ) { // the linestart widget hasn't been found, try to find it harder if ( lsw == w && dockWindowIndex <= (int)dockWindows->count()) index = dockWindowIndex; else index = 0; if ( index < (int)dockWindows->count() ) (void)dockWindows->at( index ); // move current to index } #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 ( dw = dockWindows->current(); dw; dw = dockWindows->next() ) { if ( orientation() == Horizontal ) dw->setFixedExtentWidth( -1 ); else dw->setFixedExtentHeight( -1 ); if ( !firstTime && lineStarts.find( dw ) != -1 ) // 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 < (int)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 < (int)dockWindows->count() ) { #if defined(QDOCKAREA_DEBUG) qDebug( "give the widget at %d a newline", index ); #endif QDockWindow* 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() == Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum, orientation() == Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum ) ); }
int QDockAreaLayout::layoutItems( const QRect &rect, bool testonly ) { if ( !dockWindows || !dockWindows->first() ) return 0; dirty = FALSE; // some corrections QRect r = rect; if ( orientation() == Vertical ) r.setHeight( r.height() - 3 ); // init lines.clear(); ls.clear(); QPtrListIterator<QDockWindow> it( *dockWindows ); QDockWindow *dw = 0; int start = start_pos( r, orientation() ); int pos = start; int sectionpos = 0; int linestrut = 0; QValueList<DockData> lastLine; int tbstrut = -1; int maxsize = size_extent( rect.size(), orientation() ); int visibleWindows = 0; // go through all widgets in the dock while ( ( dw = it.current() ) != 0 ) { ++it; 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() == 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; } // remeber 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( DockData( dw, dwRect ) ); if ( ::qt_cast<QToolBar*>(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() == Horizontal ) lines.append( QRect( 0, sectionpos, r.width(), linestrut ) ); else lines.append( QRect( sectionpos, 0, linestrut, r.height() ) ); if ( *(--lines.end()) == *(--(--lines.end())) ) lines.remove( lines.at( lines.count() - 1 ) ); it.toFirst(); bool hadResizable = FALSE; while ( ( dw = it.current() ) != 0 ) { ++it; if ( !dw->isVisibleTo( parentWidget ) ) continue; hadResizable = hadResizable || dw->isResizeEnabled(); dw->updateSplitterVisibility( visibleWindows > 1 ); //!dw->area()->isLastDockWindow( dw ) ); } return sectionpos + linestrut; }
QTextStream &operator<<( QTextStream &ts, const QDockArea &dockArea ) { QString str; QPtrList<QDockWindow> l = dockArea.dockWindowList(); for ( QDockWindow *dw = l.first(); dw; dw = l.next() ) str += "[" + QString( dw->caption() ) + "," + QString::number( (int)dw->offset() ) + "," + QString::number( (int)dw->newLine() ) + "," + QString::number( dw->fixedExtent().width() ) + "," + QString::number( dw->fixedExtent().height() ) + "," + QString::number( (int)!dw->isHidden() ) + "]"; ts << str << endl; return ts; }