From 94c50969fa99d9baf29f337122601444e15c026e Mon Sep 17 00:00:00 2001 From: ouv Date: Tue, 15 Jan 2013 10:34:21 +0000 Subject: [PATCH] Merged with V6_main branch (for the issue 0001481: External 20599, 20605: IMP, save views VTK, GL ) --- src/Qtx/QtxWorkstack.cxx | 1081 ++++++++++++++++++++------------------ src/Qtx/QtxWorkstack.h | 176 ++++--- 2 files changed, 665 insertions(+), 592 deletions(-) diff --git a/src/Qtx/QtxWorkstack.cxx b/src/Qtx/QtxWorkstack.cxx index e7849756a..0455ac919 100644 --- a/src/Qtx/QtxWorkstack.cxx +++ b/src/Qtx/QtxWorkstack.cxx @@ -1,11 +1,14 @@ -// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // -// This library is distributed in the hope that it will be useful +// This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. @@ -16,9 +19,10 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // File: QtxWorkstack.cxx // Author: Sergey TELKOV - +// #include "QtxWorkstack.h" #include "QtxAction.h" @@ -28,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -49,12 +53,32 @@ class QtxWorkstackArea::WidgetEvent : public QEvent { public: - WidgetEvent( Type t, QWidget* w = 0 ) : QEvent( t ), myWidget( w ) {}; + WidgetEvent( Type t, QtxWorkstackChild* w = 0 ) : QEvent( t ), myChild( w ) {}; + + QtxWorkstackChild* child() const { return myChild; } + +private: + QtxWorkstackChild* myChild; // event receiver widget +}; + +/*! + \class QtxWorkstackArea::RestoreEvent + \internal + \brief Internal class used to forward restore info events to the workarea +*/ + +class QtxWorkstackArea::RestoreEvent : public QtxWorkstackArea::WidgetEvent +{ +public: + RestoreEvent( Type t, int id, int f, QtxWorkstackChild* w ) + : WidgetEvent( t, w ), myId( id ), myFlags( f ) {}; - QWidget* widget() const { return myWidget; } + int id() const { return myId; } + int flags() const { return myFlags; } private: - QWidget* myWidget; // event receiver widget + int myId; + int myFlags; }; /*! @@ -167,13 +191,13 @@ void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab ) /*! \brief Called when drop operation is finished. - + Inserts dropped widget to the target workarea. */ void QtxWorkstackDrag::dropWidget() { if ( myArea ) - myArea->insertWidget( myChild->widget(), myTab ); + myArea->insertChild( myChild, myTab ); } /*! @@ -279,7 +303,7 @@ QSize CloseButton::sizeHint() const { ensurePolished(); int dim = 0; - if( !icon().isNull() ) + if( !icon().isNull() ) { const QPixmap pm = icon().pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal ); @@ -294,8 +318,8 @@ QSize CloseButton::sizeHint() const \return minimum size value */ QSize CloseButton::minimumSizeHint() const -{ - return sizeHint(); +{ + return sizeHint(); } /*! @@ -351,11 +375,142 @@ void CloseButton::paintEvent( QPaintEvent* ) QPixmap pm = icon().pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), isEnabled() ? underMouse() ? QIcon::Active : QIcon::Normal - : QIcon::Disabled, + : QIcon::Disabled, isDown() ? QIcon::On : QIcon::Off ); style()->drawItemPixmap( &p, r, Qt::AlignCenter, pm ); } + +/*! + \class QtxWorkstackSplitter + \internal + \brief Workstack splitter. +*/ + +/*! + \brief Constructor. + \param parent parent widget +*/ +QtxWorkstackSplitter::QtxWorkstackSplitter( QWidget* parent ) +: QSplitter( parent ) +{ + setChildrenCollapsible( false ); +} + +/*! + \brief Destructor. +*/ +QtxWorkstackSplitter::~QtxWorkstackSplitter() +{ +} + +/*! + \brief Get parent workstack + \return workstack owning this workarea +*/ +QtxWorkstack* QtxWorkstackSplitter::workstack() const +{ + QtxWorkstack* ws = 0; + QWidget* wid = parentWidget(); + while ( wid && !ws ) + { + ws = ::qobject_cast( wid ); + wid = wid->parentWidget(); + } + return ws; +} + +/*! + \brief Save the widget area configuration into data stream. +*/ +void QtxWorkstackSplitter::saveState( QDataStream& stream ) const +{ + stream << QtxWorkstack::SplitMarker; + + uchar flags = 0; + if ( orientation() == Qt::Horizontal ) + flags |= QtxWorkstack::Horizontal; + + stream << flags; + stream << count(); + + QList sz = sizes(); + for ( QList::const_iterator it = sz.begin(); it != sz.end(); ++it ) + stream << *it; + + for ( int i = 0; i < count(); i++ ) + { + QWidget* wid = widget( i ); + QtxWorkstackSplitter* split = ::qobject_cast( wid ); + if ( split ) + split->saveState( stream ); + else + { + QtxWorkstackArea* area = ::qobject_cast( wid ); + if ( area ) + area->saveState( stream ); + } + } +} + +/*! + \brief Restore the widget area configuration from data stream info. + \return \c true in successful case. +*/ +bool QtxWorkstackSplitter::restoreState( QDataStream& stream, QMap& map ) +{ + int num = 0; + uchar flags = 0; + + stream >> flags; + stream >> num; + + setOrientation( flags & QtxWorkstack::Horizontal ? Qt::Horizontal : Qt::Vertical ); + + QList sz; + for ( int s = 0; s < num; s++ ) + { + int sn = 0; + stream >> sn; + sz.append( sn ); + } + + bool ok = true; + for ( int i = 0; i < num && ok; i++ ) + { + int marker; + stream >> marker; + + if ( stream.status() != QDataStream::Ok ) + return false; + + if ( marker == QtxWorkstack::SplitMarker ) + { + QtxWorkstackSplitter* split = new QtxWorkstackSplitter( this ); + addWidget( split ); + split->setVisible( true ); + + ok = split->restoreState( stream, map ); + } + else if ( marker == QtxWorkstack::AreaMarker ) + { + QtxWorkstack* ws = workstack(); + QtxWorkstackArea* area = ws->createArea( this ); + addWidget( area ); + area->setVisible( true ); + + ok = area->restoreState( stream, map ); + } + else + return false; + } + + if ( ok ) + setSizes( sz ); + + return ok; +} + /*! \class QtxWorkstackArea \internal @@ -429,8 +584,8 @@ bool QtxWorkstackArea::isNull() const bool QtxWorkstackArea::isEmpty() const { bool res = false; - for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it ) - res = it.value().vis; + for ( ChildList::const_iterator it = myList.begin(); it != myList.end() && !res; ++it ) + res = (*it)->visibility(); return !res; } @@ -441,28 +596,49 @@ bool QtxWorkstackArea::isEmpty() const \param f widget flags \return child widget container object (or 0 if index is invalid) */ -QWidget* QtxWorkstackArea::insertWidget( QWidget* wid, const int idx, Qt::WindowFlags f ) +QtxWorkstackChild* QtxWorkstackArea::insertWidget( QWidget* wid, const int idx, Qt::WindowFlags f ) { if ( !wid ) return 0; - int pos = myList.indexOf( wid ); + QtxWorkstackChild* c = child( wid ); + if ( !c ) + c = new QtxWorkstackChild( wid, myStack, f ); + + insertChild( c, idx ); + + return c; +} + +void QtxWorkstackArea::insertChild( QtxWorkstackChild* child, const int idx ) +{ + if ( !child ) + return; + + QtxWorkstackArea* a = child->area(); + if ( a && a != this ) + a->removeChild( child, false ); + + int pos = myList.indexOf( child ); if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) ) - return 0; + return; + + bool found = myList.contains( child ); - myList.removeAll( wid ); + myList.removeAll( child ); pos = idx < 0 ? myList.count() : idx; - myList.insert( qMin( pos, (int)myList.count() ), wid ); - if ( !myInfo.contains( wid ) ) + myList.insert( qMin( pos, (int)myList.count() ), child ); + + if ( !found ) { - QtxWorkstackChild* child = new QtxWorkstackChild( wid, myStack, f ); - myChild.insert( wid, child ); - myInfo.insert( wid, WidgetInfo() ); - myInfo[wid].id = generateId(); - myInfo[wid].vis = wid->isVisibleTo( wid->parentWidget() ); + bool hasId = false; + for ( ChildList::const_iterator it = myList.begin(); it != myList.end() && !hasId; ++it ) + hasId = (*it)->id() == child->id(); + + if ( hasId || child->id() < 0 ) + child->setId( generateId() ); connect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) ); - connect( wid, SIGNAL( destroyed() ), this, SLOT( onWidgetDestroyed() ) ); connect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) ); connect( child, SIGNAL( hidden( QtxWorkstackChild* ) ), this, SLOT( onChildHidden( QtxWorkstackChild* ) ) ); connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) ); @@ -471,10 +647,8 @@ QWidget* QtxWorkstackArea::insertWidget( QWidget* wid, const int idx, Qt::Window updateState(); - setWidgetActive( wid ); - wid->setFocus(); - - return myChild[wid]; + setWidgetActive( child->widget() ); + child->widget()->setFocus(); } /*! @@ -496,43 +670,48 @@ void QtxWorkstackArea::onContextMenuRequested( QPoint p ) } /*! - \brief Called when area's child widget is destroyed. - - Removes child widget from the area. + \brief Remove widget from workarea. + \param wid widget to be removed + \param del if \c true the widget should be also deleted */ -void QtxWorkstackArea::onWidgetDestroyed() +void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del ) { - if ( sender() ) - removeWidget( (QWidget*)sender(), false ); + removeChild( child( wid ), del ); } /*! - \brief Remove widget from workarea. - \param wid widget to be removed + \brief Remove child from workarea. + \param child child to be removed \param del if \c true the widget should be also deleted */ -void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del ) +void QtxWorkstackArea::removeChild( QtxWorkstackChild* child, const bool del ) { - if ( !myList.contains( wid ) ) + if ( !myList.contains( child ) ) return; - bool wasActive = wid == workstack()->activeWindow(); + bool wasActive = child->widget() == workstack()->activeWindow(); - if ( myBar->indexOf( widgetId( wid ) ) != -1 ) - myBar->removeTab( myBar->indexOf( widgetId( wid ) ) ); + myStack->removeWidget( child ); - myStack->removeWidget( child( wid ) ); + if ( myBar->indexOf( child->id() ) != -1 ) + myBar->removeTab( myBar->indexOf( child->id() ) ); - myList.removeAll( wid ); - myInfo.remove( wid ); - myChild.remove( wid ); + myList.removeAll( child ); if ( del ) { - delete child( wid ); + delete child; if ( myList.isEmpty() ) wasActive = false; } + else if ( child->widget() ) + { + disconnect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) ); + disconnect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) ); + disconnect( child, SIGNAL( hidden( QtxWorkstackChild* ) ), this, SLOT( onChildHidden( QtxWorkstackChild* ) ) ); + disconnect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) ); + disconnect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) ); + } if ( isNull() ) deleteLater(); @@ -543,6 +722,11 @@ void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del ) emit activated( activeWidget() ); } +QList QtxWorkstackArea::childList() const +{ + return myList; +} + /*! \brief Get all visible child widgets. \return list of visible child widgets @@ -550,10 +734,11 @@ void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del ) QWidgetList QtxWorkstackArea::widgetList() const { QWidgetList lst; - for ( QWidgetList::const_iterator it = myList.begin(); it != myList.end(); ++it ) + for ( ChildList::const_iterator it = myList.begin(); it != myList.end(); ++it ) { - if ( widgetVisibility( *it ) ) - lst.append( *it ); + QtxWorkstackChild* c = *it; + if ( c->visibility() ) + lst.append( c->widget() ); } return lst; } @@ -583,26 +768,7 @@ void QtxWorkstackArea::setActiveWidget( QWidget* wid ) */ bool QtxWorkstackArea::contains( QWidget* wid ) const { - return myList.contains( wid ); -} - -/*! - \brief Show/hide workarea. - \param on new visibility state -*/ -void QtxWorkstackArea::setVisible( bool on ) -{ - QMap map; - for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it ) - { - map.insert( *it, isBlocked( *it ) ); - setBlocked( *it, true ); - } - - QFrame::setVisible( on ); - - for ( QWidgetList::iterator itr = myList.begin(); itr != myList.end(); ++itr ) - setBlocked( *itr, map.contains( *itr ) ? map[*itr] : false ); + return child( wid ); } /*! @@ -636,8 +802,7 @@ QtxWorkstack* QtxWorkstackArea::workstack() const QWidget* wid = parentWidget(); while ( wid && !ws ) { - if ( wid->inherits( "QtxWorkstack" ) ) - ws = (QtxWorkstack*)wid; + ws = ::qobject_cast( wid ); wid = wid->parentWidget(); } return ws; @@ -672,6 +837,82 @@ bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e ) return false; } +/*! + \brief Save the own widgets configuration into data stream. +*/ +void QtxWorkstackArea::saveState( QDataStream& stream ) const +{ + stream << QtxWorkstack::AreaMarker; + stream << myList.count(); + stream << myBar->tabId( myBar->currentIndex() ); + for ( ChildList::const_iterator it = myList.begin(); it != myList.end(); ++it ) + { + QtxWorkstackChild* c = *it; + + stream << QtxWorkstack::WidgetMarker; + + stream << c->widget()->objectName(); + stream << c->id(); + + uchar flags = 0; + if ( c->visibility() ) + flags |= QtxWorkstack::Visible; + + stream << flags; + } +} + +/*! + \brief Restore the widgets configuration from data stream info. + \return \c true in successful case. +*/ +bool QtxWorkstackArea::restoreState( QDataStream& stream, QMap& map ) +{ + int num = 0; + int cur = -1; + + stream >> num; + stream >> cur; + + QtxWorkstackChild* curChild = 0; + for ( int i = 0; i < num; i++ ) + { + int marker; + stream >> marker; + + if ( stream.status() != QDataStream::Ok || marker != QtxWorkstack::WidgetMarker ) + return false; + + QString name; + stream >> name; + + int id = -1; + stream >> id; + + uchar flags = 0; + stream >> flags; + + QtxWorkstackChild* c = map.contains( name ) ? map[name] : 0; + if ( !c ) + { + qWarning( "QtxWorkstack: Restored child widget \"%s\" not found.", (const char*)name.toLatin1() ); + return false; + } + + map.remove( name ); + + if ( id == cur ) + curChild = c; + + QApplication::postEvent( this, new RestoreEvent( (QEvent::Type)RestoreWidget, id, flags, c ) ); + } + + if ( curChild ) + QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)MakeCurrent, curChild ) ); + + return true; +} + /*! \brief Get rectangle to be drawn when highlighting drop area. \return area drop rectangle @@ -735,17 +976,30 @@ void QtxWorkstackArea::customEvent( QEvent* e ) if ( activeWidget()->focusWidget()->hasFocus() ) { QFocusEvent in( QEvent::FocusIn ); - QApplication::sendEvent( this, &in ); - } - else { + QApplication::sendEvent( this, &in ); + } + else + { activeWidget()->focusWidget()->setFocus(); - myBar->updateActiveState(); - } + myBar->updateActiveState(); + } } } break; - case RemoveWidget: - removeWidget( we->widget() ); + case MakeCurrent: + if ( we->child()->widget() ) + setActiveWidget( we->child()->widget() ); + break; + case RestoreWidget: + if ( we->child() ) + { + QtxWorkstackChild* c = we->child(); + RestoreEvent* re = (RestoreEvent*)we; + if ( c->widget() ) + c->widget()->setVisible( re->flags() & QtxWorkstack::Visible ); + c->setId( re->id() ); + insertChild( c ); + } break; default: break; @@ -815,19 +1069,7 @@ void QtxWorkstackArea::onDragActiveTab() */ void QtxWorkstackArea::onChildDestroyed( QObject* obj ) { - QtxWorkstackChild* child = (QtxWorkstackChild*)obj; - myStack->removeWidget( child ); - - QWidget* wid = 0; - for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it ) - { - if ( it.value() == child ) - wid = it.key(); - } - - myChild.remove( wid ); - - QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)RemoveWidget, wid ) ); + removeChild( (QtxWorkstackChild*)obj, false ); } /*! @@ -836,7 +1078,7 @@ void QtxWorkstackArea::onChildDestroyed( QObject* obj ) */ void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c ) { - setWidgetShown( c->widget(), true ); + updateState(); } /*! @@ -845,7 +1087,7 @@ void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c ) */ void QtxWorkstackArea::onChildHidden( QtxWorkstackChild* c ) { - setWidgetShown( c->widget(), false ); + updateState(); } /*! @@ -873,19 +1115,9 @@ void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c ) */ void QtxWorkstackArea::updateCurrent() { - QMap map; - for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it ) - { - map.insert( *it, isBlocked( *it ) ); - setBlocked( *it, true ); - } - QWidget* cur = child( widget( myBar->tabId( myBar->currentIndex() ) ) ); if ( cur ) myStack->setCurrentWidget( cur ); - - for ( QWidgetList::iterator itr = myList.begin(); itr != myList.end(); ++itr ) - setBlocked( *itr, map.contains( *itr ) ? map[*itr] : false ); } /*! @@ -909,13 +1141,9 @@ void QtxWorkstackArea::updateTab( QWidget* wid ) */ QWidget* QtxWorkstackArea::widget( const int id ) const { - QWidget* wid = 0; - for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it ) - { - if ( it.value().id == id ) - wid = it.key(); - } - return wid; + QtxWorkstackChild* c = child( id ); + + return c ? c->widget() : 0; } /*! @@ -925,23 +1153,9 @@ QWidget* QtxWorkstackArea::widget( const int id ) const */ int QtxWorkstackArea::widgetId( QWidget* wid ) const { - int id = -1; - if ( myInfo.contains( wid ) ) - id = myInfo[wid].id; - return id; -} + QtxWorkstackChild* c = child( wid ); -/*! - \brief Get child widget's visibility. - \param wid widget - \return \c true if widget is visible -*/ -bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const -{ - bool res = false; - if ( myInfo.contains( wid ) ) - res = myInfo[wid].vis; - return res; + return c ? c->id() : -1; } /*! @@ -957,20 +1171,6 @@ void QtxWorkstackArea::setWidgetActive( QWidget* wid ) myBar->setCurrentIndex( myBar->indexOf( id ) ); } -/*! - \brief Show/hide child widget. - \param wid widget - \param on new visibility state -*/ -void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on ) -{ - if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on ) - return; - - myInfo[wid].vis = on; - updateState(); -} - /*! \brief Update internal state. */ @@ -987,15 +1187,16 @@ void QtxWorkstackArea::updateState() QWidget* prev = activeWidget(); int idx = 0; - for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it ) + for ( ChildList::iterator it = myList.begin(); it != myList.end(); ++it ) { - QWidget* wid = *it; - int id = widgetId( wid ); + QtxWorkstackChild* cont = *it; + QWidget* wid = cont->widget();; + int id = cont->id(); if ( id < 0 ) continue; - bool vis = widgetVisibility( wid ); + bool vis = cont->visibility(); int cIdx = myBar->indexOf( id ); if ( cIdx != -1 && ( !vis || myBar->indexOf( id ) != idx ) ) @@ -1006,11 +1207,6 @@ void QtxWorkstackArea::updateState() updateTab( wid ); - bool block = isBlocked( wid ); - setBlocked( wid, true ); - - QtxWorkstackChild* cont = child( wid ); - if ( !vis ) myStack->removeWidget( cont ); else if ( myStack->indexOf( cont ) < 0 ) @@ -1018,29 +1214,27 @@ void QtxWorkstackArea::updateState() if ( vis ) idx++; - - setBlocked( wid, block ); } int curId = widgetId( prev ); if ( myBar->indexOf( curId ) < 0 ) { - QWidget* wid = 0; - int pos = myList.indexOf( prev ); - for ( int i = pos - 1; i >= 0 && !wid; i-- ) + QtxWorkstackChild* c = 0; + int pos = myList.indexOf( child( prev ) ); + for ( int i = pos - 1; i >= 0 && !c; i-- ) { - if ( widgetVisibility( myList.at( i ) ) ) - wid = myList.at( i ); + if ( myList.at( i )->visibility() ) + c = myList.at( i ); } - for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ ) + for ( int j = pos + 1; j < (int)myList.count() && !c; j++ ) { - if ( widgetVisibility( myList.at( j ) ) ) - wid = myList.at( j ); + if ( myList.at( j )->visibility() ) + c = myList.at( j ); } - if ( wid ) - curId = widgetId( wid ); + if ( c ) + curId = c->id(); } myBar->setCurrentIndex( myBar->indexOf( curId ) ); @@ -1084,8 +1278,8 @@ int QtxWorkstackArea::generateId() const { QMap map; - for ( WidgetInfoMap::const_iterator it = myInfo.begin(); it != myInfo.end(); ++it ) - map.insert( it.value().id, 0 ); + for ( ChildList::const_iterator it = myList.begin(); it != myList.end(); ++it ) + map.insert( (*it)->id(), 0 ); int id = 0; while ( map.contains( id ) ) @@ -1094,29 +1288,6 @@ int QtxWorkstackArea::generateId() const return id; } -/*! - \brief Check if the child wiget is blocked. - \param wid widget - \return \c true if the widget is blocked -*/ -bool QtxWorkstackArea::isBlocked( QWidget* wid ) const -{ - return myBlock.contains( wid ); -} - -/*! - \brief Block widget. - \param wid widget - \param on new blocked state -*/ -void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on ) -{ - if ( on ) - myBlock.insert( wid, 0 ); - else - myBlock.remove( wid ); -} - /*! \brief Get child widget container. \param wid child widget @@ -1125,11 +1296,25 @@ void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on ) QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const { QtxWorkstackChild* res = 0; - if ( myChild.contains( wid ) ) - res = myChild[wid]; + for ( ChildList::const_iterator it = myList.begin(); it != myList.end() && !res; ++it ) + { + if ( (*it)->widget() == wid ) + res = *it; + } return res; } +QtxWorkstackChild* QtxWorkstackArea::child( const int id ) const +{ + QtxWorkstackChild* c = 0; + for ( ChildList::const_iterator it = myList.begin(); it != myList.end() && !c; ++it ) + { + if ( (*it)->id() == id ) + c = *it; + } + return c; +} + /*! \fn void QtxWorkstackArea::activated( QWidget* w ) \brief Emitted when child widget is activated. @@ -1163,15 +1348,23 @@ QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const */ QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent, Qt::WindowFlags f ) : QWidget( parent ), + myId( 0 ), myWidget( wid ) { - myWidget->setParent( this, f ); - myWidget->installEventFilter( this ); - QVBoxLayout* base = new QVBoxLayout( this ); - base->setMargin( 0 ); - base->addWidget( myWidget ); + if ( myWidget ) + { + myWidget->setParent( this, f ); + myWidget->installEventFilter( this ); + if ( myWidget->focusProxy() ) + myWidget->focusProxy()->installEventFilter( this ); + myWidget->setVisible( myWidget->isVisibleTo( myWidget->parentWidget() ) ); + + QVBoxLayout* base = new QVBoxLayout( this ); + base->setMargin( 0 ); + base->addWidget( myWidget ); - connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + } } /*! @@ -1184,11 +1377,13 @@ QtxWorkstackChild::~QtxWorkstackChild() if ( !widget() ) return; - if( widget() ) + if ( widget() ) disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); widget()->hide(); widget()->removeEventFilter( this ); + if ( widget()->focusProxy() ) + widget()->focusProxy()->removeEventFilter( this ); widget()->setParent( 0 ); } @@ -1202,6 +1397,43 @@ QWidget* QtxWorkstackChild::widget() const return myWidget; } +/*! + \brief Returns the id. +*/ +int QtxWorkstackChild::id() const +{ + return myId; +} + +/*! + \brief Sets the id. +*/ +void QtxWorkstackChild::setId( const int id ) +{ + myId = id; +} + +/*! + \brief Returns true if this child window should be visible. +*/ +bool QtxWorkstackChild::visibility() +{ + return myWidget ? myWidget->isVisibleTo( this ) : false; +} + +QtxWorkstackArea* QtxWorkstackChild::area() const +{ + QtxWorkstackArea* a = 0; + QWidget* w = parentWidget(); + while ( !a && w ) + { + a = ::qobject_cast( w ); + w = w->parentWidget(); + } + + return a; +} + /*! \brief Custom event filter. @@ -1236,18 +1468,14 @@ bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e ) */ void QtxWorkstackChild::onDestroyed( QObject* obj ) { - if ( obj != widget() ) - return; - QLayout* lay = layout(); if ( lay ) { - QLayoutItem* item = lay->takeAt( 0 ); + QLayoutItem* item = lay->takeAt( 0 ); if ( item ) lay->removeItem( item ); } - myWidget = 0; deleteLater(); } @@ -1262,7 +1490,7 @@ void QtxWorkstackChild::childEvent( QChildEvent* e ) QLayout* lay = layout(); if ( lay ) { - QLayoutItem* item = lay->takeAt( 0 ); + QLayoutItem* item = lay->takeAt( 0 ); if ( item ) lay->removeItem( item ); } @@ -1309,8 +1537,7 @@ void QtxWorkstackChild::childEvent( QChildEvent* e ) */ QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent ) : QTabBar( parent ), - myActive( false ), - myId( -1 ) + myId( -1 ),myActive(false) { setDrawBase( true ); setElideMode( Qt::ElideNone ); @@ -1495,11 +1722,11 @@ void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool \brief Workstack widget. Organizes the child widgets in the tabbed space. - Allows splitting the working area to arrange the child widgets in + Allows splitting the working area to arrange the child widgets in arbitrary way. Any widgets can be moved to another working area with drag-n-drop operation. - This widget can be used as workspace of the application main window, + This widget can be used as workspace of the application main window, for example, as kind of implementation of multi-document interface. */ @@ -1534,8 +1761,7 @@ QtxWorkstack::QtxWorkstack( QWidget* parent ) QVBoxLayout* base = new QVBoxLayout( this ); base->setMargin( 0 ); - mySplit = new QSplitter( this ); - mySplit->setChildrenCollapsible( false ); + mySplit = new QtxWorkstackSplitter( this ); base->addWidget( mySplit ); } @@ -1547,9 +1773,9 @@ QtxWorkstack::~QtxWorkstack() } /*! - \brief Get list of all widgets in all areas or in specified area which given + \brief Get list of all widgets in all areas or in specified area which given widget belongs to - \param wid widget specifying area if it is equal to null when widgets of all + \param wid widget specifying area if it is equal to null when widgets of all areas are retuned \return list of widgets */ @@ -1560,7 +1786,7 @@ QWidgetList QtxWorkstack::windowList( QWidget* wid ) const { areas( mySplit, lst, true ); } - else + else { QtxWorkstackArea* area = wgArea( wid ); if ( area ) @@ -1679,7 +1905,6 @@ void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType QList allAreas; areas(mySplit, allAreas, true); - for ( QList::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it ) { if ( (*it)->contains( wid ) ) @@ -1689,6 +1914,10 @@ void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType if ( !area ) return; + QWidget* curWid = area->activeWidget(); + if ( !curWid ) + return; + QWidgetList wids = area->widgetList(); if ( wids.count() < 2 ) return; @@ -1722,6 +1951,7 @@ void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType { area->removeWidget( wid_i ); newArea->insertWidget( wid_i ); + wid_i->showMaximized(); } } break; @@ -1735,16 +1965,21 @@ void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType { area->removeWidget( *itr ); newArea->insertWidget( *itr ); + (*itr)->showMaximized(); } } break; case SplitMove: area->removeWidget( wid ); newArea->insertWidget( wid ); + wid->showMaximized(); break; } distributeSpace( trg ); + + curWid->show(); + curWid->setFocus(); } /*! @@ -1784,6 +2019,8 @@ void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all ) if ( !area1 || !area2 ) return; + QSplitter* s1 = splitter( area1 ); + QWidget* curWid = area1->activeWidget(); if ( !curWid ) return; @@ -1795,6 +2032,8 @@ void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all ) // Set wid1 at first position, wid2 at second area1->insertWidget( wid1 ); area1->insertWidget( wid2, 1 ); + wid1->showMaximized(); + wid2->showMaximized(); } else { @@ -1804,6 +2043,7 @@ void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all ) QWidgetList wids1 = area1->widgetList(); for ( QWidgetList::iterator itr1 = wids1.begin(); itr1 != wids1.end() && *itr1 != wid1; ++itr1, ++wid1_ind ); area1->insertWidget( wid2, wid1_ind + 1 ); + wid2->showMaximized(); } } else @@ -1823,6 +2063,7 @@ void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all ) area1->insertWidget( *itr2, wid1_ind + 1 ); else area1->insertWidget( *itr2, ind ); + (*itr2)->showMaximized(); } } else @@ -1830,10 +2071,18 @@ void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all ) // Set wid2 right after wid1 area2->removeWidget( wid2 ); area1->insertWidget( wid2, wid1_ind + 1 ); + wid2->showMaximized(); } } + distributeSpace( s1 ); + area1->setActiveWidget( curWid ); + + wid2->show(); + wid1->setFocus(); + curWid->show(); + curWid->setFocus(); } /*! @@ -2002,8 +2251,8 @@ void QtxWorkstack::setIcon( const int id, const QIcon& icon ) /*! \brief Set actions to be visible in the context popup menu. - - Actions, which IDs are set in \a flags parameter, will be shown in the + + Actions, which IDs are set in \a flags parameter, will be shown in the context popup menu. Other actions will not be shown. \param flags ORed together actions flags @@ -2018,8 +2267,8 @@ void QtxWorkstack::setMenuActions( const int flags ) /*! \brief Set actions to be visible in the context popup menu. - - Actions, which IDs are set in \a flags parameter, will be shown in the + + Actions, which IDs are set in \a flags parameter, will be shown in the context popup menu. Other actions will not be shown. \param flags ORed together actions flags @@ -2367,8 +2616,7 @@ QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area ) QIntList szList = pSplit->sizes(); - QSplitter* wrap = new QSplitter( 0 ); - wrap->setChildrenCollapsible( false ); + QSplitter* wrap = new QtxWorkstackSplitter( 0 ); pSplit->insertWidget( pSplit->indexOf( area ) + 1, wrap ); wrap->setVisible( true ); wrap->addWidget( area ); @@ -2698,7 +2946,7 @@ QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const connect( area, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); connect( area, SIGNAL( activated( QWidget* ) ), this, SLOT( onWindowActivated( QWidget* ) ) ); connect( area, SIGNAL( contextMenuRequested( QWidget*, QPoint ) ), - this, SLOT( onContextMenuRequested( QWidget*, QPoint ) ) ); + this, SLOT( onContextMenuRequested( QWidget*, QPoint ) ) ); connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) ); return area; @@ -2826,348 +3074,133 @@ void QtxWorkstack::updateState( QSplitter* split ) if ( areaList.isEmpty() && splitList.isEmpty() ) delete split; - else if ( vis ) - split->show(); else - split->hide(); + split->setVisible( vis ); } /*! - \brief Get splitter info (for debug purposes) - \param split splitter - \param info string to be filled with splitter data. + \brief Dump workstack configuration to the state description array. + \param version number + \return state byte array. */ -void QtxWorkstack::splitterInfo( QSplitter* split, QString& info ) const +QByteArray QtxWorkstack::saveState( int version ) const { - if ( !split ) - return; - - /*const QObjectList& objs = */split->children(); // VSR: is it needed ??? - - QString sizesStr; - QList sizes = split->sizes(); - for ( QList::iterator sIt = sizes.begin(); sIt != sizes.end(); ++sIt ) - { - if ( *sIt > 1 ) // size 1 pixel usually means empty Workstack area, which will NOT be re-created, - sizesStr += QString( ":%1" ).arg( *sIt ); // so we don't need to store its size - } + QByteArray data; - if ( !sizesStr.isEmpty() ) // cut the first ':' - sizesStr = sizesStr.right( sizesStr.length() - 1 ); + QDataStream stream( &data, QIODevice::WriteOnly ); + stream << QtxWorkstack::VersionMarker; + stream << version; + saveState( stream ); - info += QString( "(splitter orientation=%1 sizes=%3 " ).arg( split->orientation() ).arg( sizesStr ); - - for( int index = 0, count = split->count(); index < count; index++ ) - { - QObject* obj = split->widget( index ); - if ( obj->inherits( "QSplitter" ) ) - splitterInfo( (QSplitter*)obj, info ); - else if ( obj->inherits( "QtxWorkstackArea" ) ) - { - QtxWorkstackArea* area = (QtxWorkstackArea*)obj; - if ( area->isEmpty() ) - continue; - info += QString( "(views active='%1'" ).arg( area->activeWidget()->objectName() ); - QWidgetList views = area->widgetList(); - for ( QWidgetList::iterator wIt = views.begin(); wIt != views.end(); ++wIt ) - info += QString( " '%1'" ).arg( (*wIt)->objectName() ); - info += ')'; - } - } - - info += ')'; - printf( (const char*)QString( info + '\n' ).toLatin1() ); + return data; } /*! - \brief Remove round brackets symbols from the string. - \internal - \param parameters string to be processed + \brief Restore workstack configuration from the state description array. + \param version number + \return restore performing state */ -static void cutBrackets( QString& parameters ) +bool QtxWorkstack::restoreState( const QByteArray& state, int version ) { - QChar c1 = parameters[0]; - QChar c2 = parameters[int(parameters.length()-1)]; - if ( !parameters.isEmpty() && c1 == '(' && c2 == ')' ) - parameters = parameters.mid( 1, parameters.length()-2 ); -} - -/*! - \brief Parse string to get some parameter value. - \internal - - String \a str can contain the parameters description of kind "= ...". - For example: - \code - QString s = "splitter orientation=0 children=2 sizes=332:478"; - QString orient_val = getValue( s, "children" ); // orient_val contains "2" - QString size_val = getValue( s, "sizes" ); // val contains "332:478" - \endcode + if ( state.isEmpty() ) + return false; - \param str string to be processed - \param valName parameter name - \return parameter value (or null QStrinhg if parameter is not found) -*/ -static QString getValue( const QString& str, const QString& valName ) -{ - int i = str.indexOf( valName ); - if ( i != -1 ) - { - int equal_i = str.indexOf( '=', i ); - if ( equal_i != -1 ) - { - int space_i = str.indexOf( ' ', ++equal_i ); - if ( space_i != -1 ) - return str.mid( equal_i, space_i - equal_i ); - } - } - return QString(); -} + QByteArray sd = state; + QDataStream stream( &sd, QIODevice::ReadOnly ); + int marker, ver; + stream >> marker; + stream >> ver; + if ( stream.status() != QDataStream::Ok || marker != QtxWorkstack::VersionMarker || ver != version ) + return false; -/*! - \brief Check format of splitter parameters string. - \internal - \param parameters splitter parameters description - \return \c true on success and \c false on error -*/ -static bool checkFormat( const QString& parameters ) -{ - QString params( parameters ); - // 1. begins and ends with brackets - QChar c1 = params[0]; - QChar c2 = params[int(params.length()-1)]; - bool ok = ( c1 == '(' && c2 == ')' ); - if ( !ok ) return ok; - ::cutBrackets( params ); - // 2. has splitter word - ok = ( params.left( 8 ) == "splitter" ); - if ( !ok ) return ok; - // 3. has children? = '(' is found - int i = params.indexOf( '(' ); - ok = i != -1; - if ( !ok ) return ok; - params = params.left( i ); // cut all children, they will be checked later - // 4. has orientation word and correct value - ::getValue( params, "orientation" ).toInt( &ok ); - if ( !ok ) return ok; - // 5. has sizes word and values - ok = ! ::getValue( params, "sizes" ).isEmpty(); - if ( !ok ) return ok; - // 6. check children -> number of '(' == number of ')' in original string - ok = ( parameters.contains( '(' ) == parameters.contains( ')' ) ); - return ok; + return restoreState( stream ); } -/*! - \brief Get splitter's children descriptions from the string. - \internal - - Child widgets descriptions are separated by '(' and ')' symbols. - - \param str string to be processed - \return child widgets descriptions -*/ -static QStringList getChildren( const QString& str ) +void QtxWorkstack::saveState( QDataStream& stream ) const { - QStringList lst; - if ( !str.startsWith( "(" ) ) - return lst; - - int i = 1, - nOpen = 1, // count brackets: '(' increments nOpen, ')' decrements - start = 0; - while ( i < (int)str.length() ) - { - if ( str[i] == '(' ) - { - nOpen++; - if ( nOpen == 1 ) - start = i; - } - else if ( str[i] == ')' ) - { - nOpen--; - if ( nOpen == 0 ) - lst.append( str.mid( start, i-start+1 ) ); - } - i++; - } - - return lst; + mySplit->saveState( stream ); } -/*! - \brief Get view name by index. - \internal - - Example: - \code - QString s = "views active='AnotherView' 'GLView' 'AnotherView'"; - QString a0 = getViewName( s, 0 ); // --> a0 contains "GLView" - QString a1 = getViewName( s, 1 ); // --> a1 contains "AnotherView" - \endcode - - \param str string to be processed - \param i index - \return view name -*/ -static QString getViewName( const QString& str, int i ) +bool QtxWorkstack::restoreState( QDataStream& stream ) { - QRegExp exp( "\\s'\\w+'" ); - int start = 0; // start index of view name in the string - int num = 0 ; // index of found match - while ( ( start = exp.indexIn( str, start ) ) != -1 && num < i ) + QMap map; + QList areaList; + areas( mySplit, areaList, true ); + for ( QList::const_iterator it = areaList.begin(); it != areaList.end(); ++it ) { - start += exp.matchedLength(); - num ++; - } - if ( start != -1 ) // +2 and -3 avoid starting space and starting and ending ' symbols - return str.mid( start + 2, exp.matchedLength() - 3 ); - - return QString(); -} + QtxWorkstackArea* area = *it; + QList childList = area->childList(); + for ( QList::iterator itr = childList.begin(); itr != childList.end(); ++itr ) + { + QtxWorkstackChild* c = *itr; + if ( !c->widget() ) + continue; -/*! - \brief Get child widget with specified name. - \internal - \param parent parent widget - \param aName child widget name - \return child widget or 0 if not found -*/ -static QWidget* getView( const QWidget* parent, const QString& aName ) -{ - QWidget* view = 0; - QList l = qFindChildren( parent->topLevelWidget(), aName ); - if ( !l.isEmpty() ) - view = ::qobject_cast( l.first() ); - return view; -} + map.insert( c->widget()->objectName(), c ); -/*! - \brief Setup splitter according to the specified parameters string. - \param splitter splitter to be set up - \param parameters splitter parameters description - \param sMap map containing resulting child splitters sizes -*/ -void QtxWorkstack::setSplitter( QSplitter* splitter, const QString& parameters, QMap >& sMap ) -{ - printf( QString( parameters + '\n' ).toLatin1() ); - if ( !::checkFormat( parameters ) ) { - printf( "\nInvalid format of workstack parameters. Positions of viewers can not be restored.\n" ); - return; + qDebug( "QtxWorkstack::restoreState: found widget \"%s\"", (const char*)c->widget()->objectName().toLatin1() ); + } } - QString params( parameters ); - ::cutBrackets( params ); - - // get splitter sizes and store it in the map for future setting - QList sizes; - QStringList sizesLst = ::getValue( params, "sizes" ).split( ':', QString::SkipEmptyParts ); - QStringList::Iterator it; - for ( it = sizesLst.begin(); it != sizesLst.end(); ++it ) - sizes.append( (*it).toInt() ); - sMap[ splitter ] = sizes; + int marker; + stream >> marker; + if ( stream.status() != QDataStream::Ok || marker != QtxWorkstack::SplitMarker ) + return false; - // set orientation of splitter - int orient = ::getValue( params, "orientation" ).toInt(); - splitter->setOrientation( (Qt::Orientation)orient ); + QtxWorkstackSplitter* split = new QtxWorkstackSplitter( this ); + if ( layout() ) + layout()->addWidget( split ); - // get children - QString options = params.left( params.indexOf( '(' ) ); - QString childrenStr = params.right( params.length()-options.length() ); - QStringList children = ::getChildren( childrenStr ); + bool ok = split->restoreState( stream, map ); + if ( !ok ) + delete split; + else + { + mySplit->deleteLater(); + mySplit = split; - // debug output.. - // printf (" splitter orient=%d, sizes_count=%d, children=%d\n", orient, sizes.count(), children.count() ); - // for ( QStringList::Iterator tit = children.begin(); tit != children.end(); ++tit ) - // printf (" |-> child = [%s]\n", (*tit).latin1() ); + QList aList; + areas( mySplit, aList, true ); - for ( it = children.begin(); it != children.end(); ++it ) - { - if ( (*it).startsWith( "(splitter" ) ) + QtxWorkstackArea* a = !aList.isEmpty() ? aList.first() : 0; + for ( QMap::const_iterator it = map.begin(); it != map.end(); ++it ) { - QSplitter* newSplitter = new QSplitter( splitter ); - setSplitter( newSplitter, *it, sMap ); - } - else if ( (*it).startsWith( "(views" ) ) - { - QtxWorkstackArea* newArea = createArea( splitter ); - QString activeViewName = ::getValue( *it, "active" ); - QWidget* activeView = 0; - activeViewName = activeViewName.mid( 1, activeViewName.length()-2 ); // chop off ' symbols - int i = 0; - QString viewName = ::getViewName( *it, i ); - while ( !viewName.isEmpty() ) - { - if ( QWidget* view = ::getView( splitter, viewName ) ) - { - newArea->insertWidget( view ); - if ( activeViewName == view->objectName() ) - activeView = view; - } - viewName = ::getViewName( *it, ++i ); - } - if ( activeView ) - newArea->setActiveWidget( activeView ); + QtxWorkstackChild* c = it.value(); + if ( c->widget() ) + c->widget()->setVisible( false ); + if ( a ) + a->insertChild( c ); + else + c->setVisible( false ); } } + + return ok; } /*! - \brief Restore workstack configuration from the state description string. - \param parameters workstack state description - \return reference to this workstack + \brief Set resize mode of all splitters opaque or transparent. + \param opaque opaque mode */ -QtxWorkstack& QtxWorkstack::operator<<( const QString& parameters ) +void QtxWorkstack::setOpaqueResize( bool opaque ) { - // clear the main splitter - remove all child splitters and empty areas from it QList splitList; - QList areaList; - splitters( mySplit, splitList, false ); - areas( mySplit, areaList, false ); - for ( QList::iterator iter = splitList.begin(); iter != splitList.end(); ++iter ) - delete *iter; - - for ( QList::iterator it = areaList.begin(); it != areaList.end(); ++it ) - { - if ( (*it)->isEmpty() ) - delete *it; - } - - // restore splitter recursively - QMap< QSplitter*, QList > sMap; - setSplitter( mySplit, parameters, sMap ); - - // now mySplit may contains empty area (where all views were located before restoring) - // in order setSize to work correctly we have to exclude this area - areaList.clear(); - areas( mySplit, areaList, false ); - for ( QList::iterator delIt = areaList.begin(); delIt != areaList.end(); ++delIt ) - { - if ( (*delIt)->isEmpty() ) - delete *delIt; - } - - QApplication::instance()->processEvents(); - - // restore splitters' sizes (map of sizes is filled in setSplitters) - for ( QMap< QSplitter*, QList >::iterator itm = sMap.begin(); itm != sMap.end(); ++itm ) - itm.key()->setSizes( itm.value() ); - - return (*this); + splitters( mySplit, splitList, true ); + splitList << mySplit; + foreach( QSplitter* split, splitList ) + split->setOpaqueResize( opaque ); } /*! - \brief Dump workstack configuration to the state description string. - \param parameters resulting workstack state description - \return reference to this workstack + \brief Get resize mode of all splitters: opaque (\c true) or transparent (\c false). + \return current opaque mode */ -QtxWorkstack& QtxWorkstack::operator>>( QString& outParameters ) +bool QtxWorkstack::opaqueResize() const { - splitterInfo( mySplit, outParameters ); - return (*this); + return mySplit->opaqueResize(); } + /*! \fn void QtxWorkstack::windowActivated( QWidget* w ) \brief Emitted when the workstack's child widget \w is activated. @@ -3200,9 +3233,9 @@ QtxWorkstackArea* QtxWorkstack::wgArea( QWidget* wid ) const \brief Moves the first widget to the same area which the second widget belongs to \param wid widget to be moved \param wid_to widget specified the destination area - \param before specifies whether the first widget has to be moved before or after + \param before specifies whether the first widget has to be moved before or after the second widget - \return TRUE if operation is completed successfully, FALSE otherwise + \return TRUE if operation is completed successfully, FALSE otherwise */ bool QtxWorkstack::move( QWidget* wid, QWidget* wid_to, const bool before ) { @@ -3237,7 +3270,7 @@ bool QtxWorkstack::move( QWidget* wid, QWidget* wid_to, const bool before ) /*! \brief Group all windows in one area - \return TRUE if operation is completed successfully, FALSE otherwise + \return TRUE if operation is completed successfully, FALSE otherwise */ void QtxWorkstack::stack() { @@ -3255,13 +3288,19 @@ void QtxWorkstack::stack() area_to = wgArea( *it ); area_src = area_to; } - else + else area_src = wgArea( *it ); if ( area_src != area_to ) { area_src->removeWidget( *it, true ); area_to->insertWidget( *it, -1 ); + (*it)->showMaximized(); } } } + +QAction* QtxWorkstack::action( const int id ) const +{ + return myActionsMap.contains( id ) ? myActionsMap[id] : 0; +} diff --git a/src/Qtx/QtxWorkstack.h b/src/Qtx/QtxWorkstack.h index 431eebf24..80075f059 100644 --- a/src/Qtx/QtxWorkstack.h +++ b/src/Qtx/QtxWorkstack.h @@ -1,24 +1,28 @@ -// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D -// +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either +// License as published by the Free Software Foundation; either // version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // File: QtxWorkstack.h // Author: Sergey TELKOV - +// #ifndef QTXWORKSTACK_H #define QTXWORKSTACK_H @@ -28,22 +32,26 @@ #pragma warning( disable:4251 ) #endif -#include +#include #include -#include #include -#include +#include +#include +#include +#include +#include class QAction; -class QSplitter; -class QStackedWidget; +class QDataStream; class QRubberBand; +class QStackedWidget; class QAbstractButton; class QtxWorkstackArea; class QtxWorkstackDrag; class QtxWorkstackChild; class QtxWorkstackTabBar; +class QtxWorkstackSplitter; class QTX_EXPORT QtxWorkstack : public QWidget { @@ -52,13 +60,23 @@ class QTX_EXPORT QtxWorkstack : public QWidget public: //! Workstack actions (context menu items) enum { SplitVertical = 0x01, //!< "Split vertically" menu item - SplitHorizontal = 0x02, //!< "Split horizontally" menu item - Close = 0x04, //!< "Close" menu item - Rename = 0x08, //!< "Rename" menu item - All = SplitVertical | SplitHorizontal | - Close | Rename //!< all menu items + SplitHorizontal = 0x02, //!< "Split horizontally" menu item + Close = 0x04, //!< "Close" menu item + Rename = 0x08, //!< "Rename" menu item + All = SplitVertical | SplitHorizontal | + Close | Rename //!< all menu items + }; + + enum { VersionMarker = 0x01, + SplitMarker = 0x02, + AreaMarker = 0x04, + WidgetMarker = 0x08 }; - + + enum { Horizontal = 0x01, + Visible = 0x02 + }; + //! Workstack splitting type enum SplitType { @@ -86,28 +104,30 @@ public: void setMenuActions( const int ); int menuActions() const; + void stack(); void split( const int ); bool move( QWidget* wid, QWidget* wid_to, const bool before ); - void stack(); QWidget* addWindow( QWidget*, Qt::WindowFlags = 0 ); + QByteArray saveState( int ) const; + bool restoreState( const QByteArray&, int ); + + void setOpaqueResize( bool = true ); + bool opaqueResize() const; + void Split( QWidget* wid, const Qt::Orientation o, const SplitType type ); void Attract( QWidget* wid1, QWidget* wid2, const bool all ); void SetRelativePosition( QWidget* wid, const Qt::Orientation o, const double pos ); void SetRelativePositionInSplitter( QWidget* wid, const double pos ); - // asv: Store/Restore visual parameters - geometry of inner windows - QtxWorkstack& operator<<( const QString& ); - QtxWorkstack& operator>>( QString& ); - signals: void windowActivated( QWidget* ); public slots: void splitVertical(); void splitHorizontal(); - + private slots: void onRename(); void onCloseWindow(); @@ -119,6 +139,11 @@ private slots: protected: virtual void customEvent( QEvent* ); + QAction* action( const int ) const; + + void saveState( QDataStream& ) const; + bool restoreState( QDataStream& ); + private: QSplitter* splitter( QtxWorkstackArea* ) const; void splitters( QSplitter*, QList&, const bool = false ) const; @@ -143,23 +168,37 @@ private: void updateState( QSplitter* ); void distributeSpace( QSplitter* ) const; + int setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o, - const int need_pos, const int splitter_pos ); - - void splitterInfo( QSplitter*, QString& ) const; - void setSplitter( QSplitter*, const QString&, QMap< QSplitter*, QList >& ); - + const int need_pos, const int splitter_pos ); + private: - QWidget* myWin; //!< active widget - QtxWorkstackArea* myArea; //!< active workarea - QSplitter* mySplit; //!< tol-level splitter - QWidget* myWorkWin; //!< widget where popup menu is invoked (used internally) - QtxWorkstackArea* myWorkArea; //!< workarea where popup menu is invoked (used internally) + QPointer myWin; //!< active widget + QPointer myArea; //!< active workarea + QtxWorkstackSplitter* mySplit; //!< tol-level splitter + QPointer myWorkWin; //!< widget where popup menu is invoked (used internally) + QPointer myWorkArea; //!< workarea where popup menu is invoked (used internally) QMap myActionsMap; //!< actions map friend class QtxWorkstackArea; friend class QtxWorkstackDrag; + friend class QtxWorkstackAction; + friend class QtxWorkstackSplitter; +}; + +class QtxWorkstackSplitter : public QSplitter +{ + Q_OBJECT + +public: + QtxWorkstackSplitter( QWidget* = 0 ); + virtual ~QtxWorkstackSplitter(); + + QtxWorkstack* workstack() const; + + void saveState( QDataStream& ) const; + bool restoreState( QDataStream&, QMap& ); }; class QtxWorkstackArea : public QFrame @@ -167,6 +206,7 @@ class QtxWorkstackArea : public QFrame Q_OBJECT class WidgetEvent; + class RestoreEvent; public: QtxWorkstackArea( QWidget* ); @@ -175,15 +215,19 @@ public: bool isNull() const; bool isEmpty() const; - QWidget* insertWidget( QWidget*, const int = -1, Qt::WindowFlags = 0 ); + QtxWorkstackChild* insertWidget( QWidget*, const int = -1, Qt::WindowFlags = 0 ); void removeWidget( QWidget*, const bool = true ); + void insertChild( QtxWorkstackChild*, const int = -1 ); + void removeChild( QtxWorkstackChild*, const bool = true ); + QWidget* activeWidget() const; void setActiveWidget( QWidget* ); bool contains( QWidget* ) const; QWidgetList widgetList() const; + QList childList() const; bool isActive() const; void updateActiveState(); @@ -197,20 +241,18 @@ public: int tabAt( const QPoint& ) const; + void saveState( QDataStream& ) const; + bool restoreState( QDataStream&, QMap& ); + signals: void activated( QWidget* ); void contextMenuRequested( QWidget*, QPoint ); void deactivated( QtxWorkstackArea* ); -public slots: - virtual void setVisible( bool ); - private slots: void onClose(); void onCurrentChanged( int ); - void onWidgetDestroyed(); - void onChildDestroyed( QObject* ); void onChildShown( QtxWorkstackChild* ); void onChildHidden( QtxWorkstackChild* ); @@ -228,8 +270,9 @@ protected: private: //! Custom events enum { ActivateWidget = QEvent::User, //!< activate widget event - FocusWidget, //!< focus receiving widget event - RemoveWidget //!< widget removing event + FocusWidget, //!< focus receiving widget event + MakeCurrent, + RestoreWidget }; private: @@ -239,38 +282,22 @@ private: QWidget* widget( const int ) const; int widgetId( QWidget* ) const; - bool widgetVisibility( QWidget* ) const; + + QtxWorkstackChild* child( QWidget* ) const; + QtxWorkstackChild* child( const int ) const; void setWidgetActive( QWidget* ); - void setWidgetShown( QWidget*, const bool ); int generateId() const; - bool isBlocked( QWidget* ) const; - void setBlocked( QWidget*, const bool ); - - QtxWorkstackChild* child( QWidget* ) const; - private: - struct WidgetInfo - { - WidgetInfo() : id( 0 ), vis( false ) {} - int id; bool vis; - }; - - typedef QMap BlockMap; - typedef QMap ChildMap; - typedef QMap WidgetInfoMap; + typedef QList ChildList; private: QtxWorkstackTabBar* myBar; //!< workarea tab bar header + ChildList myList; //!< child widgets list QAbstractButton* myClose; //!< close button QStackedWidget* myStack; //!< widget stack - - QWidgetList myList; //!< child widgets list - WidgetInfoMap myInfo; //!< widgets states mp - ChildMap myChild; //!< child widget containers map - BlockMap myBlock; //!< blocked widgets }; class QtxWorkstackChild : public QWidget @@ -281,7 +308,15 @@ public: QtxWorkstackChild( QWidget*, QWidget* = 0, Qt::WindowFlags = 0 ); virtual ~QtxWorkstackChild(); - QWidget* widget() const; + QWidget* widget() const +; + + int id() const; + void setId( const int ); + + bool visibility(); + + QtxWorkstackArea* area() const; virtual bool eventFilter( QObject*, QEvent* ); @@ -298,7 +333,8 @@ protected: virtual void childEvent( QChildEvent* ); private: - QWidget* myWidget; //!< child widget + int myId; //!< id + QPointer myWidget; //!< child widget }; class QtxWorkstackTabBar : public QTabBar @@ -326,13 +362,11 @@ private slots: void onCurrentChanged( int ); protected: + virtual void changeEvent( QEvent* ); virtual void mouseMoveEvent( QMouseEvent* ); virtual void mousePressEvent( QMouseEvent* ); virtual void mouseReleaseEvent( QMouseEvent* ); virtual void contextMenuEvent( QContextMenuEvent* ); - virtual void changeEvent( QEvent* ); - -// virtual void paintLabel( QPainter*, const QRect&, QTab*, bool ) const; private: int myId; //!< current tab page index -- 2.39.2