From: nds Date: Wed, 8 Oct 2008 03:31:53 +0000 (+0000) Subject: Merging GUI_SRC module with the BR_V5_DEV branch. X-Git-Tag: TG_mergeto_BR_V5_DEV_finished~4 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=97738d7facaac435d7afe1e3b052fb36d49f87ff;p=modules%2Fgui.git Merging GUI_SRC module with the BR_V5_DEV branch. --- diff --git a/src/Event/Event.h b/src/Event/Event.h new file mode 100755 index 000000000..db337d428 --- /dev/null +++ b/src/Event/Event.h @@ -0,0 +1,37 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// 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 +// 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#if !defined ( EVENT_H ) +#define EVENT_H + +#ifdef WIN32 +# ifdef EVENT_EXPORTS +# define EVENT_EXPORT __declspec(dllexport) +# else +# define EVENT_EXPORT __declspec(dllimport) +# endif +#else //WIN32 +# define EVENT_EXPORT +#endif //WIN32 + +#if defined WIN32 +#pragma warning ( disable: 4251 ) +#endif + +#endif // EVENT_H diff --git a/src/Event/Event.pro b/src/Event/Event.pro new file mode 100644 index 000000000..c8087357d --- /dev/null +++ b/src/Event/Event.pro @@ -0,0 +1,24 @@ +TEMPLATE = lib +TARGET = Event +DESTDIR = ../../$(CONFIG_ID)/lib +MOC_DIR = ../../moc +OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET + +INCLUDEPATH += ../../include +LIBS += + +CONFIG -= debug release debug_and_release +CONFIG += qt thread debug dll shared + +win32:DEFINES += WIN32 +DEFINES += EVENT_EXPORTS + +HEADERS = Event.h +HEADERS += SALOME_Event.h + +SOURCES = SALOME_Event.cxx + +includes.files = $$HEADERS +includes.path = ../../include + +INSTALLS += includes diff --git a/src/Event/SALOME_Event.cxx b/src/Event/SALOME_Event.cxx new file mode 100755 index 000000000..c48945f6e --- /dev/null +++ b/src/Event/SALOME_Event.cxx @@ -0,0 +1,243 @@ +// KERNEL SALOME_Event : Define event posting mechanism +// +// Copyright (C) 2003 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 +// 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 +// 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 : SALOME_Event.cxx +// Author : Sergey ANIKIN + +#include "SALOME_Event.h" + +#include +#include + +// asv 21.02.05 : introducing multi-platform approach of thread comparison +// - on Unix using pthread_t type for storing ThreadId +// - on Win32 using integer type for storing ThreadId +// NOT using integer ThreadId on both Unix and Win32 because (from documentation): +// "...Do not allow your program to rely on the internal structure or size of the pthread_t..." + +#ifdef WIN32 +#include +static DWORD myThread; +#else +#include +static pthread_t myThread; +#endif + +/*! + \class SALOME_CustomEvent + \brief Generic event class for user-defined events + + This class contains a generic void* data member that may be used + for transferring event-specific data to the receiver. + + \warning The internal data is not destroyed by the class destructor. +*/ + +/*! + \brief Constructor. + \param type event type +*/ +SALOME_CustomEvent::SALOME_CustomEvent( int type ) +: QEvent( (QEvent::Type)type ), d( 0 ) +{ +} + +/*! + \brief Constructor. + \param type event type + \param data custom data +*/ +SALOME_CustomEvent::SALOME_CustomEvent( QEvent::Type type, void* data ) +: QEvent( type ), d( data ) +{ +} + +/*! + \brief Get custom data. + \return pointer to the internal data +*/ +void* SALOME_CustomEvent::data() const +{ + return d; +} + +/*! + \brief Set custom data. + \param data pointer to the internal data +*/ +void SALOME_CustomEvent::setData( void* data ) +{ + d = data; +} + +/*! + \class SALOME_Event + \brief The class which encapsulates data and functionality required for + posting component-specific events to perform arbitrary operations + in the main GUI thread. + + SALOME_Event objects can be posted by any thread belonging to the GUI process. + + It is necessary to derive a custom event class from SALOME_Event and + re-implement virtual Execute() method. This method should actually perform + the desirable operation. To pass all the required data to Execute() and + store a return value, arbitrary data fields can be added to the custom + event class. There is no need to protect such fields with a mutex, for only + one thread working with a SALOME_Event object is active at any moment. + + Usage: + - Create SALOME_Event. Components can derive their own event class from + SALOME_Event in order to pass custom data to the event handler. + - Call process() method to post the event. After process() execution + it is possible to examine fields of your custom event object. + - Perform delete operator on the event to wake up the desktop (you can also + set parameter to \c true to automatically wake up desktop after + process(). + + The method processed() is used by the desktop to signal that event processing + has been completed. + + To make all this work, it is necessary to call static method GetSessionThread() + during the application initialization, i.e. from main() function. + It is important to call this method from the primary application thread. + + Caveats: + - there are no. +*/ + +//! Total number of semaphore resources +const int NumberOfResources = 2; + +/*! + \brief Initialize event mechanism. + + This function sets up the main application thread. It should be called + during the application initialization, i.e. main() function. +*/ +void SALOME_Event::GetSessionThread(){ +#ifdef WIN32 + myThread = ::GetCurrentThreadId(); +#else + myThread = pthread_self(); +#endif +} + +/*! + \brief Check if the processing is in the main application thread. + \return \c true if this method is called from the main application thread +*/ +bool SALOME_Event::IsSessionThread(){ + bool aResult = false; +#ifdef WIN32 + aResult = myThread == ::GetCurrentThreadId(); +#else + aResult = myThread == pthread_self(); +#endif + return aResult; +} + +/*! + \brief Constructor. +*/ +SALOME_Event::SALOME_Event(){ + // Prepare the semaphore + mySemaphore = new QSemaphore( NumberOfResources ); + mySemaphore->acquire( NumberOfResources ); +} + +/*! + \brief Destructor. +*/ +SALOME_Event::~SALOME_Event(){ + if ( mySemaphore->available() < NumberOfResources ) + mySemaphore->release( NumberOfResources - mySemaphore->available() ); + delete mySemaphore; +} + +/*! + \brief Post the event and wait for its completion. + \sa processed() +*/ +void SALOME_Event::process() +{ + QApplication::postEvent( qApp, new SALOME_CustomEvent( SALOME_EVENT, (void*)this ) ); + mySemaphore->acquire( 1 ); +} + +/*! + \brief Use this method to signal that this event has been processed. +*/ +void SALOME_Event::processed() +{ + mySemaphore->release( 1 ); +} + +/*! + \fn virtual void SALOME_Event::Execute(); + \brief This method should be redefined in the successor classes + to do real work. +*/ + +/*! + \class TMemFunEvent + \brief Template class for event which calls the function + without arguments and returning result. +*/ + +/*! + \class TVoidMemFunEvent + \brief Template class for event which calls the function + without arguments and without return value. +*/ + +/*! + \class TMemFun1ArgEvent + \brief Template class for event which calls the function + with one argument and returning result. +*/ + +/*! + \class TVoidMemFun1ArgEvent + \brief Template class for event which calls the function + with one argument and without return value. +*/ + +/*! + \class TMemFun2ArgEvent + \brief Template class for event which calls the function + with two arguments and returning result. +*/ + +/*! + \class TVoidMemFun2ArgEvent + \brief Template class for event which calls the function + with two arguments and without return value. +*/ + +/*! + \fn ProcessEvent + \brief Template function for processing events with return value. +*/ + +/*! + \fn ProcessVoidEvent + \brief Template function for processing events without return value. +*/ diff --git a/src/Event/SALOME_Event.h b/src/Event/SALOME_Event.h new file mode 100644 index 000000000..c44cc6d54 --- /dev/null +++ b/src/Event/SALOME_Event.h @@ -0,0 +1,229 @@ +// KERNEL SALOME_Event : Define event posting mechanism +// +// Copyright (C) 2003 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 +// 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 +// 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 : SALOME_Event.h +// Author : Sergey ANIKIN + +#ifndef SALOME_EVENT_H +#define SALOME_EVENT_H + +#include + +#include + +//! SALOME custom event type +#define SALOME_EVENT QEvent::Type( QEvent::User + 10000 ) + +class EVENT_EXPORT SALOME_CustomEvent : public QEvent +{ +public: + SALOME_CustomEvent( int type ); + SALOME_CustomEvent( QEvent::Type type, void* data ); + + void* data() const; + void setData( void* data ); + +private: + void *d; //!< internal data +}; + +class QSemaphore; + +class EVENT_EXPORT SALOME_Event +{ +public: + SALOME_Event(); + virtual ~SALOME_Event(); + + virtual void Execute() = 0; + + static bool IsSessionThread(); + void process(); + +protected: + void processed(); + friend class SalomeApp_EventFilter; + + static void GetSessionThread(); + friend int main(int, char **); + +private: + QSemaphore* mySemaphore; //!< internal semaphore +}; + +template class TMemFunEvent : public SALOME_Event +{ +public: + typedef TRes TResult; + TResult myResult; + typedef TResult (TObject::* TAction)(); + TMemFunEvent(TObject* theObject, TAction theAction, + TResult theResult = TResult()): + myObject(theObject), + myAction(theAction), + myResult(theResult) + {} + virtual void Execute() + { + myResult = (myObject->*myAction)(); + } +private: + TObject* myObject; + TAction myAction; +}; + +template class TVoidMemFunEvent : public SALOME_Event +{ +public: + typedef void (TObject::* TAction)(); + TVoidMemFunEvent(TObject* theObject, TAction theAction): + myObject(theObject), + myAction(theAction) + {} + virtual void Execute() + { + (myObject->*myAction)(); + } +private: + TObject* myObject; + TAction myAction; +}; + +template +class TMemFun1ArgEvent : public SALOME_Event +{ +public: + typedef TRes TResult; + TResult myResult; + typedef TResult (TObject::* TAction)(TArg); + TMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg, + TResult theResult = TResult()): + myObject(theObject), + myAction(theAction), + myResult(theResult), + myArg(theArg) + {} + virtual void Execute() + { + myResult = (myObject->*myAction)(myArg); + } +private: + TObject* myObject; + TAction myAction; + TStoreArg myArg; +}; + +template +class TVoidMemFun1ArgEvent : public SALOME_Event +{ +public: + typedef void (TObject::* TAction)(TArg); + TVoidMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg): + myObject(theObject), + myAction(theAction), + myArg(theArg) + {} + virtual void Execute() + { + (myObject->*myAction)(myArg); + } +private: + TObject* myObject; + TAction myAction; + TStoreArg myArg; +}; + +template +class TMemFun2ArgEvent: public SALOME_Event +{ +public: + typedef TRes TResult; + TResult myResult; + typedef TResult (TObject::* TAction)(TArg,TArg1); + TMemFun2ArgEvent(TObject* theObject, TAction theAction, + TArg theArg, TArg1 theArg1, + TResult theResult = TResult()): + myObject(theObject), + myAction(theAction), + myResult(theResult), + myArg(theArg), + myArg1(theArg1) + {} + virtual void Execute() + { + myResult = (myObject->*myAction)(myArg,myArg1); + } +private: + TObject* myObject; + TAction myAction; + TStoreArg myArg; + TStoreArg1 myArg1; +}; + +template +class TVoidMemFun2ArgEvent : public SALOME_Event +{ +public: + typedef void (TObject::* TAction)(TArg,TArg1); + TVoidMemFun2ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1): + myObject(theObject), + myAction(theAction), + myArg(theArg), + myArg1(theArg1) + {} + virtual void Execute() + { + (myObject->*myAction)(myArg,myArg1); + } +private: + TObject* myObject; + TAction myAction; + TStoreArg myArg; + TStoreArg1 myArg1; +}; + +template inline typename TEvent::TResult ProcessEvent(TEvent* theEvent) +{ + typename TEvent::TResult aResult; + if(SALOME_Event::IsSessionThread()) { + theEvent->Execute(); + aResult = theEvent->myResult; + } + else { + theEvent->process(); + aResult = theEvent->myResult; + } + delete theEvent; + return aResult; +} + +inline void ProcessVoidEvent(SALOME_Event* theEvent) +{ + if(SALOME_Event::IsSessionThread()) { + theEvent->Execute(); + } + else { + theEvent->process(); + } + delete theEvent; +} + +#endif // SALOME_EVENT_H diff --git a/src/Qtx/QtxActionSet.cxx b/src/Qtx/QtxActionSet.cxx index da8d7630d..916ce7ec8 100644 --- a/src/Qtx/QtxActionSet.cxx +++ b/src/Qtx/QtxActionSet.cxx @@ -1,17 +1,17 @@ // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D -// +// // 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 @@ -212,7 +212,7 @@ void QtxActionSet::clear() /*! \brief Called when action is changed. - + Update action state. */ void QtxActionSet::onChanged() @@ -363,6 +363,9 @@ void QtxActionSet::updateAction( QWidget* w ) for ( ActionList::iterator it = mySet.begin(); it != mySet.end(); ++it ) w->removeAction( *it ); + if ( !w->actions().contains( this ) ) + return; + QAction* first = 0; for ( int i = 0; i < mySet.count(); i++ ) { diff --git a/src/Qtx/QtxDockWidget.cxx b/src/Qtx/QtxDockWidget.cxx index fd6f00371..fde9657d5 100644 --- a/src/Qtx/QtxDockWidget.cxx +++ b/src/Qtx/QtxDockWidget.cxx @@ -43,7 +43,12 @@ public: virtual bool eventFilter( QObject*, QEvent* ); + bool isEmpty() const; + bool isVisible() const; + protected: + enum { Update = QEvent::User, Remove }; + virtual void customEvent( QEvent* ); private: @@ -56,11 +61,15 @@ private: void updateCaption(); void updateVisibility(); + void setEmpty( const bool ); + void setVisible( const bool ); + private: QtxDockWidget* myCont; bool myState; bool myEmpty; - bool myVisible; + bool myBlock; + bool myShown; }; /*! @@ -70,12 +79,14 @@ private: QtxDockWidget::Watcher::Watcher( QtxDockWidget* cont ) : QObject( cont ), myCont( cont ), myState( true ), - myEmpty( false ) + myEmpty( false ), + myBlock( false ) { myCont->installEventFilter( this ); - myVisible = myCont->isVisibleTo( myCont->parentWidget() ); installFilters(); + + myShown = myCont->isVisibleTo( myCont->parentWidget() ); } /*! @@ -90,7 +101,6 @@ bool QtxDockWidget::Watcher::eventFilter( QObject* o, QEvent* e ) e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) { installFilters(); - QApplication::postEvent( this, new QEvent( QEvent::User ) ); } if ( o == myCont && e->type() == QEvent::ChildAdded ) @@ -99,7 +109,7 @@ bool QtxDockWidget::Watcher::eventFilter( QObject* o, QEvent* e ) if ( ce->child()->isWidgetType() ) ce->child()->installEventFilter( this ); - QApplication::postEvent( this, new QEvent( QEvent::User ) ); + QApplication::postEvent( this, new QEvent( (QEvent::Type)Update ) ); } if ( o != myCont && e->type() == QEvent::WindowIconChange ) @@ -108,11 +118,14 @@ bool QtxDockWidget::Watcher::eventFilter( QObject* o, QEvent* e ) if ( o != myCont && e->type() == QEvent::WindowTitleChange ) updateCaption(); - if ( ( o != myCont && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) || - ( o == myCont && ( e->type() == QEvent::ChildRemoved ) ) || - ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) ) + if ( o != myCont && ( e->type() == QEvent::HideToParent || e->type() == QEvent::ShowToParent ) ) updateVisibility(); + if ( o == myCont && e->type() == QEvent::ChildRemoved ) + { + QApplication::postEvent( this, new QEvent( (QEvent::Type)Remove ) ); + } + return false; } @@ -125,7 +138,7 @@ void QtxDockWidget::Watcher::shown( QtxDockWidget* dw ) if ( dw != myCont ) return; - myVisible = true; + setVisible( true ); } /*! @@ -137,7 +150,27 @@ void QtxDockWidget::Watcher::hidden( QtxDockWidget* dw ) if ( dw != myCont ) return; - myVisible = false; + setVisible( false ); +} + +bool QtxDockWidget::Watcher::isEmpty() const +{ + return myEmpty; +} + +bool QtxDockWidget::Watcher::isVisible() const +{ + return myShown; +} + +void QtxDockWidget::Watcher::setEmpty( const bool on ) +{ + myEmpty = on; +} + +void QtxDockWidget::Watcher::setVisible( const bool on ) +{ + myShown = on; } /*! @@ -148,10 +181,14 @@ void QtxDockWidget::Watcher::showContainer() if ( !myCont ) return; + bool vis = isVisible(); + QtxDockWidget* cont = myCont; myCont = 0; cont->show(); myCont = cont; + + setVisible( vis ); } /*! @@ -162,21 +199,33 @@ void QtxDockWidget::Watcher::hideContainer() if ( !myCont ) return; + bool vis = isVisible(); + QtxDockWidget* cont = myCont; myCont = 0; cont->hide(); myCont = cont; + + setVisible( vis ); } /*! \brief Proces custom events. \param e custom event (not used) */ -void QtxDockWidget::Watcher::customEvent( QEvent* /*e*/ ) +void QtxDockWidget::Watcher::customEvent( QEvent* e ) { - updateIcon(); - updateCaption(); - updateVisibility(); + if ( e->type() == Update ) + { + updateIcon(); + updateCaption(); + updateVisibility(); + } + else if ( myCont && e->type() == Remove && !myCont->widget() ) + { + myCont->deleteLater(); + myCont = 0; + } } /*! @@ -208,18 +257,25 @@ void QtxDockWidget::Watcher::updateVisibility() if ( !myCont ) return; - QLayout* l = myCont->layout(); - if ( !l ) - return; - bool vis = false; - for ( int i = 0; i < (int)l->count() && !vis; i++ ) - vis = l->itemAt( i ) && l->itemAt( i )->widget() && l->itemAt( i )->widget()->isVisibleTo( myCont ); + if ( myCont->widget() ) + vis = myCont->widget()->isVisibleTo( myCont ); + else + { + QLayout* l = myCont->layout(); + if ( l ) + { + for ( int i = 0; i < (int)l->count() && !vis; i++ ) + vis = l->itemAt( i ) && l->itemAt( i )->widget() && l->itemAt( i )->widget()->isVisibleTo( myCont ); + } + } - if ( myEmpty == vis ) + bool empty = isEmpty(); + if ( empty == vis ) { - myEmpty = !vis; - if ( !myEmpty ) + empty = !vis; + setEmpty( empty ); + if ( !empty ) myCont->toggleViewAction()->setVisible( myState ); else { @@ -228,7 +284,7 @@ void QtxDockWidget::Watcher::updateVisibility() } } - vis = !myEmpty && myVisible; + vis = !empty && isVisible(); if ( vis != myCont->isVisibleTo( myCont->parentWidget() ) ) vis ? showContainer() : hideContainer(); } @@ -238,10 +294,12 @@ void QtxDockWidget::Watcher::updateVisibility() */ void QtxDockWidget::Watcher::updateIcon() { - if ( !myCont || !myCont->widget() ) + if ( !myCont || !myCont->widget() || myBlock ) return; + myBlock = true; myCont->setWindowIcon( myCont->widget()->windowIcon() ); + myBlock = false; } /*! @@ -274,7 +332,7 @@ QtxDockWidget::QtxDockWidget( const QString& title, QWidget* parent, Qt::WindowF /*! \brief Constructor. - \param watch if \c true the event filter is installed to watch wigdet state changes + \param watch if \c true the event filter is installed to watch wigdet state changes to update it properly \param parent parent widget \param f widget flags @@ -315,15 +373,7 @@ QtxDockWidget::~QtxDockWidget() QSize QtxDockWidget::sizeHint() const { QSize sz = QDockWidget::sizeHint(); -/* - if ( place() == InDock && isStretchable() && area() ) - { - if ( orientation() == Horizontal ) - sz.setWidth( area()->width() ); - else - sz.setHeight( area()->height() ); - } -*/ + return sz; } @@ -334,20 +384,7 @@ QSize QtxDockWidget::sizeHint() const QSize QtxDockWidget::minimumSizeHint() const { QSize sz = QDockWidget::minimumSizeHint(); -/* - if ( orientation() == Horizontal ) - sz = QSize( 0, QDockWidget::minimumSizeHint().height() ); - else - sz = QSize( QDockWidget::minimumSizeHint().width(), 0 ); - if ( place() == InDock && isStretchable() && area() ) - { - if ( orientation() == Horizontal ) - sz.setWidth( area()->width() ); - else - sz.setHeight( area()->height() ); - } -*/ return sz; } @@ -357,6 +394,12 @@ QSize QtxDockWidget::minimumSizeHint() const */ void QtxDockWidget::setVisible( bool on ) { + updateGeometry(); + if ( widget() ) + widget()->updateGeometry(); + + QDockWidget::setVisible( on && ( myWatcher ? !myWatcher->isEmpty() : true ) ); + if ( myWatcher ) { if ( on ) @@ -364,12 +407,6 @@ void QtxDockWidget::setVisible( bool on ) else myWatcher->hidden( this ); } - - updateGeometry(); - if ( widget() ) - widget()->updateGeometry(); - - QDockWidget::setVisible( on ); } /*! diff --git a/src/Qtx/QtxDoubleSpinBox.cxx b/src/Qtx/QtxDoubleSpinBox.cxx index c79e581c0..ba8585f4a 100644 --- a/src/Qtx/QtxDoubleSpinBox.cxx +++ b/src/Qtx/QtxDoubleSpinBox.cxx @@ -22,6 +22,7 @@ #include "QtxDoubleSpinBox.h" #include +#include /*! \class QtxDoubleSpinBox @@ -57,7 +58,8 @@ */ QtxDoubleSpinBox::QtxDoubleSpinBox( QWidget* parent ) : QDoubleSpinBox( parent ), - myCleared( false ) + myCleared( false ), + myPrecision(0) { connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); @@ -77,7 +79,8 @@ QtxDoubleSpinBox::QtxDoubleSpinBox( QWidget* parent ) */ QtxDoubleSpinBox::QtxDoubleSpinBox( double min, double max, double step, QWidget* parent ) : QDoubleSpinBox( parent ), - myCleared( false ) + myCleared( false ), + myPrecision( 0 ) { setMinimum( min ); setMaximum( max ); @@ -87,6 +90,32 @@ QtxDoubleSpinBox::QtxDoubleSpinBox( double min, double max, double step, QWidget this, SLOT( onTextChanged( const QString& ) ) ); } +/*! + \brief Constructor. + + Constructs a spin box with specified minimum, maximum and step value. + The precision is set to 2 decimal places. + The value is initially set to the minimum value. + + \param min spin box minimum possible value + \param max spin box maximum possible value + \param step spin box increment/decrement value + \param parent parent object +*/ +QtxDoubleSpinBox::QtxDoubleSpinBox( double min, double max, double step, int prec, int dec, QWidget* parent ) +: QDoubleSpinBox( parent ), + myCleared( false ), + myPrecision( prec ) +{ + setDecimals( dec ); + setMinimum( min ); + setMaximum( max ); + setSingleStep( step ); + + connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), + this, SLOT( onTextChanged( const QString& ) ) ); +} + /*! \brief Destructor. */ @@ -97,6 +126,7 @@ QtxDoubleSpinBox::~QtxDoubleSpinBox() /*! \brief Check if spin box is in the "cleared" state. \return \c true if spin box is cleared + \sa setCleared() */ bool QtxDoubleSpinBox::isCleared() const { @@ -106,6 +136,7 @@ bool QtxDoubleSpinBox::isCleared() const /*! \brief Change "cleared" status of the spin box. \param on new "cleared" status + \sa isCleared() */ void QtxDoubleSpinBox::setCleared( const bool on ) { @@ -117,13 +148,85 @@ void QtxDoubleSpinBox::setCleared( const bool on ) } /*! - \brief Convert value to the text. - \param val value being converted - \return string containing the converted value + \brief Set precision of the spin box + + If precision value is less than 0, the 'g' format is used for value output, + otherwise 'f' format is used. + + \param prec new precision value. + \sa precision() +*/ +void QtxDoubleSpinBox::setPrecision( const int prec ) +{ + int newPrec = qMax( prec, 0 ); + int oldPrec = qMax( myPrecision, 0 ); + myPrecision = prec; + if ( newPrec != oldPrec ) + update(); +} + +/*! + \brief Get precision value of the spin box + \return current prevision value + \sa setPrecision() +*/ +int QtxDoubleSpinBox::getPrecision() const +{ + return myPrecision; +} + +/*! + \brief Interpret text entered by the user as a value. + \param text text entered by the user + \return mapped value + \sa textFromValue() +*/ +double QtxDoubleSpinBox::valueFromText( const QString& text ) const +{ + if (myPrecision < 0) + return text.toDouble(); + + return QDoubleSpinBox::valueFromText(text); +} + +/*! + \brief This function is used by the spin box whenever it needs to display + the given value. + + \param val spin box value + \return text representation of the value + \sa valueFromText() */ QString QtxDoubleSpinBox::textFromValue( double val ) const { - return myCleared ? QString() : QDoubleSpinBox::textFromValue( val ); + QString s = QLocale().toString( val, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : qAbs( myPrecision ) ); + return removeTrailingZeroes( s ); +} + +/*! + \brief Return source string with removed leading and trailing zeros. + \param str source string + \return resulting string +*/ +QString QtxDoubleSpinBox::removeTrailingZeroes( const QString& src ) const +{ + QString delim( QLocale().decimalPoint() ); + + int idx = src.lastIndexOf( delim ); + if ( idx == -1 ) + return src; + + QString iPart = src.left( idx ); + QString fPart = src.mid( idx + 1 ); + + while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' ) + fPart.remove( fPart.length() - 1, 1 ); + + QString res = iPart; + if ( !fPart.isEmpty() ) + res += delim + fPart; + + return res; } /*! @@ -142,6 +245,61 @@ void QtxDoubleSpinBox::stepBy( int steps ) QDoubleSpinBox::stepBy( steps ); } +/*! + \brief This function is used to determine whether input is valid. + \param str currently entered value + \param pos cursor position in the string + \return validating operation result +*/ +QValidator::State QtxDoubleSpinBox::validate( QString& str, int& pos ) const +{ + if (myPrecision >= 0) + return QDoubleSpinBox::validate(str, pos); + + QString pref = this->prefix(); + QString suff = this->suffix(); + uint overhead = pref.length() + suff.length(); + QValidator::State state = QValidator::Invalid; + + QDoubleValidator v (NULL); + v.setDecimals( decimals() ); + v.setBottom( minimum() ); + v.setTop( maximum() ); + v.setNotation( QDoubleValidator::ScientificNotation ); + + if ( overhead == 0 ) + state = v.validate( str, pos ); + else + { + if ( str.length() >= overhead && str.startsWith( pref ) && + str.right( suff.length() ) == suff ) + { + QString core = str.mid( pref.length(), str.length() - overhead ); + int corePos = pos - pref.length(); + state = v.validate( core, corePos ); + pos = corePos + pref.length(); + str.replace( pref.length(), str.length() - overhead, core ); + } + else + { + state = v.validate( str, pos ); + if ( state == QValidator::Invalid ) + { + QString special = this->specialValueText().trimmed(); + QString candidate = str.trimmed(); + if ( special.startsWith( candidate ) ) + { + if ( candidate.length() == special.length() ) + state = QValidator::Acceptable; + else + state = QValidator::Intermediate; + } + } + } + } + return state; +} + /*! \brief Called when user enters the text in the spin box. \param txt current spin box text (not used) diff --git a/src/Qtx/QtxDoubleSpinBox.h b/src/Qtx/QtxDoubleSpinBox.h index 45ef5434b..29958dcfb 100644 --- a/src/Qtx/QtxDoubleSpinBox.h +++ b/src/Qtx/QtxDoubleSpinBox.h @@ -25,6 +25,7 @@ #include "Qtx.h" #include +#include class QTX_EXPORT QtxDoubleSpinBox : public QDoubleSpinBox { @@ -33,21 +34,31 @@ class QTX_EXPORT QtxDoubleSpinBox : public QDoubleSpinBox public: QtxDoubleSpinBox( QWidget* = 0 ); QtxDoubleSpinBox( double, double, double = 1, QWidget* = 0 ); + QtxDoubleSpinBox( double, double, double, int, int, QWidget* = 0 ); virtual ~QtxDoubleSpinBox(); bool isCleared() const; virtual void setCleared( const bool ); + int getPrecision() const ; + void setPrecision( const int ); + virtual void stepBy( int ); + virtual double valueFromText( const QString& ) const; + virtual QString textFromValue( double ) const; + + virtual QValidator::State validate( QString&, int& ) const; + private slots: virtual void onTextChanged( const QString& ); protected: - virtual QString textFromValue( double ) const; + QString removeTrailingZeroes( const QString& ) const; private: bool myCleared; + int myPrecision; }; #endif diff --git a/src/Qtx/QtxEvalExpr.cxx b/src/Qtx/QtxEvalExpr.cxx index 75bcb7c43..f892bfb6e 100644 --- a/src/Qtx/QtxEvalExpr.cxx +++ b/src/Qtx/QtxEvalExpr.cxx @@ -72,8 +72,8 @@ void QtxEvalExpr::intialize( const bool stdSets, const QString& expr ) if ( stdSets ) { myParser->setAutoDeleteOperationSets( true ); - myParser->insertOperationSet( new QtxEvalSetArithmetic() ); myParser->insertOperationSet( new QtxEvalSetLogic() ); + myParser->insertOperationSet( new QtxEvalSetArithmetic() ); myParser->insertOperationSet( new QtxEvalSetString() ); myParser->insertOperationSet( new QtxEvalSetMath() ); myParser->insertOperationSet( new QtxEvalSetSets() ); @@ -266,8 +266,8 @@ void QtxEvalParser::insertOperationSet( QtxEvalSet* set, const int idx ) if ( mySets.contains( set ) ) return; - int index = idx < 0 ? mySets.count() - 1 : idx; - index = qMin( index, mySets.count() - 1 ); + int index = idx < 0 ? mySets.count() : idx; + index = qMin( index, mySets.count() ); mySets.insert( index, set ); } @@ -371,7 +371,7 @@ bool QtxEvalParser::prepare( const QString& expr, Postfix& post ) while ( pos < len && error() == QtxEvalExpr::OK ) { PostfixItem item; - while ( expr[pos].isSpace() && pos < len ) + while ( pos < len && expr[pos].isSpace() ) pos++; if ( pos >= len ) break; @@ -1181,7 +1181,7 @@ int QtxEvalParser::priority( const QString& op, bool isBin ) const for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && priority <= 0; ++it, i++ ) priority = (*it)->priority( op, isBin ); - return priority > 0 ? priority + i * 10 : 0; + return priority > 0 ? priority + i * 50 : 0; } /*! @@ -1761,8 +1761,8 @@ int QtxEvalSetLogic::priority( const QString& op, bool isBin ) const QtxEvalExpr::Error QtxEvalSetLogic::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const { QtxEvalExpr::Error err = QtxEvalExpr::OK; - bool val1 = booleanValue( v1 ); - bool val2 = booleanValue( v2 ); + int val1 = intValue( v1 ); + int val2 = intValue( v2 ); if ( v1.isValid() && v2.isValid() ) { if ( op == "and" || op == "&&" ) @@ -1783,26 +1783,27 @@ QtxEvalExpr::Error QtxEvalSetLogic::calculate( const QString& op, QVariant& v1, } /*! - \brief Convert value to the boolean. + \brief Convert value to the integer. + + Note: the value is converted to the integer (not boolean) in order + to compare integer numbers correctly. + \param v value being converted \return converted value */ -bool QtxEvalSetLogic::booleanValue( const QVariant& v ) const +int QtxEvalSetLogic::intValue( const QVariant& v ) const { - bool res = false; + int res = 0; switch ( v.type() ) { case QVariant::Bool: - res = v.toBool(); + res = v.toBool() ? 1 : 0; break; case QVariant::Int: - res = v.toInt() != 0; - break; case QVariant::UInt: - res = v.toUInt() != 0; + res = v.toInt(); break; default: - res = false; break; } return res; diff --git a/src/Qtx/QtxEvalExpr.h b/src/Qtx/QtxEvalExpr.h index 34acd4747..6679d7e86 100644 --- a/src/Qtx/QtxEvalExpr.h +++ b/src/Qtx/QtxEvalExpr.h @@ -247,7 +247,7 @@ public: virtual QString name() const; private: - bool booleanValue( const QVariant& v ) const; + int intValue( const QVariant& v ) const; }; class QTX_EXPORT QtxEvalSetMath : public QtxEvalSetBase diff --git a/src/Qtx/QtxMap.h b/src/Qtx/QtxMap.h index 403fc3284..98dec2975 100644 --- a/src/Qtx/QtxMap.h +++ b/src/Qtx/QtxMap.h @@ -16,8 +16,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: QtxMap.h -// Author: Vadim SANDLER +// File : QtxMap.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// #ifndef QTXMAP_H #define QTXMAP_H diff --git a/src/Qtx/QtxResourceMgr.cxx b/src/Qtx/QtxResourceMgr.cxx index 273c49159..80812a2f1 100644 --- a/src/Qtx/QtxResourceMgr.cxx +++ b/src/Qtx/QtxResourceMgr.cxx @@ -33,8 +33,6 @@ #include #endif -#define EMULATE_GLOBAL_CONTEXT - #include /*! diff --git a/src/Qtx/QtxTable.cxx b/src/Qtx/QtxTable.cxx index 64f9ae5c7..630694b45 100644 --- a/src/Qtx/QtxTable.cxx +++ b/src/Qtx/QtxTable.cxx @@ -1510,12 +1510,12 @@ void QtxTable::endHeaderEdit( const bool accept ) if ( !isHeaderEditing() ) return; - QString oldTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null; + QString oldTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString(); if ( accept && myEditedHeader ) setHeaderContentFromEditor( myEditedHeader, myEditedSection, myHeaderEditor ); - QString newTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null; + QString newTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString(); int sec = myEditedSection; QHeaderView* hdr = myEditedHeader; diff --git a/src/Qtx/QtxTable.h b/src/Qtx/QtxTable.h index ea93a37c9..52443ffab 100644 --- a/src/Qtx/QtxTable.h +++ b/src/Qtx/QtxTable.h @@ -19,8 +19,8 @@ // File: QtxTable.h // Author: Sergey TELKOV -#ifndef QTX_TABLE_H -#define QTX_TABLE_H +#ifndef QTXTABLE_H +#define QTXTABLE_H #include "Qtx.h" @@ -199,4 +199,4 @@ private: #endif -#endif +#endif // QTXTABLE_H