#include <QRegExp>
#include <QLayout>
#include <QPainter>
-#include <QSplitter>
+#include <QByteArray>
+#include <QDataStream>
#include <QFocusEvent>
#include <QMouseEvent>
#include <QRubberBand>
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 ) {};
- QWidget* widget() const { return myWidget; }
+ QtxWorkstackChild* child() const { return myChild; }
private:
- QWidget* myWidget; // event receiver widget
+ 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 ) {};
+
+ int id() const { return myId; }
+ int flags() const { return myFlags; }
+
+private:
+ int myId;
+ int myFlags;
};
/*!
/*!
\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 );
}
/*!
{
ensurePolished();
int dim = 0;
- if( !icon().isNull() )
+ if( !icon().isNull() )
{
const QPixmap pm = icon().pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ),
QIcon::Normal );
\return minimum size value
*/
QSize CloseButton::minimumSizeHint() const
-{
- return sizeHint();
+{
+ return sizeHint();
}
/*!
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<QtxWorkstack*>( 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<int> sz = sizes();
+ for ( QList<int>::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<QtxWorkstackSplitter*>( wid );
+ if ( split )
+ split->saveState( stream );
+ else
+ {
+ QtxWorkstackArea* area = ::qobject_cast<QtxWorkstackArea*>( 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<QString, QtxWorkstackChild*>& map )
+{
+ int num = 0;
+ uchar flags = 0;
+
+ stream >> flags;
+ stream >> num;
+
+ setOrientation( flags & QtxWorkstack::Horizontal ? Qt::Horizontal : Qt::Vertical );
+
+ QList<int> 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
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;
}
\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* ) ) );
updateState();
- setWidgetActive( wid );
- wid->setFocus();
-
- return myChild[wid];
+ setWidgetActive( child->widget() );
+ child->widget()->setFocus();
}
/*!
}
/*!
- \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;
- if ( myBar->indexOf( widgetId( wid ) ) != -1 )
- myBar->removeTab( myBar->indexOf( widgetId( wid ) ) );
+ if ( myBar->indexOf( child->id() ) != -1 )
+ myBar->removeTab( myBar->indexOf( child->id() ) );
- myStack->removeWidget( child( wid ) );
+ myStack->removeWidget( child );
- myList.removeAll( wid );
- myInfo.remove( wid );
- myChild.remove( wid );
+ myList.removeAll( child );
if ( del )
- delete child( wid );
+ delete child;
+ 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();
updateState();
}
+QList<QtxWorkstackChild*> QtxWorkstackArea::childList() const
+{
+ return myList;
+}
+
/*!
\brief Get all visible child widgets.
\return list of visible child widgets
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;
}
*/
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<QWidget*, bool> 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 );
}
/*!
QWidget* wid = parentWidget();
while ( wid && !ws )
{
- if ( wid->inherits( "QtxWorkstack" ) )
- ws = (QtxWorkstack*)wid;
+ ws = ::qobject_cast<QtxWorkstack*>( wid );
wid = wid->parentWidget();
}
return ws;
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<QString, QtxWorkstackChild*>& 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
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;
*/
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 );
}
/*!
*/
void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
{
- setWidgetShown( c->widget(), true );
+ updateState();
}
/*!
*/
void QtxWorkstackArea::onChildHidden( QtxWorkstackChild* c )
{
- setWidgetShown( c->widget(), false );
+ updateState();
}
/*!
*/
void QtxWorkstackArea::updateCurrent()
{
- QMap<QWidget*, bool> 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 );
}
/*!
*/
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;
}
/*!
*/
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;
}
/*!
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.
*/
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 ) )
updateTab( wid );
- bool block = isBlocked( wid );
- setBlocked( wid, true );
-
- QtxWorkstackChild* cont = child( wid );
-
if ( !vis )
myStack->removeWidget( cont );
else if ( myStack->indexOf( cont ) < 0 )
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 ) );
{
QMap<int, int> 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 ) )
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
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.
*/
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 );
+ myWidget->setVisible( myWidget->isVisibleTo( myWidget->parentWidget() ) );
- connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+ QVBoxLayout* base = new QVBoxLayout( this );
+ base->setMargin( 0 );
+ base->addWidget( myWidget );
+
+ connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+ }
}
/*!
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<QtxWorkstackArea*>( w );
+ w = w->parentWidget();
+ }
+
+ return a;
+}
+
/*!
\brief Custom event filter.
\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.
*/
QVBoxLayout* base = new QVBoxLayout( this );
base->setMargin( 0 );
- mySplit = new QSplitter( this );
- mySplit->setChildrenCollapsible( false );
+ mySplit = new QtxWorkstackSplitter( this );
base->addWidget( mySplit );
}
}
/*!
- \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
*/
{
areas( mySplit, lst, true );
}
- else
+ else
{
QtxWorkstackArea* area = wgArea( wid );
if ( area )
/*!
\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
/*!
\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
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 );
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<int> sizes = split->sizes();
- for ( QList<int>::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
+ if ( state.isEmpty() )
+ return false;
- String \a str can contain the parameters description of kind "<param>=<value> ...".
- 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
+ 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;
- \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();
+ return restoreState( stream );
}
-/*!
- \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;
-}
-
-/*!
- \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<QString, QtxWorkstackChild*> map;
+ QList<QtxWorkstackArea*> areaList;
+ areas( mySplit, areaList, true );
+ for ( QList<QtxWorkstackArea*>::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 );
+ QtxWorkstackArea* area = *it;
+ QList<QtxWorkstackChild*> childList = area->childList();
+ for ( QList<QtxWorkstackChild*>::iterator itr = childList.begin(); itr != childList.end(); ++itr )
+ {
+ QtxWorkstackChild* c = *itr;
+ if ( !c->widget() )
+ continue;
- return QString();
-}
+ map.insert( c->widget()->objectName(), c );
-/*!
- \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<QWidget*> l = qFindChildren<QWidget*>( parent->topLevelWidget(), aName );
- if ( !l.isEmpty() )
- view = ::qobject_cast<QWidget*>( l.first() );
- return view;
-}
-
-/*!
- \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<QSplitter*, QList<int> >& 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<int> 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<QtxWorkstackArea*> aList;
+ areas( mySplit, aList, true );
- for ( it = children.begin(); it != children.end(); ++it )
- {
- if ( (*it).startsWith( "(splitter" ) )
- {
- QSplitter* newSplitter = new QSplitter( splitter );
- setSplitter( newSplitter, *it, sMap );
- }
- else if ( (*it).startsWith( "(views" ) )
+ QtxWorkstackArea* a = !aList.isEmpty() ? aList.first() : 0;
+ for ( QMap<QString, QtxWorkstackChild*>::const_iterator it = map.begin(); it != map.end(); ++it )
{
- 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 );
}
}
-}
-
-/*!
- \brief Restore workstack configuration from the state description string.
- \param parameters workstack state description
- \return reference to this workstack
-*/
-QtxWorkstack& QtxWorkstack::operator<<( const QString& parameters )
-{
- // clear the main splitter - remove all child splitters and empty areas from it
- QList<QSplitter*> splitList;
- QList<QtxWorkstackArea*> areaList;
- splitters( mySplit, splitList, false );
- areas( mySplit, areaList, false );
- for ( QList<QSplitter*>::iterator iter = splitList.begin(); iter != splitList.end(); ++iter )
- delete *iter;
-
- for ( QList<QtxWorkstackArea*>::iterator it = areaList.begin(); it != areaList.end(); ++it )
- {
- if ( (*it)->isEmpty() )
- delete *it;
- }
-
- // restore splitter recursively
- QMap< QSplitter*, QList<int> > 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<QtxWorkstackArea*>::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<int> >::iterator itm = sMap.begin(); itm != sMap.end(); ++itm )
- itm.key()->setSizes( itm.value() );
-
- return (*this);
-}
-
-/*!
- \brief Dump workstack configuration to the state description string.
- \param parameters resulting workstack state description
- \return reference to this workstack
-*/
-QtxWorkstack& QtxWorkstack::operator>>( QString& outParameters )
-{
- splitterInfo( mySplit, outParameters );
- return (*this);
+ return ok;
}
/*!
\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 )
{
/*!
\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()
{
area_to = wgArea( *it );
area_src = area_to;
}
- else
+ else
area_src = wgArea( *it );
if ( area_src != area_to )
}
}
}
+
+QAction* QtxWorkstack::action( const int id ) const
+{
+ return myActionsMap.contains( id ) ? myActionsMap[id] : 0;
+}
#include "Qtx.h"
-#include <QWidget>
+#include <QMap>
#include <QFrame>
-#include <QTabBar>
#include <QEvent>
-#include <QMap>
+#include <QWidget>
+#include <QTabBar>
+#include <QPointer>
+#include <QSplitter>
class QAction;
-class QSplitter;
-class QStackedWidget;
+class QByteArray;
+class QDataStream;
class QRubberBand;
+class QStackedWidget;
class QAbstractButton;
class QtxWorkstackArea;
class QtxWorkstackDrag;
class QtxWorkstackChild;
class QtxWorkstackTabBar;
+class QtxWorkstackSplitter;
#ifdef WIN32
#pragma warning( disable:4251 )
SplitHorizontal = 0x02, //!< "Split horizontally" menu item
Close = 0x04, //!< "Close" menu item
Rename = 0x08, //!< "Rename" menu item
- All = SplitVertical | SplitHorizontal |
+ 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
{
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 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();
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<QSplitter*>&, const bool = false ) const;
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<int> >& );
-
+
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)
+ QWidget* myWin; //!< active widget
+ QtxWorkstackArea* myArea; //!< active workarea
+ QtxWorkstackSplitter* mySplit; //!< tol-level splitter
+ QWidget* myWorkWin; //!< widget where popup menu is invoked (used internally)
+ QtxWorkstackArea* myWorkArea; //!< workarea where popup menu is invoked (used internally)
QMap<int, QAction*> 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<QString, QtxWorkstackChild*>& );
};
class QtxWorkstackArea : public QFrame
Q_OBJECT
class WidgetEvent;
+ class RestoreEvent;
public:
QtxWorkstackArea( QWidget* );
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<QtxWorkstackChild*> childList() const;
bool isActive() const;
void updateActiveState();
int tabAt( const QPoint& ) const;
+ void saveState( QDataStream& ) const;
+ bool restoreState( QDataStream&, QMap<QString, QtxWorkstackChild*>& );
+
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* );
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:
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<QWidget*, bool> BlockMap;
- typedef QMap<QWidget*, QtxWorkstackChild*> ChildMap;
- typedef QMap<QWidget*, WidgetInfo> WidgetInfoMap;
+ typedef QList<QtxWorkstackChild*> 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
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* );
virtual void childEvent( QChildEvent* );
private:
- QWidget* myWidget; //!< child widget
+ int myId; //!< id
+ QPointer<QWidget> myWidget; //!< child widget
};
class QtxWorkstackTabBar : public QTabBar
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
: QObject(),
myApp( app )
{
-}
+}
/*!
Destructor.
Sets names of all view windows in given list. This is used
in order to apply the same naming algorithm when saving and restoring
view windows. Names of view windows must be the same before saving
- workstack (splitters) information, and before its restoring!
+ workstack (splitters) information, and before its restoring!
Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
VTKViewer_0_0
OCCViewer_0_0 OCCViewer_0_1 OCCViewer_0_2
*/
void nameViewWindows( const ViewManagerList& lst )
{
- QMultiHash<QString,int> viewersCounter; // map viewerType - to - index_of_this_viewer_type
- QListIterator<SUIT_ViewManager*> it(lst);
- SUIT_ViewManager* aVM = 0;
- while ( it.hasNext() ) {
- aVM = it.next();
- if ( !aVM ) continue;
+ QMap<QString, int> viewersCounter;
+ for ( QList<SUIT_ViewManager*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
+ {
+ SUIT_ViewManager* aVM = *it;
+ if ( !aVM )
+ continue;
int view_count = aVM->getViewsCount();
QString vType = aVM->getType();
if ( !view_count )
continue; //No views is opened in the viewer
-
- int viewerID = viewersCounter.value( vType );
- if ( !viewerID ) {
- viewerID = 0;
- viewersCounter.insert( vType, viewerID );
- }
- else
- ++viewerID;
+
+ if ( !viewersCounter.contains( vType ) )
+ viewersCounter.insert( vType, 0 );
+
+ int& viewerID = viewersCounter[vType];
QVector<SUIT_ViewWindow*> views = aVM->getViews();
- for ( int i = 0; i < view_count; i++ ) {
+ for ( int i = 0; i < view_count; i++ )
+ {
QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( viewerID ).arg( i );
views[i]->setObjectName( vName );
}
+ viewerID++;
}
- viewersCounter.clear();
}
/*!
int savePoint = 1;
std::vector<int> savePoints = study->getSavePoints();
//Calculate a new savePoint number = the last save point number + 1
- if ( savePoints.size() > 0)
+ if ( savePoints.size() > 0)
savePoint = savePoints[savePoints.size()-1] + 1;
_PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName(), savePoint );
ViewManagerList lst;
myApp->viewManagers( lst );
- // setting unique names for view windows in order to save this view inside
+ // setting unique names for view windows in order to save this view inside
// workstack's structure (see below). On restore the views with the same names will
// be placed to the same place inside the workstack's splitters.
nameViewWindows( lst );
// store active window's name
- SUIT_ViewWindow* win = myApp->desktop()->activeWindow();
+ SUIT_ViewWindow* win = myApp->desktop()->activeWindow();
if ( win )
ip->setProperty("AP_ACTIVE_VIEW", win->objectName().toStdString() );
if ( !vm ) continue;
int view_count = vm->getViewsCount();
- if ( !view_count )
+ if ( !view_count )
continue; //No views is opened in the viewer
-
+
std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).toStdString();
ip->append("AP_VIEWERS_LIST", viewerEntry);
-
+
QVector<SUIT_ViewWindow*> views = vm->getViews();
for(int i = 0; i<view_count; i++) {
ip->append( viewerEntry, views[i]->windowTitle().toStdString() );
}
//Save information about split areas
- if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
- QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
+ if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
+ {
QString workstackInfo;
- (*workstack) >> workstackInfo;
- ip->setProperty( "AP_WORKSTACK_INFO", workstackInfo.toStdString() );
+ QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
+ QByteArray geomState = workstack->saveState( 0 );
+ ip->setProperty( "AP_WORKSTACK_INFO", QString( geomState.toHex() ).toStdString() );
}
-
+
//Save a name of the active module
- if ( CAM_Module* activeModule = myApp->activeModule() )
+ if ( CAM_Module* activeModule = myApp->activeModule() )
ip->setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().toStdString() );
//Store visual parameters of the modules
- QList<CAM_Module*> mlist;
+ QList<CAM_Module*> mlist;
myApp->modules( mlist );
QListIterator<CAM_Module*> itM( mlist );
CAM_Module* module = 0;
// set default name of new savePoint
study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );
-
+
return savePoint;
}
qApp->installEventFilter( this );
//Remove all already existent veiwers and their views
- ViewManagerList lst;
- myApp->viewManagers( lst );
- QListIterator<SUIT_ViewManager*> it(lst);
- while ( it.hasNext() ) {
- myApp->removeViewManager( it.next() );
- qApp->processEvents();
- }
+ myApp->clearViewManagers();
+
//Restore the viewers and view windows
int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
SUIT_ViewWindow* viewWin = 0;
// parameters of view windows are stored in a map for restoring after restoring of the workstack
QMap<SUIT_ViewWindow*, QString> viewersParameters;
-
- for ( int i = 0; i < nbViewers; i++ ) {
+
+ for ( int i = 0; i < nbViewers; i++ )
+ {
std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
std::string type = veiewerParams[0];
std::string viewerID = veiewerParams[1];
SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
- if ( !vm )
+ if ( !vm )
continue; //Unknown viewer
-
+
int nbViews = (ip->nbValues(viewerEntry))/2;
-
+
//Create nbViews-1 view (-1 because 1 view is created by createViewManager)
- for ( int i = 1; i< nbViews; i++ ) {
+ for ( int i = 1; i< nbViews; i++ )
+ {
SUIT_ViewWindow* aView = vm->createViewWindow();
aView->show();
}
int viewCount = vm->getViewsCount();
- if (viewCount != nbViews) {
+ if ( viewCount != nbViews )
+ {
printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
continue;
}
//Resize the views, set their captions and apply visual parameters.
- QVector<SUIT_ViewWindow*> views = vm->getViews();
- for (int i = 0, j = 0; i<viewCount; i++, j+=2) {
+ QVector<SUIT_ViewWindow*> views = vm->getViews();
+ for ( int i = 0, j = 0; i<viewCount; i++, j+=2 )
+ {
viewWin = views[i];
- if ( !viewWin )
+ if ( !viewWin )
continue;
// wait untill the window is really shown. This step fixes MANY bugs..
- while ( !vm->isVisible() )
- qApp->processEvents();
-
- viewWin->setWindowTitle(ip->getValue(viewerEntry, j).c_str());
-
+ // while ( !vm->isVisible() )
+ // qApp->processEvents();
+
+ viewWin->setWindowTitle( ip->getValue( viewerEntry, j ).c_str() );
+
// printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
- viewersParameters[ viewWin ] = ip->getValue(viewerEntry, j+1).c_str();
+ viewersParameters[ viewWin ] = ip->getValue( viewerEntry, j + 1 ).c_str();
//viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
}
}
// restore modules' visual parameters
- std::vector<std::string> v = ip->getValues("AP_MODULES_LIST");
- for ( int i = 0; i < v.size(); i++ ) {
+ std::vector<std::string> v = ip->getValues( "AP_MODULES_LIST" );
+ for ( int i = 0; i < v.size(); i++ )
+ {
myApp->activateModule( v[i].c_str() );
if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
module->restoreVisualParameters( savePoint );
// new view windows may have been created in module->restoreVisualParameters() [GAUSS]
// so here we store their visual parameters for later restoring..
- lst.clear();
- myApp->viewManagers(lst);
- QListIterator<SUIT_ViewManager*> itVM( lst );
- SUIT_ViewManager* aVM = 0;
- while ( itVM.hasNext() ) {
- aVM = itVM.next();
- if ( !aVM ) continue;
+ QList<SUIT_ViewManager*> lst;
+ myApp->viewManagers( lst );
+ for ( QList<SUIT_ViewManager*>::iterator itVM = lst.begin(); itVM != lst.end(); ++itVM )
+ {
+ SUIT_ViewManager* aVM = *itVM;
+ if ( !aVM )
+ continue;
int view_count = aVM->getViewsCount();
QVector<SUIT_ViewWindow*> views = aVM->getViews();
- for ( int i = 0; i < view_count; i++ ) {
- if ( !viewersParameters.contains( views[i] ) ) {
+ for ( int i = 0; i < view_count; i++ )
+ {
+ if ( !viewersParameters.contains( views[i] ) )
+ {
viewersParameters[ views[i] ] = views[i]->getVisualParameters();
// printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
}
}
- }
+ }
// activate module that was active on save
QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
- if ( !activeModuleName.isEmpty() )
+ if ( !activeModuleName.isEmpty() )
myApp->activateModule( activeModuleName );
- // setting unique names for view windows in order to restore positions of view windows inside
- // workstack's structure (see below). During save the same naming algorithm was used,
+ // setting unique names for view windows in order to restore positions of view windows inside
+ // workstack's structure (see below). During save the same naming algorithm was used,
// so the same views will get the same names.
nameViewWindows( lst );
+ qApp->processEvents();
+
// restore workstack parameters. should be done after module's restoreVisualParameters(), because
// some modules can create their own viewers (like VISU creates GaussViewers)
- if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
+ if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
+ {
QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
- (*workstack) << ip->getProperty( "AP_WORKSTACK_INFO" ).c_str();
+ workstack->restoreState( QByteArray::fromHex( QByteArray( ip->getProperty( "AP_WORKSTACK_INFO" ).c_str() ) ), 0 );
}
// restore visual parameters of view windows. it must be done AFTER restoring workstack.
}
qApp->removeEventFilter( this );
-
+
// for ( it.toFirst(); it.current(); ++it ) {
// int view_count = it.current()->getViewsCount();
// QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
aType == QEvent::KeyPress ||
aType == QEvent::KeyRelease )
return true;
-
+
return QObject::eventFilter( o, e );
}