Salome HOME
Merge changes from 'master' branch.
[modules/gui.git] / src / Qtx / QtxGroupBox.cxx
index 801c3a599e2d605867252568839c4ea36e4d2614..25a66d417124025c119546b7f9f1773721e6882e 100644 (file)
-// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-// 
+// Copyright (C) 2007-2016  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 
-// but WITHOUT ANY WARRANTY; without even the implied warranty of 
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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/
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 // File:      QtxGroupBox.cxx
 // Author:    Sergey TELKOV
-
+//
 #include "QtxGroupBox.h"
 
-#include <qhbox.h>
-#include <qlayout.h>
-#include <qtoolbutton.h>
-#include <qapplication.h>
-#include <qobjectlist.h>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QEvent>
+#include <QObjectList>
+#include <QApplication>
 
 /*!
-  Constructor
-*/
-QtxGroupBox::QtxGroupBox( QWidget* parent, const char* name )
-: QGroupBox( parent, name ),
-myContainer( 0 )
-{
-}
+  \class QtxGroupBox
+  \brief Enhanced group box widget.
 
-/*!
-  Constructor
+  The QtxGroupBox class allows inserting custom widgets in the 
+  group box title. Use insertTitleWidget() method to add
+  custom widget to the title and removeTitleWidget() to remove it.
 */
-QtxGroupBox::QtxGroupBox( const QString& title, QWidget* parent, const char* name )
-: QGroupBox( title, parent, name ),
-myContainer( 0 )
-{
-  initialize();
-}
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param parent parent widget 
 */
