-// 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.
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
+
// File: QtxWorkstack.cxx
// Author: Sergey TELKOV
-
+//
#include "QtxWorkstack.h"
#include "QtxAction.h"
#include <QRegExp>
#include <QLayout>
#include <QPainter>
-#include <QSplitter>
+#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 ) {};
+
+ 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;
};
/*!
/*!
\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();
}
/*!
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<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;
- 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();
emit activated( activeWidget() );
}
+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 );
+ 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* ) ) );
+ }
}
/*!
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 );
}
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.
*/
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();
}
QLayout* lay = layout();
if ( lay )
{
- QLayoutItem* item = lay->takeAt( 0 );
+ QLayoutItem* item = lay->takeAt( 0 );
if ( item )
lay->removeItem( item );
}
*/
QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
: QTabBar( parent ),
- myActive( false ),
- myId( -1 )
+ myId( -1 ),myActive(false)
{
setDrawBase( true );
setElideMode( Qt::ElideNone );
\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 )
QList<QtxWorkstackArea*> allAreas;
areas(mySplit, allAreas, true);
-
for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it )
{
if ( (*it)->contains( wid ) )
if ( !area )
return;
+ QWidget* curWid = area->activeWidget();
+ if ( !curWid )
+ return;
+
QWidgetList wids = area->widgetList();
if ( wids.count() < 2 )
return;
{
area->removeWidget( wid_i );
newArea->insertWidget( wid_i );
+ wid_i->showMaximized();
}
}
break;
{
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();
}
/*!
if ( !area1 || !area2 )
return;
+ QSplitter* s1 = splitter( area1 );
+
QWidget* curWid = area1->activeWidget();
if ( !curWid )
return;
// Set wid1 at first position, wid2 at second
area1->insertWidget( wid1 );
area1->insertWidget( wid2, 1 );
+ wid1->showMaximized();
+ wid2->showMaximized();
}
else
{
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
area1->insertWidget( *itr2, wid1_ind + 1 );
else
area1->insertWidget( *itr2, ind );
+ (*itr2)->showMaximized();
}
}
else
// 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();
}
/*!
/*!
\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 );
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;
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
-
- 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
+ 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<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 );
-
- return QString();
-}
+ 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;
-/*!
- \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;
-}
+ 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<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" ) )
+ QtxWorkstackArea* a = !aList.isEmpty() ? aList.first() : 0;
+ for ( QMap<QString, QtxWorkstackChild*>::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<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);
+ 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.
\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 )
{
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;
+}
-// 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
#pragma warning( disable:4251 )
#endif
-#include <QWidget>
+#include <QMap>
#include <QFrame>
-#include <QTabBar>
#include <QEvent>
-#include <QMap>
+#include <QWidget>
+#include <QTabBar>
+#include <QPointer>
+#include <QSplitter>
+#include <QByteArray>
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
{
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
{
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();
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> >& );
-
+ 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<QWidget> myWin; //!< active widget
+ QPointer<QtxWorkstackArea> myArea; //!< active workarea
+ QtxWorkstackSplitter* mySplit; //!< tol-level splitter
+ QPointer<QWidget> myWorkWin; //!< widget where popup menu is invoked (used internally)
+ QPointer<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