From ee58a2db6b758ca0629f9088a667d20b59fdc5e6 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 14 Dec 2008 01:03:28 +0000 Subject: [PATCH] some work on a better widget layouting and more usable splitters in combination with CollapsibleWidgets git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1915 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 14 ++- include/fluiq/collapsible_widget.h | 18 ++- include/fluiq/splitter.h | 34 ++--- include/fluiq/workspace.h | 1 - src/gui/fluiq/collapsible_widget.cpp | 178 +++++++++++++++++++++++---- src/gui/fluiq/splitter.cpp | 72 +++++------ src/gui/fluiq/widget_container.cpp | 10 ++ src/gui/fluiq/workspace.cpp | 9 -- 8 files changed, 235 insertions(+), 101 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93df787e3..02db60fcb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,20 @@ 2008-12-14 Tobias Doerffel - * src/core/main.cpp: + * include/fluiq/collapsible_widget.h: + * include/fluiq/splitter.h: + * include/fluiq/workspace.h: + * src/gui/fluiq/collapsible_widget.cpp: + * src/gui/fluiq/splitter.cpp: + * src/gui/fluiq/widget_container.cpp: + * src/gui/fluiq/workspace.cpp: + some work on a better widget layouting and more usable splitters in + combination with CollapsibleWidgets + * src/core/config_mgr.cpp: + * src/core/main.cpp: * src/core/mmp.cpp: - * src/gui/main_window.cpp: * src/gui/about_dialog.cpp: + * src/gui/main_window.cpp: * lmmsversion.h.in: * CMakeLists.txt: moved version information into separate header file to avoid diff --git a/include/fluiq/collapsible_widget.h b/include/fluiq/collapsible_widget.h index 5d50c981e..e2b95741e 100644 --- a/include/fluiq/collapsible_widget.h +++ b/include/fluiq/collapsible_widget.h @@ -52,6 +52,7 @@ public: virtual QSize sizeHint( void ) const; + static const int MinimalHeight = 20; protected: virtual void enterEvent( QEvent * _ev ); @@ -92,21 +93,16 @@ public: void addWidget( QWidget * _w ); void insertWidget( int _idx, QWidget * _w ); - inline QString labelText( void ) const - { - return m_header->windowTitle(); - } - - inline void setLabelText( const QString & _text ) - { - m_header->setWindowTitle( _text ); - } - inline Qt::Orientation orientation( void ) const { return m_orientation; } + inline bool isCollapsed( void ) const + { + return m_header->isCollapsed(); + } + public slots: void expand( void ); @@ -115,6 +111,8 @@ public slots: private: Qt::Orientation m_orientation; + QSize m_origMinSize; + QSize m_origMaxSize; QBoxLayout * m_masterLayout; CollapsibleWidgetHeader * m_header; diff --git a/include/fluiq/splitter.h b/include/fluiq/splitter.h index 541a76756..6f41ce29a 100644 --- a/include/fluiq/splitter.h +++ b/include/fluiq/splitter.h @@ -25,36 +25,42 @@ #ifndef _FLUIQ_SPLITTER_H #define _FLUIQ_SPLITTER_H -#include +#include + +class QBoxLayout; namespace FLUIQ { -class Splitter : public QSplitter +class Splitter : public QWidget { Q_OBJECT public: Splitter( Qt::Orientation _o, QWidget * _parent = NULL ); virtual ~Splitter(); + void addWidget( QWidget * _widget ); -protected: - QSplitterHandle * createHandle( void ); + int indexOf( QWidget * _widget ) const; + QWidget * widget( int _idx ); -} ; + int count( void ) const + { + return m_children.count(); + } + + Qt::Orientation orientation( void ) const + { + return m_orientation; + } -class SplitterHandle : public QSplitterHandle -{ -public: - SplitterHandle( Qt::Orientation _o, QSplitter * _parent ); - virtual ~SplitterHandle(); - - -protected: - void paintEvent( QPaintEvent * _event ); +private: + Qt::Orientation m_orientation; + QList m_children; + QBoxLayout * m_mainLayout; } ; diff --git a/include/fluiq/workspace.h b/include/fluiq/workspace.h index 006459543..5e0be77e3 100644 --- a/include/fluiq/workspace.h +++ b/include/fluiq/workspace.h @@ -43,7 +43,6 @@ public: virtual ~Workspace(); void addWidget( QWidget * _w ); - void addWidgetToExistingRow( QWidget * _w ); private: diff --git a/src/gui/fluiq/collapsible_widget.cpp b/src/gui/fluiq/collapsible_widget.cpp index 31c252039..e8a02f3bf 100644 --- a/src/gui/fluiq/collapsible_widget.cpp +++ b/src/gui/fluiq/collapsible_widget.cpp @@ -28,14 +28,13 @@ #include #include "fluiq/collapsible_widget.h" +#include "fluiq/splitter.h" #include "embed.h" // implementation of FLUIQ::CollapsibleWidgetHeader -const int HEADER_MIN_HEIGHT = 20; - FLUIQ::CollapsibleWidgetHeader::CollapsibleWidgetHeader( CollapsibleWidget * _parent ) : Widget( _parent ), @@ -55,11 +54,11 @@ FLUIQ::CollapsibleWidgetHeader::CollapsibleWidgetHeader( if( m_parent->orientation() == Qt::Horizontal ) { - setFixedWidth( HEADER_MIN_HEIGHT ); + setFixedWidth( MinimalHeight ); } else { - setFixedHeight( HEADER_MIN_HEIGHT ); + setFixedHeight( MinimalHeight ); } } @@ -89,12 +88,14 @@ QSize FLUIQ::CollapsibleWidgetHeader::sizeHint( void ) const { if( m_parent->orientation() == Qt::Horizontal ) { - return QSize( HEADER_MIN_HEIGHT, - HEADER_MIN_HEIGHT + - fontMetrics().width( windowTitle() ) ); + return QSize( MinimalHeight, + MinimalHeight + + fontMetrics().width( + m_parent->windowTitle() ) ); } - return QSize( HEADER_MIN_HEIGHT + fontMetrics().width( windowTitle() ), - HEADER_MIN_HEIGHT ); + return QSize( MinimalHeight + + fontMetrics().width( m_parent->windowTitle() ), + MinimalHeight ); } @@ -131,7 +132,7 @@ void FLUIQ::CollapsibleWidgetHeader::mousePressEvent( QMouseEvent * _ev ) Qt::SizeVerCursor : Qt::SizeHorCursor ); m_pressed = true; m_moved = false; - m_origMousePos = _ev->pos(); + m_origMousePos = _ev->globalPos(); update(); _ev->accept(); } @@ -150,20 +151,72 @@ void FLUIQ::CollapsibleWidgetHeader::mouseMoveEvent( QMouseEvent * _event ) { m_moved = true; - QSize ms = m_parent->minimumSize(); + QPoint pos = _event->globalPos(); - if( m_parent->orientation() == Qt::Vertical ) + Splitter * s = NULL; + if( m_parent->parentWidget() && + ( s = qobject_cast + ( m_parent->parentWidget() ) ) ) { - const int dy = _event->y() - m_origMousePos.y(); - ms.setHeight( qMax( 0, ms.height() + dy ) ); + int idx = s->indexOf( m_parent ); + QWidget * sibling = NULL; + CollapsibleWidget * collapsibleSibling; + + // look whether we have expanded left-hand siblings + while( idx > 0 && sibling == NULL ) + { + --idx; + sibling = s->widget( idx ); + collapsibleSibling = + qobject_cast( + sibling ); + if( collapsibleSibling && + collapsibleSibling->isCollapsed() ) + { + sibling = NULL; + } + } + + // found one? + if( sibling ) + { + QSize minSizeHint = sibling->minimumSizeHint(); + QSize sizeHint = sibling->sizeHint(); + QSize minSize = sibling->size(); + QSize maxSize = sibling->maximumSize(); + // then increase size according to orientation + if( m_parent->orientation() == Qt::Vertical ) + { +const int dy = pos.y() - m_origMousePos.y(); +minSize.setHeight( qMax( minSizeHint.height(), minSize.height() + dy ) ); +// implement snapping when reaching size hint +if( dy < 0 && ( ( minSize.height() < sizeHint.height() && + sizeHint.height() - minSize.height() < 20 ) + || ( sibling->size().height() == minSize.height() ) ) ) +{ + return; +} +maxSize.setHeight( minSize.height() ); + } + else + { +const int dx = pos.x() - m_origMousePos.x(); +minSize.setWidth( qMax( minSizeHint.width(), minSize.width() + dx ) ); +// implement snapping when reaching size hint +if( dx < 0 && ( ( minSize.width() < sizeHint.width() && + sizeHint.width() - minSize.width() < 20 ) + || ( sibling->size().width() == minSize.width() ) ) ) +{ + return; +} +maxSize.setWidth( minSize.width() ); + } + sibling->setMinimumSize( minSize ); + sibling->setMaximumSize( maxSize ); + s->updateGeometry(); + } + m_origMousePos = pos; } - else - { - const int dx = _event->x() - m_origMousePos.x(); - ms.setWidth( qMax( 0, ms.width() + dx ) ); - } - m_parent->setMinimumSize( ms ); - m_origMousePos = _event->pos(); } } @@ -226,7 +279,8 @@ void FLUIQ::CollapsibleWidgetHeader::paintEvent( QPaintEvent * _ev ) p.setPen( palette().color( QPalette::Text ) ); p.drawPixmap( 8, 5, m_collapsed ? m_arrowCollapsed : m_arrowExpanded ); - p.drawText( 20, 10+r.height()-p.fontMetrics().height(), windowTitle() ); + p.drawText( 20, 10+r.height()-p.fontMetrics().height(), + m_parent->windowTitle() ); } @@ -241,6 +295,8 @@ FLUIQ::CollapsibleWidget::CollapsibleWidget( Qt::Orientation _or, Widget * _parent ) : Widget( _parent ), m_orientation( _or ), + m_origMinSize(), + m_origMaxSize(), m_masterLayout( NULL ) { if( m_orientation == Qt::Horizontal ) @@ -253,10 +309,12 @@ FLUIQ::CollapsibleWidget::CollapsibleWidget( Qt::Orientation _or, } m_masterLayout->setMargin( 0 ); m_masterLayout->setSpacing( 0 ); - + setSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Expanding ); m_header = new CollapsibleWidgetHeader( this ); m_masterLayout->addWidget( m_header ); + m_masterLayout->insertStretch( 100, 0 ); connect( m_header, SIGNAL( expanded() ), this, SLOT( expand() ) ); @@ -276,7 +334,7 @@ FLUIQ::CollapsibleWidget::~CollapsibleWidget() void FLUIQ::CollapsibleWidget::addWidget( QWidget * _w ) { - m_masterLayout->addWidget( _w ); + m_masterLayout->insertWidget( m_masterLayout->count()-1, _w, 1 ); } @@ -284,7 +342,7 @@ void FLUIQ::CollapsibleWidget::addWidget( QWidget * _w ) void FLUIQ::CollapsibleWidget::insertWidget( int _idx, QWidget * _w ) { - m_masterLayout->insertWidget( _idx, _w ); + m_masterLayout->insertWidget( _idx, _w, 1 ); } @@ -295,7 +353,7 @@ void FLUIQ::CollapsibleWidget::expand( void ) m_header->setCollapsed( false ); // set size properties - setMaximumSize( QSize( 1 << 16, 1 << 16 ) ); + setMaximumSize( m_origMaxSize ); // show all children foreach( QWidget * w, findChildren() ) @@ -305,15 +363,37 @@ void FLUIQ::CollapsibleWidget::expand( void ) w->show(); } } - setMinimumSize( sizeHint() ); + + // parent has gotten smaller while we were collapsed? + if( m_orientation == Qt::Horizontal ) + { + // then re-adjust height + if( m_origMinSize.height() > sizeHint().height() ) + { + m_origMinSize.setHeight( sizeHint().height() ); + } + } + else + { + // then re-adjust width + if( m_origMinSize.width() > sizeHint().width() ) + { + m_origMinSize.setWidth( sizeHint().width() ); + } + } + setMinimumSize( m_origMinSize ); } + void FLUIQ::CollapsibleWidget::collapse( void ) { m_header->setCollapsed( true ); + m_origMinSize = minimumSize(); + m_origMaxSize = maximumSize(); + // hide all children foreach( QWidget * w, findChildren() ) { @@ -324,6 +404,7 @@ void FLUIQ::CollapsibleWidget::collapse( void ) } // set size properties + const QSize origSize = size(); const QSize headerSize = m_header->sizeHint(); if( m_orientation == Qt::Vertical ) { @@ -334,6 +415,49 @@ void FLUIQ::CollapsibleWidget::collapse( void ) setMaximumSize( QSize( headerSize.width(), 1 << 16 ) ); } setMinimumSize( headerSize ); + + +/* // now try to redistribute freed space amongst sibling widgets + Splitter * s = NULL; + if( parentWidget() && + ( s = qobject_cast( parentWidget() ) ) ) + { + int numExpanded = 0; + for( int i = 0; i < s->count(); ++i ) + { + CollapsibleWidget * cw = + qobject_cast( + s->widget( i ) ); + if( cw && cw->isCollapsed() == false ) + { + ++numExpanded; + } + } + if( numExpanded == 0 ) + { + return; + } + QSize addSizePerSibling = ( origSize - size() ) / numExpanded; + if( m_orientation == Qt::Vertical ) + { + addSizePerSibling.setWidth( 0 ); + } + else + { + addSizePerSibling.setHeight( 0 ); + } + for( int i = 0; i < s->count(); ++i ) + { + CollapsibleWidget * cw = + qobject_cast( + s->widget( i ) ); + if( cw && cw->isCollapsed() == false ) + { + cw->setMaximumSize( cw->maximumSize() + + addSizePerSibling ); + } + } + }*/ } diff --git a/src/gui/fluiq/splitter.cpp b/src/gui/fluiq/splitter.cpp index 8978c718a..06d2735b7 100644 --- a/src/gui/fluiq/splitter.cpp +++ b/src/gui/fluiq/splitter.cpp @@ -23,6 +23,7 @@ */ +#include #include #include @@ -30,11 +31,20 @@ FLUIQ::Splitter::Splitter( Qt::Orientation _o, QWidget * _parent ) : - QSplitter( _o, _parent ) + QWidget( _parent ), + m_orientation( _o ) { - setChildrenCollapsible( false ); - setSizePolicy( QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding ); + if( m_orientation == Qt::Horizontal ) + { + m_mainLayout = new QHBoxLayout( this ); + } + else + { + m_mainLayout = new QVBoxLayout( this ); + } + m_mainLayout->setMargin( 0 ); + m_mainLayout->setSpacing( 0 ); + m_mainLayout->insertStretch( 100, 0 ); } @@ -47,52 +57,38 @@ FLUIQ::Splitter::~Splitter() -QSplitterHandle * FLUIQ::Splitter::createHandle( void ) +void FLUIQ::Splitter::addWidget( QWidget * _w ) { - return new FLUIQ::SplitterHandle( orientation(), this ); + m_mainLayout->insertWidget( m_children.size(), _w, 1 ); + m_children << _w; } - -FLUIQ::SplitterHandle::SplitterHandle( Qt::Orientation _o, - QSplitter * _parent ) : - QSplitterHandle( _o, _parent ) +int FLUIQ::Splitter::indexOf( QWidget * _widget ) const { -} - - - - -FLUIQ::SplitterHandle::~SplitterHandle() -{ -} - - - - -void FLUIQ::SplitterHandle::paintEvent( QPaintEvent * _event ) -{ - QPainter painter( this ); - - QLinearGradient gradient; - gradient.setColorAt( 0, QColor( 128, 128, 128 ) ); - gradient.setColorAt( 1, QColor( 32, 32, 32 ) ); - if( orientation() == Qt::Horizontal ) + int i = 0; + foreach( QWidget * w , m_children ) { - gradient.setStart( rect().left(), rect().height()/2 ); - gradient.setFinalStop( rect().right(), rect().height()/2 ); + if( w == _widget ) + { + return i; + } + ++i; } - else - { - gradient.setStart( rect().width()/2, rect().top() ); - gradient.setFinalStop( rect().width()/2, rect().bottom() ); - } - painter.fillRect( _event->rect(), QBrush( gradient ) ); + + return -1; } + +QWidget * FLUIQ::Splitter::widget( int _idx ) +{ + return m_children[_idx]; +} + + #include "fluiq/moc_splitter.cxx" diff --git a/src/gui/fluiq/widget_container.cpp b/src/gui/fluiq/widget_container.cpp index a73d449db..8b511f9e0 100644 --- a/src/gui/fluiq/widget_container.cpp +++ b/src/gui/fluiq/widget_container.cpp @@ -46,6 +46,16 @@ FLUIQ::WidgetContainer::WidgetContainer( Qt::Orientation _o, m_scrollArea->setWidgetResizable( true ); m_scrollArea->setFrameStyle( QFrame::NoFrame ); +/* if( _o == Qt::Horizontal ) + { + m_scrollArea->setVerticalScrollBarPolicy( + Qt::ScrollBarAlwaysOff ); + } + else + { + m_scrollArea->setHorizontalScrollBarPolicy( + Qt::ScrollBarAlwaysOff ); + }*/ myLayout->addWidget( m_scrollArea ); m_splitter = new Splitter( m_orientation ); diff --git a/src/gui/fluiq/workspace.cpp b/src/gui/fluiq/workspace.cpp index ee63d92b0..84a68f238 100644 --- a/src/gui/fluiq/workspace.cpp +++ b/src/gui/fluiq/workspace.cpp @@ -52,21 +52,12 @@ FLUIQ::Workspace::~Workspace() void FLUIQ::Workspace::addWidget( QWidget * _w ) { - m_currentSplitter = new Splitter( Qt::Horizontal, this ); - m_masterLayout->addWidget( m_currentSplitter ); - m_currentSplitter->addWidget( _w ); } -void FLUIQ::Workspace::addWidgetToExistingRow( QWidget * _w ) -{ - m_currentSplitter->addWidget( _w ); -} - - #include "fluiq/moc_workspace.cxx"