-QtxGroupBox::QtxGroupBox( int strips, Orientation o, QWidget* parent, const char* name )
-: QGroupBox( strips, o, parent, name ),
-myContainer( 0 )
+QtxGroupBox::QtxGroupBox( QWidget* parent )
+: QGroupBox( parent ),
+  myContainer( 0 )
 {
   initialize();
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param title group box title text
+  \param parent parent widget 
 */
-QtxGroupBox::QtxGroupBox( int strips, Orientation o, const QString& title,
-                                          QWidget* parent, const char* name )
-: QGroupBox( strips, o, title, parent, name ),
-myContainer( 0 )
+QtxGroupBox::QtxGroupBox( const QString& title, QWidget* parent )
+: QGroupBox( title, parent ),
+  myContainer( 0 )
 {
   initialize();
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxGroupBox::~QtxGroupBox()
 {
-  delete myContainer;
 }
 
 /*!
-  Creates horizontal box as container
+  \brief Initialize the group box.
+
+  Creates horizontal box as container for title widgets.
 */
 void QtxGroupBox::initialize()
 {
-  myContainer = new QHBox( this, 0, WStyle_Customize | WStyle_NoBorderEx | WStyle_Tool );
+  myContainer = new QWidget( this );
+  QHBoxLayout* base = new QHBoxLayout( myContainer );
+  base->setMargin( 0 );
+  base->setSpacing( 0 );
 
   updateTitle();
 }
 
-#if QT_VER < 3
-
-/*!
-  \return the width of the empty space between the items in the group and the frame of the group
-*/
-int QtxGroupBox::insideMargin() const
-{
-  int m = 0;
-  if ( layout() )
-    m = layout()->margin();
-  return m;
-}
-
-/*!
-  \return the width of the empty space between each of the items in the group
-*/
-int QtxGroupBox::insideSpacing() const
-{
-  int s = 0;
-  if ( layout() )
-    s = layout()->spacing();
-  return s;
-}
-
-/*!
-  Sets the width of the empty space between the items in the group and the frame of the group
-*/
-void QtxGroupBox::setInsideMargin( int m )
-{
-  if ( layout() )
-    layout()->setMargin( m );
-}
-
-/*!
-  Sets the width of the empty space between each of the items in the group
-*/
-void QtxGroupBox::setInsideSpacing( int s )
-{
-  if ( layout() )
-    layout()->setSpacing( s );
-}
-
-#endif
-
 /*!
-  Inserts title widget
-  \param wid - new title widget
+  \brief Add widget to the group box title.
+  \param wid widget being added to the title
 */
 void QtxGroupBox::insertTitleWidget( QWidget* wid )
 {
   if ( !myContainer )
     return;
 
-  wid->reparent( myContainer, QPoint( 0, 0 ), true );
+  myContainer->layout()->addWidget( wid );
   wid->installEventFilter( this );
 
   updateTitle();
 }
 
 /*!
-  Removes title widget
-  \param wid - title widget
+  \brief Remove widget from the group box title.
+  \param wid widget to be removed from the title
 */
 void QtxGroupBox::removeTitleWidget( QWidget* wid )
 {
   if ( !myContainer || wid->parentWidget() != myContainer )
     return;
 
-  wid->reparent( 0, QPoint( 0, 0 ), false );
+  myContainer->layout()->removeWidget( wid );
+  wid->setParent( 0 );
   wid->removeEventFilter( this );
+  wid->hide();
 
   updateTitle();
 }
 
 /*!
-  Calculates margin
-*/
-void QtxGroupBox::adjustInsideMargin()
-{
-  QApplication::sendPostedEvents( myContainer, QEvent::ChildInserted );
-
-  myContainer->resize( myContainer->minimumSizeHint() );
-
-  setInsideMargin( myContainer->height() );
-}
-
-/*!
-  Sets the alignment of the group box title
+  \brief Show/hide group box.
+  \param on if \c true, show group box, otherwise, hide it
 */
-void QtxGroupBox::setAlignment( int align )
+void QtxGroupBox::setVisible( bool on )
 {
-  QGroupBox::setAlignment( align );
+  if ( on )
+    updateTitle();
 
-  updateTitle();
+  QGroupBox::setVisible( on );
 }
 
 /*!
-  Sets title of groop box
+  \brief Get recommended size for the widget.
+  \return recommended size for the widget
 */
-void QtxGroupBox::setTitle( const QString& title )
+QSize QtxGroupBox::sizeHint() const
 {
-  QGroupBox::setTitle( title );
-
-  updateTitle();
+  return expandTo( QGroupBox::sizeHint() );
 }
 
 /*!
-  Changes the layout of the group box
-  \param strips - number of column/rows
-  \param o - orientation
+  \brief Get recommended minimum size for the widget.
+  \return recommended minimum size for the widget
 */
-void QtxGroupBox::setColumnLayout( int strips, Orientation o )
+QSize QtxGroupBox::minimumSizeHint() const
 {
-  if ( myContainer )
-    myContainer->reparent( 0, QPoint( 0, 0 ), false );
-
-  QGroupBox::setColumnLayout( strips, o );
-
-  if ( myContainer )
-    myContainer->reparent( this, QPoint( 0, 0 ), false );
-
-  updateTitle();
+  return expandTo( QGroupBox::minimumSizeHint() );
 }
 
 /*!
-  Shows group box
+  \brief Custom event filter.
+  \param obj event receiver
+  \param e event
+  \return \c true if event processing should be stopped
 */
-void QtxGroupBox::show()
+bool QtxGroupBox::eventFilter( QObject* obj, QEvent* e )
 {
-  QGroupBox::show();
+  QEvent::Type type = e->type();
+  if ( myContainer && obj->parent() == myContainer &&
+       ( type == QEvent::Show || type == QEvent::ShowToParent ||
+         type == QEvent::Hide || type == QEvent::HideToParent ) )
+    QApplication::postEvent( this, new QEvent( QEvent::User ) );
 
-  updateTitle();
+  return QGroupBox::eventFilter( obj, e );
 }
-
 /*!
-  Updates group box
+  \brief Get central widget (or first found one).
+  \return widget
 */
-void QtxGroupBox::update()
+QWidget* QtxGroupBox::widget() const
 {
-  QGroupBox::update();
+  if ( !layout() )
+    return 0;
 
-  updateTitle();
+  QWidget* w = 0;
+  for ( int i = 0; i < (int)layout()->count() && !w; i++ )
+    w = layout()->itemAt( i )->widget();
+  return w;
 }
 
 /*!
-  \return the recommended size for the widget
+  \brief Set central widget to the group box.
+  \param wid widget being added to the group box
 */
-QSize QtxGroupBox::sizeHint() const
+void QtxGroupBox::setWidget( QWidget* wid )
 {
-  QSize sz = QGroupBox::sizeHint();
-
-  int sw = titleSize().width();
-
-  if ( myContainer )
-  {
-    if ( alignment() == AlignCenter )
-      sw += 2 * ( myContainer->width() + 5 );
-    else
-      sw += 1 * ( myContainer->width() + 5 );
-  }
-
-  sw += frameRect().left();
-
-  return QSize( QMAX( sz.width(), sw ), sz.height() );
-}
-
-/*!
-  \return the recommended minimum size for the widget
-*/
-QSize QtxGroupBox::minimumSizeHint() const
-{
-  QSize sz = QGroupBox::minimumSizeHint();
+  QWidget* w = widget();
+  if ( w == wid )
+    return;
 
-  int sw = titleSize().width() + myContainer ? myContainer->width() + 5 : 0;
+  if ( layout() )
+    layout()->removeWidget( w );
 
-  if ( myContainer )
+  if ( !wid )
+    delete layout();
+  else if ( !layout() )
   {
-    if ( alignment() == AlignCenter )
-      sw += 2 * ( myContainer->width() + 5 );
-    else
-      sw += 1 * ( myContainer->width() + 5 );
+    QLayout* bl = new QVBoxLayout( this );
+    bl->setMargin( 0 );
+    bl->setSpacing( 0 );
   }
 
-  sw += frameRect().left();
-
-  return QSize( QMAX( sz.width(), sw ), sz.height() );
-}
-
-/*!
-  Custom event filter
-*/
-bool QtxGroupBox::eventFilter( QObject* obj, QEvent* e )
-{
-  QEvent::Type type = e->type();
-  if ( myContainer && obj->parent() == myContainer &&
-       ( type == QEvent::Show || type == QEvent::ShowToParent ||
-         type == QEvent::Hide || type == QEvent::HideToParent ) )
-    QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
+  if ( layout() )
+    layout()->addWidget( wid );
 
-  return QGroupBox::eventFilter( obj, e );
+  if ( wid )
+    wid->updateGeometry();
 }
 
 /*!
-  Custom resize event filter
+  \brief Customize resize event.
+  \param e resize event
 */
 void QtxGroupBox::resizeEvent( QResizeEvent* e )
 {
@@ -298,56 +219,38 @@ void QtxGroupBox::resizeEvent( QResizeEvent* e )
 }
 
 /*!
-  Custom child event filter
+  \brief Customize child event.
+  \param e child event
 */
 void QtxGroupBox::childEvent( QChildEvent* e )
 {
-  if ( e->type() == QEvent::ChildInserted && e->child() == myContainer )
+/*
+  if ( e->type() == QEvent::ChildAdded && e->child() == myContainer )
     return;
-
-  QGroupBox::childEvent( e );
-}
-
-/*!
-  Event filter of custom items
 */
-void QtxGroupBox::customEvent( QCustomEvent* )
-{
-  updateTitle();
+  QGroupBox::childEvent( e );
 }
 
 /*!
-  On frame changed
+  \brief Process custom events.
+  \param e custom event (not used)
 */
-void QtxGroupBox::frameChanged()
+void QtxGroupBox::customEvent( QEvent* /*e*/ )
 {
   updateTitle();
 }
 
 /*!
-  \return size of title
+  \brief Get the group box title size.
+  \return title size
 */
 QSize QtxGroupBox::titleSize() const
 {
-  QSize sz( 0, 0 );
-
-  if ( layout() )
-  {
-    QSpacerItem* si = 0;
-    for ( QLayoutIterator it = layout()->iterator(); it.current() && !si; ++it )
-      si = it.current()->spacerItem();
-    if ( si )
-      sz = si->sizeHint();
-  }
-
-  int w = sz.width();
-  int h = sz.height() + insideMargin();
-
-  return QSize( w, h );
+  return QSize( fontMetrics().width( title() ), fontMetrics().height() );
 }
 
 /*!
-  Updates title
+  \brief Update the group box title.
 */
 void QtxGroupBox::updateTitle()
 {
@@ -355,53 +258,92 @@ void QtxGroupBox::updateTitle()
     return;
 
   int align = alignment();
-  if ( align == AlignAuto )
-    align = QApplication::reverseLayout() ? AlignRight : AlignLeft;
 
   if ( title().isEmpty() )
-    align = AlignRight;
+    align = Qt::AlignRight;
 
   QSize ts = titleSize();
 
   int m = 5;
 
-  int w = frameRect().width() - ts.width();
-  if ( align == AlignCenter )
+  int w = width() - ts.width();
+  if ( align == Qt::AlignCenter )
     w = w / 2;
 
   w -= m;
 
-  QApplication::sendPostedEvents( myContainer, QEvent::ChildInserted );
   myContainer->resize( myContainer->minimumSizeHint() );
 
   bool vis = false;
-  const QObjectList* list = myContainer->children();
-  if ( list )
-  {
-    for ( QObjectListIt it( *list ); it.current() && !vis; ++it )
-      vis = it.current()->isWidgetType() &&
-            ((QWidget*)it.current())->isVisibleTo( myContainer );
-  }
+  const QObjectList list = myContainer->children();
+  for ( QObjectList::const_iterator it = list.begin(); it != list.end() && !vis; ++it )
+    vis = (*it)->isWidgetType() && ((QWidget*)(*it))->isVisibleTo( myContainer );
 
-  if ( myContainer->height() > ts.height() || myContainer->width() > w || !vis )
+  if ( !vis )
     myContainer->hide();
   else
   {
     int x = 0;
-    if ( align == AlignRight )
-      x = frameRect().left() + m;
+    if ( align == Qt::AlignRight )
+      x = rect().left() + m;
     else
-      x = frameRect().right() - myContainer->width() - m;
+      x = rect().right() - myContainer->width() - m;
 
-    int y = frameRect().top() - ( myContainer->height() - frameWidth() ) / 2;
+    int y = rect().top() - ( myContainer->height() - ts.height() ) / 2;
 
-    QPoint pos( x, QMAX( 0, y ) );
-    pos = mapToGlobal( pos );
-    if ( myContainer->parentWidget() )
-      pos = myContainer->parentWidget()->mapFromGlobal( pos );
+    QPoint pos( x, qMax( 0, y ) );
     myContainer->move( pos );
     myContainer->show();
   }
 
+  if ( layout() )
+  {
+    if ( myContainer && myContainer->isVisibleTo( this ) )
+      setInsideMargin( qMax( 0, myContainer->height() - ts.height() ) );
+    else
+      setInsideMargin( 0 );
+  }
+
   updateGeometry();
 }
+
+/*!
+  \brief Expand group box to the specified size.
+  \param sz new size
+*/
+QSize QtxGroupBox::expandTo( const QSize& sz ) const
+{
+  int sh = 0;
+  int sw = titleSize().width();
+  if ( myContainer && myContainer->isVisibleTo( (QWidget*)this ) )
+  {
+    if ( alignment() == Qt::AlignCenter )
+      sw += 2 * ( myContainer->width() + 5 );
+    else
+      sw += 1 * ( myContainer->width() + 5 );
+    sw += 20;
+    sh = myContainer->height() + 5;
+  }
+  return QSize( qMax( sz.width(), sw ), qMax( sz.height(), sh ) );
+}
+
+/*!
+  \brief Set group box's inside margin size.
+  \param m new inside margin size
+*/
+void QtxGroupBox::setInsideMargin( const int m )
+{
+  QVBoxLayout* bl = ::qobject_cast<QVBoxLayout*>( layout() );
+
+  if ( !bl )
+    return;
+
+  QSpacerItem* spacer = 0;
+  if ( bl->count() )
+    spacer = bl->itemAt( 0 )->spacerItem();
+
+  if ( !spacer )
+    bl->insertSpacing( 0, m );
+  else
+    spacer->changeSize( 0, m );
+}