Back to index

salome-gui  6.5.0
QtxMainWindow.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 //  File:      QtxMainWindow.cxx
00023 //  Author:    Sergey TELKOV
00024 
00025 #include "QtxMainWindow.h"
00026 
00027 #include "QtxToolBar.h"
00028 
00029 #include <QEvent>
00030 #include <QPoint>
00031 #include <QTimer>
00032 #include <QLayout>
00033 #include <QMenuBar>
00034 #include <QStatusBar>
00035 #include <QRubberBand>
00036 #include <QMouseEvent>
00037 #include <QApplication>
00038 #include <QDesktopWidget>
00039 #include <cstdio>
00047 class QtxMainWindow::Filter : public QObject
00048 {
00049 public:
00050   Filter( QWidget*, QtxMainWindow*, QObject* = 0 );
00051   virtual ~Filter();
00052 
00053   virtual bool eventFilter( QObject*, QEvent* );
00054 
00055 private:
00056   QMainWindow* myMain;      
00057   QWidget*     myWidget;    
00058 };
00059 
00066 QtxMainWindow::Filter::Filter( QWidget* wid, QtxMainWindow* mw, QObject* parent )
00067 : QObject( parent ),
00068   myMain( mw ),
00069   myWidget( wid )
00070 {
00071   QApplication::instance()->installEventFilter( this );
00072 };
00073 
00077 QtxMainWindow::Filter::~Filter()
00078 {
00079 }
00080 
00090 bool QtxMainWindow::Filter::eventFilter( QObject* o, QEvent* e )
00091 {
00092   if ( myMain == o && e->type() == QEvent::ChildRemoved &&
00093        myWidget == ((QChildEvent*)e)->child() )
00094     return true;
00095 
00096   return QObject::eventFilter( o, e );
00097 }
00098 
00105 class QtxMainWindow::Resizer : public QObject
00106 {
00107 public:
00108   Resizer( const QPoint&, const Qt::Orientation, QtxMainWindow* );
00109   virtual ~Resizer();
00110 
00111   QMouseEvent*    finalEvent() const;
00112   void            setFinalEvent( QMouseEvent* );
00113 
00114   void            setPosition( const QPoint& );
00115   virtual bool    eventFilter( QObject*, QEvent* );
00116 
00117 private:
00118   void            setFilters( bool );
00119 
00120 private:
00121   QPoint          myPos;
00122   QMainWindow*    myMain;
00123   QRubberBand*    myRubber;
00124   Qt::Orientation myOrient;
00125   QMouseEvent*    myFinEvent;
00126 };
00127 
00132 QtxMainWindow::Resizer::Resizer( const QPoint& p, const Qt::Orientation o, QtxMainWindow* mw )
00133 : QObject( mw ),
00134   myMain( mw ),
00135   myOrient( o ),
00136   myFinEvent( 0 )
00137 {
00138   setFilters( true );
00139 
00140   myRubber = new QRubberBand( QRubberBand::Line, 0 );
00141 
00142   setPosition( p );
00143 
00144   myRubber->hide();
00145 };
00146 
00150 QtxMainWindow::Resizer::~Resizer()
00151 {
00152   delete myRubber;
00153 
00154   setFilters( false );
00155 }
00156 
00157 void QtxMainWindow::Resizer::setPosition( const QPoint& pos )
00158 {
00159   myPos = pos;
00160   if ( myRubber ) {
00161     QRect r;
00162     QPoint min = myMain->mapToGlobal( myMain->rect().topLeft() );
00163     QPoint max = myMain->mapToGlobal( myMain->rect().bottomRight() );
00164     if ( myOrient == Qt::Horizontal ) {
00165       int p = qMax( qMin( myPos.y(), max.y() ), min.y() );
00166       r = QRect( myMain->mapToGlobal( QPoint( 0, 0 ) ).x(), p - 1, myMain->width(), 3 );
00167     }
00168     else {
00169       int p = qMax( qMin( myPos.x(), max.x() ), min.x() );
00170       r = QRect( p - 1, myMain->mapToGlobal( QPoint( 0, 0 ) ).y(), 3, myMain->height() );
00171     }
00172     myRubber->setGeometry( r );
00173     if ( !myRubber->isVisible() )
00174       myRubber->show();
00175   }
00176 }
00177 
00178 QMouseEvent* QtxMainWindow::Resizer::finalEvent() const
00179 {
00180   return myFinEvent;
00181 }
00182 
00183 void QtxMainWindow::Resizer::setFinalEvent( QMouseEvent* e )
00184 {
00185   myFinEvent = e;
00186 }
00187 
00194 bool QtxMainWindow::Resizer::eventFilter( QObject* o, QEvent* e )
00195 {
00196   if ( e->type() == QEvent::Timer ) {
00197     if ( !finalEvent() )
00198       return true;
00199 
00200     setFilters( false );
00201     QApplication::postEvent( myMain, finalEvent() );
00202     myFinEvent = 0;
00203     deleteLater();
00204   }
00205 
00206   return QObject::eventFilter( o, e );
00207 }
00208 
00209 void QtxMainWindow::Resizer::setFilters( bool on )
00210 {
00211   if ( myMain ) {
00212     if ( on )
00213       myMain->layout()->installEventFilter( this );
00214     else
00215       myMain->layout()->removeEventFilter( this );
00216   }
00217 
00218   QTimer* t = qFindChild<QTimer*>( myMain->layout() );
00219   if ( t ) {
00220     if ( on )
00221       t->installEventFilter( this );
00222     else
00223       t->removeEventFilter( this );
00224   }
00225 }
00226 
00238 QtxMainWindow::QtxMainWindow( QWidget* parent, Qt::WindowFlags f )
00239 : QMainWindow( parent, f ),
00240   myMenuBar( 0 ),
00241   myStatusBar( 0 ),
00242   myOpaque( true ),
00243   myResizer( 0 ),
00244   myMouseMove( 0 ),
00245   myFullScreenAllowed(true)
00246 {
00247   //rnv: Enables tooltips for inactive windows.
00248   //rnv: For details see http://bugtracker.opencascade.com/show_bug.cgi?id=20893
00249   setAttribute(Qt::WA_AlwaysShowToolTips);
00250 }
00251 
00255 QtxMainWindow::~QtxMainWindow()
00256 {
00257   setDockableMenuBar( false );
00258   setDockableStatusBar( false );
00259 }
00260 
00265 bool QtxMainWindow::isDockableMenuBar() const
00266 {
00267   return myMenuBar != 0;
00268 }
00269 
00275 void QtxMainWindow::setDockableMenuBar( const bool on )
00276 {
00277   if ( isDockableMenuBar() == on )
00278     return;
00279 
00280   QMenuBar* mb = menuBar();
00281   if ( !mb )
00282     return;
00283 
00284   if ( on && !myMenuBar )
00285   {
00286     myMenuBar = new QtxToolBar( true, this );
00287     new Filter( mb, this, myMenuBar );
00288     myMenuBar->setObjectName( "menu_bar_container" );
00289     myMenuBar->setWindowTitle( tr( "Menu bar" ) );
00290     myMenuBar->addWidget( mb );
00291     myMenuBar->setAllowedAreas( Qt::TopToolBarArea | Qt::BottomToolBarArea );
00292 
00293     addToolBarBreak( Qt::TopToolBarArea );
00294     addToolBar( Qt::TopToolBarArea, myMenuBar );
00295     addToolBarBreak( Qt::TopToolBarArea );
00296 
00297     connect( myMenuBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00298   }
00299   else if ( !on && myMenuBar )
00300   {
00301     setMenuBar( mb );
00302     disconnect( myMenuBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00303     delete myMenuBar;
00304     myMenuBar = 0;
00305   }
00306 }
00307 
00312 bool QtxMainWindow::isDockableStatusBar() const
00313 {
00314   return myStatusBar;
00315 }
00316 
00322 void QtxMainWindow::setDockableStatusBar( const bool on )
00323 {
00324   if ( isDockableStatusBar() == on )
00325     return;
00326 
00327   QStatusBar* sb = statusBar();
00328   if ( !sb )
00329     return;
00330 
00331   if ( on && !myStatusBar )
00332   {
00333     sb->setMinimumWidth( 250 );
00334     sb->setSizeGripEnabled( false );
00335     myStatusBar = new QtxToolBar( true, this );
00336     new Filter( sb, this, myStatusBar );
00337     myStatusBar->setObjectName( "status_bar_container" );
00338     myStatusBar->setWindowTitle( tr( "Status bar" ) );
00339     myStatusBar->addWidget( sb );
00340     myStatusBar->setAllowedAreas( Qt::TopToolBarArea | Qt::BottomToolBarArea );
00341 
00342     addToolBar( Qt::BottomToolBarArea, myStatusBar );
00343 
00344     connect( myStatusBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00345   }
00346   else if ( !on && myStatusBar )
00347   {
00348     setStatusBar( sb );
00349     disconnect( myStatusBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00350     delete myStatusBar;
00351     myStatusBar = 0;
00352 
00353     sb->setSizeGripEnabled( true );
00354   }
00355 }
00356 
00357 bool QtxMainWindow::isOpaqueResize() const
00358 {
00359   return myOpaque;
00360 }
00361 
00362 void QtxMainWindow::setOpaqueResize( bool on )
00363 {
00364   myOpaque = on;
00365 }
00366 
00371 QString QtxMainWindow::storeGeometry() const
00372 {
00373   QRect frame = frameGeometry();
00374   QRect screen = QApplication::desktop()->availableGeometry( this );
00375 
00376   QString x;
00377   if ( frame.left() == screen.left() )
00378     x = QString( "+0" );
00379   else if ( frame.right() == screen.right() )
00380     x = QString( "-0" );
00381   else
00382     x = QString( "+%1" ).arg( frame.left() );
00383 
00384   QString y;
00385   if ( frame.top() == screen.top() )
00386     y = QString( "+0" );
00387   else if ( frame.bottom() == screen.bottom() )
00388     y = QString( "-0" );
00389   else
00390     y = QString( "+%1" ).arg( frame.top() );
00391 
00392   QString geom = QString( "%1x%2%3%4" ).arg( width() ).arg( height() ).arg( x ).arg( y );
00393 
00394   QString state;
00395   switch ( windowState() )
00396   {
00397   case Qt::WindowMaximized:
00398     state = QString( "max" );
00399     break;
00400   case Qt::WindowMinimized:
00401     state = QString( "min" );
00402     break;
00403   case Qt::WindowFullScreen:
00404     state = isFullScreenAllowed() ? QString( "full" ) : QString( "max" );
00405     break;
00406   }
00407 
00408   if ( !state.isEmpty() )
00409     geom += QString( ":" ) + state;
00410 
00411   return geom;
00412 }
00413 
00418 void QtxMainWindow::retrieveGeometry( const QString& str )
00419 {
00420   QString geom = str;
00421   geom.remove( '\t' );
00422   geom.remove( ' ' );
00423 
00424   QRect rect = geometry();
00425   QRect screen = QApplication::desktop()->availableGeometry( this );
00426 
00427   QRegExp szRx( "(\\d+%?)\\s*x\\s*(\\d+%?)" );
00428   if ( szRx.indexIn( geom ) != -1 )
00429   {
00430     int w = -1;
00431     bool wp = false;
00432     int ws = geometryValue( szRx.cap( 1 ).trimmed(), w, wp );
00433     bool wOk = ws != 0;
00434     if ( wOk && wp )
00435       w = screen.width() * qMax( qMin( w, 100 ), 0 ) / 100;
00436     wOk = wOk && w;
00437 
00438     int h = -1;
00439     bool hp = false;
00440     int hs = geometryValue( szRx.cap( 2 ).trimmed(), h, hp );
00441     bool hOk = hs != 0;
00442     if ( hOk && hp )
00443       h = screen.height() * qMax( qMin( h, 100 ), 0 ) / 100;
00444     hOk = hOk && h;
00445 
00446     if ( wOk && hOk )
00447       rect.setSize( QSize( w, h ) );
00448   }
00449 
00450   QRegExp posRx( "([+|-]\\d+%?)\\s*([+|-]\\d+%?)" );
00451   if ( posRx.indexIn( geom ) != -1 )
00452   {
00453     int x = -1;
00454     bool xp = false;
00455     int xs = geometryValue( posRx.cap( 1 ).trimmed(), x, xp );
00456     bool xOk = xs != 0;
00457     if ( xOk )
00458     {
00459       if ( xp )
00460        x = screen.width() * qMax( qMin( x, 100 ), 0 ) / 100;
00461       x = ( xs > 0 ? x : screen.right() - x - rect.width() ) + frameGeometry().x() - geometry().x();
00462     }
00463 
00464     int y = -1;
00465     bool yp = false;
00466     int ys = geometryValue( posRx.cap( 2 ).trimmed(), y, yp );
00467     bool yOk = ys != 0;
00468     if ( yOk )
00469     {
00470       if ( yp )
00471        y = screen.height() * qMax( qMin( y, 100 ), 0 ) / 100;
00472       y = ( ys > 0 ? y : screen.bottom() - y - rect.height() ) + frameGeometry().y() - geometry().y();
00473     }
00474 
00475     if ( xOk && yOk )
00476       rect.moveTo( x, y );
00477   }
00478 
00479   Qt::WindowState state = Qt::WindowNoState;
00480 
00481   QRegExp stRx( ":(\\w+)" );
00482   if ( stRx.indexIn( geom ) != -1 )
00483   {
00484     QString stStr = stRx.cap( 1 ).trimmed().toLower();
00485     if ( stStr.startsWith( QString( "max" ) ) )
00486       state = Qt::WindowMaximized;
00487     else if ( stStr.startsWith( QString( "min" ) ) )
00488       state = Qt::WindowMinimized;
00489     else if ( stStr.startsWith( QString( "full" ) ) )
00490       state = Qt::WindowFullScreen;
00491   }
00492 
00493   resize( rect.size() );
00494   move( rect.topLeft() );
00495 
00496   if ( state != Qt::WindowNoState )
00497     setWindowState( state );
00498 }
00499 
00513 int QtxMainWindow::geometryValue( const QString& str, int& num, bool& percent ) const
00514 {
00515   num = -1;
00516   int res = 1;
00517   QString numStr = str;
00518   if ( numStr.startsWith( "+" ) || numStr.startsWith( "-" ) )
00519   {
00520     res = numStr.startsWith( "+" ) ? 1 : -1;
00521     numStr = numStr.mid( 1 );
00522   }
00523 
00524   percent = numStr.endsWith( "%" );
00525   if ( percent )
00526     numStr = numStr.mid( 0, numStr.length() - 1 );
00527 
00528   bool ok = false;
00529   num = numStr.toInt( &ok );
00530   if ( !ok )
00531     res = 0;
00532 
00533   return res;
00534 }
00535 
00543 void QtxMainWindow::onDestroyed( QObject* obj )
00544 {
00545   QObject* o = 0;
00546   if ( obj == myMenuBar )
00547   {
00548     myMenuBar = 0;
00549     o = menuBar();
00550   }
00551   else if ( obj == myStatusBar )
00552   {
00553     myStatusBar = 0;
00554     o = statusBar();
00555   }
00556 
00557   if ( o )
00558   {
00559     QChildEvent ce( QEvent::ChildRemoved, o );
00560     QApplication::sendEvent( this, &ce );
00561   }
00562 }
00563 
00564 bool QtxMainWindow::event( QEvent* e )
00565 {
00566 //   if ( e->type() == QEvent::WindowDeactivate ) {
00567 //     printf( "----------------> Deactivated\n" );
00568 //   }
00569 
00570   if ( myResizer ) {
00571     QMouseEvent* me = static_cast<QMouseEvent*>( e );
00572     if ( ( e->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton ) || 
00573         ( e->type() == QEvent::MouseButtonPress && me->button() != Qt::LeftButton ) ) {
00574       if ( me->button() == Qt::LeftButton ) {
00575        if ( myMouseMove ) {
00576          QMainWindow::event( myMouseMove );
00577          delete myMouseMove;
00578          myMouseMove = 0;
00579        }
00580 
00581        QMouseEvent* me = static_cast<QMouseEvent*>( e );
00582        myResizer->setFinalEvent( new QMouseEvent( QEvent::MouseButtonRelease, me->pos(), me->globalPos(),
00583                                              Qt::LeftButton, me->buttons(), me->modifiers() ) );
00584        myResizer = 0;
00585        return true;
00586       }
00587     }
00588   }
00589 
00590   if ( myResizer && e->type() == QEvent::MouseMove ) {
00591     QMouseEvent* me = static_cast<QMouseEvent*>( e );
00592     if ( myMouseMove )
00593       delete myMouseMove;
00594     myMouseMove = new QMouseEvent( me->type(), me->pos(), me->globalPos(),
00595                                    me->button(), me->buttons(), me->modifiers() );
00596     myResizer->setPosition( me->globalPos() );
00597   }
00598 
00599   bool ok = QMainWindow::event( e );
00600 
00601   if ( !myResizer && e->type() == QEvent::MouseButtonPress ) {
00602     QMouseEvent* me = static_cast<QMouseEvent*>( e );
00603     if ( !isOpaqueResize() && ok && testAttribute( Qt::WA_SetCursor ) && me->button() == Qt::LeftButton ) {
00604       bool status = true;
00605       Qt::Orientation o;
00606       switch ( cursor().shape() )
00607        {
00608        case Qt::SplitHCursor:
00609          o = Qt::Vertical;
00610          break;
00611        case Qt::SplitVCursor:
00612          o = Qt::Horizontal;
00613          break;
00614        default:
00615          status = false;
00616          break;
00617        }
00618       if ( status ) {
00619        myResizer = new Resizer( me->globalPos(), o, this );
00620        myMouseMove = new QMouseEvent( me->type(), me->pos(), me->globalPos(),
00621                                    me->button(), me->buttons(), me->modifiers() );
00622       }
00623     }
00624   }
00625 
00626   return ok;
00627 }
00628 
00634 bool QtxMainWindow::isFullScreenAllowed() const {
00635   return myFullScreenAllowed;
00636 }
00637 
00638 
00644 void QtxMainWindow::setFullScreenAllowed( const bool f ) {
00645     myFullScreenAllowed = f;
00646 }