]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
*** empty log message ***
authorstv <stv@opencascade.com>
Mon, 9 Jul 2007 12:22:44 +0000 (12:22 +0000)
committerstv <stv@opencascade.com>
Mon, 9 Jul 2007 12:22:44 +0000 (12:22 +0000)
74 files changed:
src/Qtx/Qtx.cxx
src/Qtx/Qtx.h
src/Qtx/QtxAction.cxx
src/Qtx/QtxAction.h
src/Qtx/QtxActionMenuMgr.cxx
src/Qtx/QtxActionMenuMgr.h
src/Qtx/QtxActionMgr.cxx
src/Qtx/QtxActionMgr.h
src/Qtx/QtxActionSet.cxx [new file with mode: 0644]
src/Qtx/QtxActionSet.h [new file with mode: 0644]
src/Qtx/QtxActionToolMgr.cxx
src/Qtx/QtxActionToolMgr.h
src/Qtx/QtxColorButton.cxx [new file with mode: 0644]
src/Qtx/QtxColorButton.h [new file with mode: 0644]
src/Qtx/QtxColorScale.cxx
src/Qtx/QtxColorScale.h
src/Qtx/QtxComboBox.cxx
src/Qtx/QtxComboBox.h
src/Qtx/QtxDialog.cxx
src/Qtx/QtxDialog.h
src/Qtx/QtxDockAction.cxx
src/Qtx/QtxDockAction.h
src/Qtx/QtxDockWidget.cxx
src/Qtx/QtxDockWidget.h
src/Qtx/QtxDoubleSpinBox.cxx [new file with mode: 0644]
src/Qtx/QtxDoubleSpinBox.h [new file with mode: 0644]
src/Qtx/QtxEvalExpr.cxx [new file with mode: 0644]
src/Qtx/QtxEvalExpr.h [new file with mode: 0644]
src/Qtx/QtxFontEdit.cxx [new file with mode: 0644]
src/Qtx/QtxFontEdit.h [new file with mode: 0644]
src/Qtx/QtxGridBox.cxx [new file with mode: 0644]
src/Qtx/QtxGridBox.h [new file with mode: 0644]
src/Qtx/QtxGroupBox.cxx [new file with mode: 0644]
src/Qtx/QtxGroupBox.h [new file with mode: 0644]
src/Qtx/QtxIntSpinBox.cxx [new file with mode: 0755]
src/Qtx/QtxIntSpinBox.h [new file with mode: 0755]
src/Qtx/QtxListAction.cxx [new file with mode: 0755]
src/Qtx/QtxListAction.h [new file with mode: 0755]
src/Qtx/QtxLogoMgr.cxx
src/Qtx/QtxLogoMgr.h
src/Qtx/QtxMRUAction.h
src/Qtx/QtxMainWindow.cxx
src/Qtx/QtxMainWindow.h
src/Qtx/QtxMap.h [new file with mode: 0644]
src/Qtx/QtxPagePrefMgr.cxx [new file with mode: 0644]
src/Qtx/QtxPagePrefMgr.h [new file with mode: 0644]
src/Qtx/QtxPathDialog.cxx [new file with mode: 0755]
src/Qtx/QtxPathDialog.h [new file with mode: 0755]
src/Qtx/QtxPathEdit.cxx [new file with mode: 0644]
src/Qtx/QtxPathEdit.h [new file with mode: 0644]
src/Qtx/QtxPathListEdit.cxx [new file with mode: 0644]
src/Qtx/QtxPathListEdit.h [new file with mode: 0644]
src/Qtx/QtxPopupMgr.cxx [new file with mode: 0644]
src/Qtx/QtxPopupMgr.h [new file with mode: 0644]
src/Qtx/QtxPreferenceMgr.cxx [new file with mode: 0644]
src/Qtx/QtxPreferenceMgr.h [new file with mode: 0644]
src/Qtx/QtxResourceMgr.cxx
src/Qtx/QtxResourceMgr.h
src/Qtx/QtxSplash.cxx [new file with mode: 0644]
src/Qtx/QtxSplash.h [new file with mode: 0644]
src/Qtx/QtxToolBar.cxx
src/Qtx/QtxToolBar.h
src/Qtx/QtxToolTip.cxx [new file with mode: 0755]
src/Qtx/QtxToolTip.h [new file with mode: 0755]
src/Qtx/QtxValidator.cxx [new file with mode: 0644]
src/Qtx/QtxValidator.h [new file with mode: 0644]
src/Qtx/QtxWorkspace.cxx [new file with mode: 0644]
src/Qtx/QtxWorkspace.h [new file with mode: 0644]
src/Qtx/QtxWorkspaceAction.cxx [new file with mode: 0644]
src/Qtx/QtxWorkspaceAction.h [new file with mode: 0644]
src/Qtx/QtxWorkstack.cxx
src/Qtx/QtxWorkstack.h
src/Qtx/QtxWorkstackAction.cxx [new file with mode: 0644]
src/Qtx/QtxWorkstackAction.h [new file with mode: 0644]

index fd10d17241e4b11eb56c43d488928d8631737504..db5c4d0b780e7ccf75a81f75ef14c2b6bdfebc81 100755 (executable)
 
 #include "Qtx.h"
 
-#include <QtCore/qdir.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qfileinfo.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qbitmap.h>
-#include <QtGui/qwidget.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qpainter.h>
-#include <QtGui/qtoolbar.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qdesktopwidget.h>
+#include <QDir>
+#include <QMenu>
+#include <QRegExp>
+#include <QBitmap>
+#include <QWidget>
+#include <QLayout>
+#include <QPainter>
+#include <QDirModel>
+#include <QFileInfo>
+#include <QCompleter>
+#include <QApplication>
+#include <QDesktopWidget>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 
+/*!
+  \class Qtx
+  \brief A set of helpful utility functions.
+
+  The class implements a set of the static functions which can be used
+  for the different purposes:
+  - specify tab order for the set of widgets: setTabOrder()
+  - align one widget to the coordinates of the another one: alignWidget()
+  - remove extra separators from the menu or toolbar: simplifySeparators()
+  - retrieve directory, file name and extension parts of the path:
+  dir(), file(), extension()
+  - get the path to the temporary directory: tmpDir()
+  - create or remove a directory (recursively): mkDir(), rmDir()
+  - convert text file from DOS to UNIX native format: dos2unix()
+  - convert a picture to the gray scale: grayscale()
+  - other
+*/
+
+/*!
+  \brief Convert character array (ASCII string) to the QString.
+  \param str character array
+  \param len array length, if < 0, the array should be zero-terminated
+  \return QString object
+ */
 QString Qtx::toQString( const char* str, const int len )
 {
   return toQString( (unsigned char*)str, len );
 }
 
+/*!
+  \brief Convert integer array (UNICODE string) to the QString.
+  \param str integer array
+  \param len array length, if < 0, the array should be zero-terminated
+  \return QString object
+ */
 QString Qtx::toQString( const short* str, const int len )
 {
   return toQString( (unsigned short*)str, len );
 }
 
+/*!
+  \brief Convert character array (ASCII string) to the QString.
+  \param str character array
+  \param len array length, if < 0, the array should be zero-terminated
+  \return QString object
+ */
 QString Qtx::toQString( const unsigned char* str, const int len )
 {
   QString res;
-  int l = len;
   const unsigned char* s = str;
   while ( len < 0 || res.length() < len )
   {
@@ -64,10 +99,15 @@ QString Qtx::toQString( const unsigned char* str, const int len )
   return res;
 }
 
+/*!
+  \brief Convert integer array (UNICODE string) to the QString.
+  \param str integer array
+  \param len array length, if < 0, the array should be zero-terminated
+  \return QString object
+ */
 QString Qtx::toQString( const unsigned short* str, const int len )
 {
   QString res;
-  int l = len;
   const unsigned short* s = str;
   while ( len < 0 || res.length() < len )
   {
@@ -81,32 +121,34 @@ QString Qtx::toQString( const unsigned short* str, const int len )
 }
 
 /*!
-       Name: setTabOrder [static public]
-       Desc: Set tab order for specified list of widgets. Last parameter should be null pointer.
-*/
+  \brief Set tab order for specified list of widgets.
+
+  The function has arbitrary number of parameters, each should be
+  hovewer of QWidget* type. Last parameter should be null pointer.
 
+  \param first first widget in the sequence
+*/
 void Qtx::setTabOrder( QWidget* first, ... )
 {
   va_list wids;
-       va_start( wids, first );
+  va_start( wids, first );
 
-       QWidgetList widList;
+  QWidgetList widList;
 
-       QWidget* cur = first;
-       while ( cur )
-       {
-         widList.append( cur );
-               cur = va_arg( wids, QWidget* );
+  QWidget* cur = first;
+  while ( cur )
+  {
+    widList.append( cur );
+    cur = va_arg( wids, QWidget* );
   }
 
-       setTabOrder( widList );
+  setTabOrder( widList );
 }
 
 /*!
-       Name: setTabOrder [static public]
-       Desc: Set tab order for specified list of widgets.
+  \brief Set tab order for specified list of widgets.
+  \param widgets list of widgets
 */
-
 void Qtx::setTabOrder( const QWidgetList& widgets )
 {
   if ( widgets.count() < 2 )
@@ -123,132 +165,81 @@ void Qtx::setTabOrder( const QWidgetList& widgets )
 }
 
 /*!
-       Name: alignWidget [static public]
-       Desc: Align widget 'src' relative to widget 'ref' acording to alignment flags.
-             Alignment flags:
-                         Qtx::AlignLeft      - Align left side of 'src' to left side of 'ref'.
-                         Qtx::AlignRight     - Align right side of 'src' to right side of 'ref'.
-                         Qtx::AlignTop       - Align top side of 'src' to top side of 'ref'.
-                         Qtx::AlignBottom    - Align bottom side of 'src' to bottom side of 'ref'.
-                         Qtx::AlignHCenter   - Align 'src' to center of 'ref' in horizontal dimension.
-                         Qtx::AlignVCenter   - Align 'src' to center of 'ref' in vertical dimension.
-                         Qtx::AlignCenter    - Align 'src' to center of 'ref' in both dimensions.
-                         Qtx::AlignOutLeft   - Align right side of 'src' to left side of 'ref'.
-                         Qtx::AlignOutRight  - Align left side of 'src' to right side of 'ref'.
-                         Qtx::AlignOutTop    - Align bottom side of 'src' to top side of 'ref'.
-                         Qtx::AlignOutBottom - Align top side of 'src' to bottom side of 'ref'.
+  \brief Align widget \a src relative to widget \a ref acording to the 
+         alignment flags \a alignFlags.
+  \param src source widget (being aligned)
+  \param ref reference widget (source widget being aligned to)
+  \param alignFlags alignment flags (Qtx::AlignmentFlags)
 */
-
 void Qtx::alignWidget( QWidget* src, const QWidget* ref, const int alignFlags )
 {
-       if ( !src || !ref || !alignFlags )
-               return;
-
-       QPoint srcOri = src->pos();
-       QPoint refOri = ref->pos();
-       if ( src->parentWidget() && !src->isTopLevel() )
-               srcOri = src->parentWidget()->mapToGlobal( srcOri );
-       if ( ref->parentWidget() && !ref->isTopLevel() )
-               refOri = ref->parentWidget()->mapToGlobal( refOri );
-
-       int x = srcOri.x(), y = srcOri.y();
-       int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
-       int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
-
-       if ( srcWidth <= 0 )
-               srcWidth = src->sizeHint().width();
+  if ( !src || !ref || !alignFlags )
+    return;
+
+  QPoint srcOri = src->pos();
+  QPoint refOri = ref->pos();
+  if ( src->parentWidget() && !src->isTopLevel() )
+    srcOri = src->parentWidget()->mapToGlobal( srcOri );
+  if ( ref->parentWidget() && !ref->isTopLevel() )
+    refOri = ref->parentWidget()->mapToGlobal( refOri );
+
+  int x = srcOri.x(), y = srcOri.y();
+  int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
+  int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
+
+  if ( srcWidth <= 0 )
+    srcWidth = src->sizeHint().width();
   if ( srcHei <= 0 )
     srcHei = src->sizeHint().height();
 
-       int border = 0;
+  int border = 0;
   if ( ref->isTopLevel() && ref->isMaximized() &&
        src->isTopLevel() && !src->isMaximized() )
     border = ( src->frameGeometry().width() - src->width() ) / 2;
 
-       if ( alignFlags & Qtx::AlignLeft )
-               x = refOri.x() + border;
-       if ( alignFlags & Qtx::AlignOutLeft )
-               x = refOri.x() - srcWidth - border;
-       if ( alignFlags & Qtx::AlignRight )
-               x = refOri.x() + refWidth - srcWidth - border;
-       if ( alignFlags & Qtx::AlignOutRight )
-               x = refOri.x() + refWidth + border;
-       if ( alignFlags & Qtx::AlignTop )
-               y = refOri.y() + border;
-       if ( alignFlags & Qtx::AlignOutTop )
-               y = refOri.y() - srcHei - border;
-       if ( alignFlags & Qtx::AlignBottom )
-               y = refOri.y() + refHei - srcHei - border;
-       if ( alignFlags & Qtx::AlignOutBottom )
-               y = refOri.y() + refHei + border;
-       if ( alignFlags & Qtx::AlignHCenter )
-               x = refOri.x() + ( refWidth - srcWidth ) / 2;
-       if ( alignFlags & Qtx::AlignVCenter )
-               y = refOri.y() + ( refHei - srcHei ) / 2;
-
-       if ( src->parentWidget() && !src->isTopLevel() )
-       {
-               QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
-               x = pos.x();
-               y = pos.y();
-       }
-
-       QWidget* desk = QApplication::desktop();
-       if ( desk && x + srcWidth + border > desk->width() )
-               x = desk->width() - srcWidth - border;
-       if ( desk && y + srcHei + border > desk->height() )
-               y = desk->height() - srcHei - border;
-
-       x = qMax( x, 0 );
-       y = qMax( y, 0 );
-
-       src->move( x, y );
-}
-
-/*!
-       Name: simplifySeparators [static public]
-       Desc: Checks toolbar for unnecessary separators and removes them
-*/
-/*
-void Qtx::simplifySeparators( QToolBar* toolbar )
-{
-  if ( !toolbar )
-    return;
-
-  const QObjectList& objList = toolbar->children();
-
-  QObjectList delList;
-
-  bool isPrevSep = true;
-  QObject* lastVis = 0; // last visible
-  for ( QObjectList::const_iterator it = objList.begin(); it != objList.end(); ++it )
+  if ( alignFlags & Qtx::AlignLeft )
+    x = refOri.x() + border;
+  if ( alignFlags & Qtx::AlignOutLeft )
+    x = refOri.x() - srcWidth - border;
+  if ( alignFlags & Qtx::AlignRight )
+    x = refOri.x() + refWidth - srcWidth - border;
+  if ( alignFlags & Qtx::AlignOutRight )
+    x = refOri.x() + refWidth + border;
+  if ( alignFlags & Qtx::AlignTop )
+    y = refOri.y() + border;
+  if ( alignFlags & Qtx::AlignOutTop )
+    y = refOri.y() - srcHei - border;
+  if ( alignFlags & Qtx::AlignBottom )
+    y = refOri.y() + refHei - srcHei - border;
+  if ( alignFlags & Qtx::AlignOutBottom )
+    y = refOri.y() + refHei + border;
+  if ( alignFlags & Qtx::AlignHCenter )
+    x = refOri.x() + ( refWidth - srcWidth ) / 2;
+  if ( alignFlags & Qtx::AlignVCenter )
+    y = refOri.y() + ( refHei - srcHei ) / 2;
+
+  if ( src->parentWidget() && !src->isTopLevel() )
   {
-    QObject* obj = *it;
-    if ( !obj || !obj->isWidgetType() )
-      continue;
-    bool isSep = obj->inherits( "QToolBarSeparator" );
-    if ( !isSep && !((QWidget*)obj)->isVisibleTo( toolbar ) )
-      continue;
-    if ( isPrevSep && isSep )
-      delList.append( obj );
-    else
-    {
-      isPrevSep = isSep;
-      lastVis = obj;
-    }
+    QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
+    x = pos.x();
+    y = pos.y();
   }
-  // remove last visible separator
-  if ( lastVis && lastVis->inherits( "QToolBarSeparator" ) )
-      delList.append( lastVis );
 
-  for ( QObjectList::iterator itr = delList.begin(); itr != delList.end(); ++itr )
-    delete *itr;
+  QWidget* desk = QApplication::desktop();
+  if ( desk && x + srcWidth + border > desk->width() )
+    x = desk->width() - srcWidth - border;
+  if ( desk && y + srcHei + border > desk->height() )
+    y = desk->height() - srcHei - border;
+
+  x = qMax( x, 0 );
+  y = qMax( y, 0 );
+
+  src->move( x, y );
 }
-*/
 
 /*!
-       Name: simplifySeparators [static public]
-       Desc: Checks popup menu recursively for unnecessary separators and removes them
+  \brief Remove (recursively) unnecessary separators from the menu or toolbar.
+  \param wid widget, should be of QMenu* or QToolBar* class
 */
 void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
 {
@@ -260,7 +251,7 @@ void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
     return;
 
   QList<QAction*> toRemove;
-  for ( uint i = 1; i < items.count(); i++ )
+  for ( int i = 1; i < items.count(); i++ )
   {
     if ( items[i]->isSeparator() && items[i - 1]->isSeparator() )
       toRemove.append( items[i] );
@@ -282,8 +273,17 @@ void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
 }
 
 /*!
-       Name: isParent [static public]
-       Desc: Returns 'true' if specified 'parent' is parent object of given 'child'.
+  \brief Return \c true if specified \a parent is a parent object
+         of given \a child (in terms of QObject).
+
+  This function works recursively. It means that \a true is also
+  returned if \a parent is a grand-father, grand-grand-father, etc
+  of \a child. If the same object is given as both \a parent and
+  \a child, \c true is also returned.
+
+  \param child child object
+  \param parent parent object
+  \return \c true if the \a parent is a parent of \a child
 */
 bool Qtx::isParent( QObject* child, QObject* parent )
 {
@@ -301,21 +301,32 @@ bool Qtx::isParent( QObject* child, QObject* parent )
 }
 
 /*!
-       Name: dir [static public]
-       Desc: Returns dir name or null string.
+  \brief Return directory part of the file path.
+
+  If the file path does not include directory part (the file is in the
+  current directory), null string is returned.
+
+  \param path file path
+  \param abs if true (default) \a path parameter is treated as absolute file path
+  \return directory part of the file path
 */
 QString Qtx::dir( const QString& path, const bool abs )
 {
   QDir aDir = QFileInfo( path ).dir();
   QString dirPath = abs ? aDir.absolutePath() : aDir.path();
   if ( dirPath == QString( "." ) )
-    dirPath = QString::null;
+    dirPath = QString();
   return dirPath;
 }
 
 /*!
-       Name: file [static public]
-       Desc: Returns file with or without extension.
+  \brief Return file name part of the file path.
+
+  \param path file path
+  \param withExt if true (default) complete file name (with all
+         extension except the last) is returned, otherwise only base name
+         is returned
+  \return file name part of the file path
 */
 QString Qtx::file( const QString& path, bool withExt )
 {
@@ -330,8 +341,12 @@ QString Qtx::file( const QString& path, bool withExt )
 }
 
 /*!
-       Name: extension [static public]
-       Desc: Returns the file extension only or null string.
+  \brief Return extension part of the file path.
+
+  \param path file path
+  \param full if true complete extension (all extensions, dot separated)
+         is returned, otherwise (default) only last extension is returned
+  \return extension part of the file path
 */
 QString Qtx::extension( const QString& path, const bool full )
 {
@@ -339,9 +354,15 @@ QString Qtx::extension( const QString& path, const bool full )
 }
 
 /*!
-       Name: library [static public]
-       Desc: Generate library file name.
-        Append required prefix (lib) and suffix (.dll/.so) to the library file name.
+  \brief Convert the given parameter to the platform-specific library name.
+
+  The function appends platform-specific prefix (lib) and suffix (.dll/.so)
+  to the library file name.
+  For example, if \a str = "mylib", "libmylib.so" is returned for Linux and
+  mylib.dll for Windows.
+
+  \param str short library name
+  \return full library name
 */
 QString Qtx::library( const QString& str )
 {
@@ -375,94 +396,99 @@ QString Qtx::library( const QString& str )
 }
 
 /*!
-       Name: tmpDir [static public]
-       Desc: Returns path to temporary directory.
+  \brief Get the temporary directory name.
+  \return temporary directory (platform specific)
 */
 QString Qtx::tmpDir()
 {
-       char* tmpdir = ::getenv( "TEMP" );
-       if ( !tmpdir )
-               tmpdir = ::getenv ( "TMP" );
-       if ( !tmpdir )
-       {
+  char* tmpdir = ::getenv( "TEMP" );
+  if ( !tmpdir )
+    tmpdir = ::getenv ( "TMP" );
+  if ( !tmpdir )
+  {
 #ifdef WIN32
-               tmpdir = "C:\\";
+    tmpdir = "C:\\";
 #else
-               tmpdir = "/tmp";
+    tmpdir = "/tmp";
 #endif
-       }
-       return QString( tmpdir );
+  }
+  return QString( tmpdir );
 }
 
 /*!
-       Name: mkDir [static public]
-       Desc: Creates directory with intermediate perent directories.
-                   Returns true in successfull case.
+  \brief Create directory recursively including all intermediate sub directories.
+  \return \c true if the directory is successfully created and \c false otherwise
 */
 bool Qtx::mkDir( const QString& dirPath )
 {
-       return QDir().mkpath( dirPath );
+  return QDir().mkpath( dirPath );
 }
 
 /*!
-       Name: rmDir [static public]
-       Desc: Removes directory with its subdirectories and files.
-                   Returns true in successfull case.
+  \brief Remove directory recursively including all subdirectories and files.
+  \return \c true if the directory is successfully removed and \c false otherwise
 */
 bool Qtx::rmDir( const QString& thePath )
 {
-       QFileInfo fi( thePath );
-       if ( !fi.exists() )
-               return true;
-
-       bool stat = true;
-       if ( fi.isFile() )
-               stat = QFile::remove( thePath );
-       else if ( fi.isDir() )
-       {
-               QDir aDir( thePath );
-               QFileInfoList anEntries = aDir.entryInfoList();
+  QFileInfo fi( thePath );
+  if ( !fi.exists() )
+    return true;
+
+  bool stat = true;
+  if ( fi.isFile() )
+    stat = QFile::remove( thePath );
+  else if ( fi.isDir() )
+  {
+    QDir aDir( thePath );
+    QFileInfoList anEntries = aDir.entryInfoList();
     for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
-               {
+    {
       QFileInfo inf = *it;
       if ( inf.fileName() == "." || inf.fileName() == ".." )
-                                       continue;
+       continue;
       stat = stat && rmDir( inf.absoluteFilePath() );
-               }
-               stat = stat && aDir.rmdir( thePath );
-       }
-       return stat;
+    }
+    stat = stat && aDir.rmdir( thePath );
+  }
+  return stat;
 }
 
 /*!
-       Name: addSlash [static public]
-       Desc: Adds a slash to the end of 'path' if it is not already there.
+  \brief Add a slash (platform-specific) to the end of \a path
+         if it is not already there.
+  \param path directory path
+  \return modified path (with slash added to the end)
 */
 QString Qtx::addSlash( const QString& path )
 {
-       QString res = path;
+  QString res = path;
   if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
-         res.at( res.length() - 1 ) != QChar( '\\' ) )
+       res.at( res.length() - 1 ) != QChar( '\\' ) )
   res += QDir::separator();
   return res;
 }
 
 /*!
-       Name: dos2unix [static public]
-       Desc: Convert text file. Replace symbols "LF/CR" by symbol "LF".
+  \brief Convert text file from DOS format to UNIX.
+
+  The function replaces "LF/CR" symbols sequence by "LF" symbol.
+
+  \param absName file name
+  \return \c true if the file is converted successfully and \c false in
+         case of any error
 */
 bool Qtx::dos2unix( const QString& absName )
 {
   FILE* src = ::fopen( absName.toLatin1(), "rb" );
   if ( !src )
-               return false;
+    return false;
 
   /* we'll use temporary file */
   char temp[512] = { '\0' };
   QString dir = Qtx::dir( absName );
   FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toLatin1(), "__x" ) ), "wb" );
   if ( !tgt )
-               return false;
+    return false;
 
   /* temp -> result of conversion */
   const char CR = 0x0d;
@@ -508,7 +534,7 @@ bool Qtx::dos2unix( const QString& absName )
       break;              /* converted ok */
   }
   ::fclose( src );
-       ::fclose( tgt );
+  ::fclose( tgt );
 
   /* rename temp -> src */
   if ( !QFile::remove( absName ) )
@@ -518,8 +544,60 @@ bool Qtx::dos2unix( const QString& absName )
 }
 
 /*!
-       Name: rgbSet [static public]
-       Desc: Pack the specified color into one integer RGB set.
+  \brief Create path completer which can be used in the widgets
+  to provide auto completions.
+
+  Create an instance of QCompleter class and returns the pointer on it.
+  The calling function is responsible to the desstroying of the created 
+  completer object.
+
+  The QCompleter class provides completions based on a item model and can be
+  used in such as QLineEdit and QComboBox. 
+  When the user starts typing a word, QCompleter suggests possible ways of 
+  completing the word, based on a word list. 
+
+  \param type path type (Qtx::PathType)
+  \param filter file/directory filters (list of wildcards, separated by ";;")
+  \return a pointer to the created completer
+*/
+QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
+{
+  QStringList extList;
+  QStringList filterList = filter.split( ";;" );
+  for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
+  {
+    QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
+    int index = 0;
+    while ( ( index = rx.indexIn( *it, index ) ) != -1 )
+    {
+      extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
+      index += rx.matchedLength();
+    }
+  }
+
+  QDir::Filters filters = 0;
+  switch ( type )
+  {
+  case PT_OpenFile:
+  case PT_SaveFile:
+    filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
+    break;
+  case PT_Directory:
+    filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
+    break;
+  }
+
+  QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
+  QCompleter* cmp = new QCompleter( dm, 0 );
+  dm->setParent( cmp );
+
+  return cmp;
+}
+
+/*!
+  \brief Pack the specified color into integer RGB set.
+  \param c unpacked color
+  \return packed color
 */
 int Qtx::rgbSet( const QColor& c )
 {
@@ -527,8 +605,11 @@ int Qtx::rgbSet( const QColor& c )
 }
 
 /*!
-       Name: rgbSet [static public]
-       Desc: Pack the specified color components into one integer RGB set.
+  \brief Pack the specified RGB color components into integer RGB set.
+  \param r red component
+  \param g green component
+  \param b blue component
+  \return packed color
 */
 int Qtx::rgbSet( const int r, const int g, const int b )
 {
@@ -536,8 +617,9 @@ int Qtx::rgbSet( const int r, const int g, const int b )
 }
 
 /*!
-       Name: rgbSet [static public]
-       Desc: Unpack the specified integer RGB set into the color.
+  \brief Unpack the specified integer RGB set to the color.
+  \param rgb packed color
+  \return unpacked color (QColor)
 */
 QColor Qtx::rgbSet( const int rgb )
 {
@@ -547,8 +629,11 @@ QColor Qtx::rgbSet( const int rgb )
 }
 
 /*!
-       Name: rgbSet [static public]
-       Desc: Unpack the specified integer RGB set into the color components.
+  \brief Unpack the specified integer RGB set to the three RGB components.
+  \param rgb packed color
+  \param r returned unpacked red component
+  \param g returned unpacked green component
+  \param b returned unpacked blue component
 */
 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
 {
@@ -558,8 +643,11 @@ void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
 }
 
 /*!
-       Name: scaleColor [static public]
-       Desc: Returns the color specified by the index between min (blue) and max (red).
+  \brief Return the color specified by the index between min (blue) and max (red).
+  \param index color index
+  \param min required minimum hue value
+  \param max required maximum hue value
+  \return resulting color
 */
 QColor Qtx::scaleColor( const int index, const int min, const int max )
 {
@@ -567,7 +655,7 @@ QColor Qtx::scaleColor( const int index, const int min, const int max )
 
   int hue = HUE[0];
 
-       if ( min != max )
+  if ( min != max )
   {
     double aPosition = 9.0 * ( index - min ) / ( max - min );
     if ( aPosition > 0.0 )
@@ -586,10 +674,11 @@ QColor Qtx::scaleColor( const int index, const int min, const int max )
 }
 
 /*!
-       Name: scaleColors [static public]
-       Desc: Returns the 'num' number of colors from blue to red.
+  \brief Generate required number of colors aligned from blue to red.
+  \param num required number of colors
+  \param lst returned set of colors
 */
-void Qtx::scaleColors( const int num, QList<QColor>& lst )
+void Qtx::scaleColors( const int num, QColorList& lst )
 {
   lst.clear();
   for ( int i = 0; i < num; i++ )
@@ -597,8 +686,9 @@ void Qtx::scaleColors( const int num, QList<QColor>& lst )
 }
 
 /*!
-       Name: grayscale [static public]
-       Desc: Convert color image to grayscale image.
+  \brief Convert given image to the grayscale format.
+  \param img initial image
+  \return converted to the grayscale image
 */
 QImage Qtx::grayscale( const QImage& img )
 {
@@ -626,8 +716,9 @@ QImage Qtx::grayscale( const QImage& img )
 }
 
 /*!
-       Name: grayscale [static public]
-       Desc: Convert color pixmap to grayscale pixmap.
+  \brief Convert given pixmap to the grayscale format.
+  \param pix initial pixmap
+  \return converted to the grayscale pixmap
 */
 QPixmap Qtx::grayscale( const QPixmap& pix )
 {
@@ -637,8 +728,11 @@ QPixmap Qtx::grayscale( const QPixmap& pix )
 }
 
 /*!
-       Name: transparentImage [static public]
-       Desc: Create transparent image with specified width \aw, height \ah and color depth \ad.
+  \brief Create transparent image.
+  \param w required image width
+  \param h required image height
+  \param d required image depth
+  \return generated image
 */
 QImage Qtx::transparentImage( const int w, const int h, const int d )
 {
@@ -671,8 +765,11 @@ QImage Qtx::transparentImage( const int w, const int h, const int d )
 }
 
 /*!
-       Name: transparentPixmap [static public]
-       Desc: Create transparent pixmap with specified width \aw, height \ah and color depth \ad.
+  \brief Create transparent pixmap.
+  \param w required image width
+  \param h required pixmap height
+  \param d required pixmap depth
+  \return generated pixmap
 */
 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
 {
@@ -684,10 +781,17 @@ QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
 }
 
 /*!
-       Name: composite [static public]
-       Desc: Create composite pixmap. Pixmap 'pix' draws over pixmap 'dest' with coordinates
-        specified relative upper left corner of 'dest'. If 'dest' not given then new empty
-        pixmap with appropriate size created.
+  \brief Create composite pixmap. 
+
+  Pixmap \a pix is drawn over pixmap \a dest with coordinates
+  specified relatively to the upper left corner of \a dest.
+  If \a dest is not given, the new empty pixmap with appropriate size created instead.
+
+  \param pix source pixmap
+  \param x horizontal shift
+  \param y vertical shift
+  \param dest background pixmap
+  \return resulting pixmap
 */
 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
 {
index 066847e9a85e18a8a4c18047dda681de63b028a5..845e28c13dcc9745900f7e8903b459d942249b80 100755 (executable)
 #ifndef QTX_H
 #define QTX_H
 
-#if defined QTX_EXPORTS
 #if defined WIN32
-#define QTX_EXPORT _declspec( dllexport )
+#  if defined QTX_EXPORTS
+#    define QTX_EXPORT _declspec( dllexport )
+#  else
+#    define QTX_EXPORT _declspec( dllimport )
+#  endif
 #else
-#define QTX_EXPORT  
-#endif
-#else
-#if defined WIN32
-#define QTX_EXPORT _declspec( dllimport )
-#else
-#define QTX_EXPORT  
-#endif
+#  define QTX_EXPORT  
 #endif
 
 #if defined SOLARIS
 #define true  1
 #endif
 
-#define QT_VER 4
-
-#include <Qt/qnamespace.h>
+#include <QString>
+#include <QList>
+#include <QColor>
+#include <QImage>
+#include <QPixmap>
 
-#include <QtGui/qcolor.h>
-#include <QtGui/qimage.h>
-#include <QtGui/qpixmap.h>
-
-class QMenu;
 class QObject;
-class QString;
 class QWidget;
-class QToolBar;
-
-template <class> class QList;
-
-typedef QList<int>    QIntList;
-typedef QList<short>  QShortList;
-typedef QList<double> QDoubleList;
+class QCompleter;
 
-/*!
-  \class Qtx
-  \brief Set of auxiliary static methods
-*/
+typedef QList<int>    QIntList;       //!< list of int values
+typedef QList<short>  QShortList;     //!< list of short int values
+typedef QList<double> QDoubleList;    //!< list of double values
+typedef QList<QColor> QColorList;     //!< list of colors
 
-#ifndef QT_MOC_RUN
 class QTX_EXPORT Qtx
-#else
-class QTX_EXPORT Qtx : public Qt
-#endif
 {
 public:
-  enum AlignmentFlags
+  //! Widget alignment flags
+  typedef enum
   {
-    AlignLeft = Qt::AlignLeft,
-    AlignLeading = Qt::AlignLeading,
-    AlignRight = Qt::AlignRight,
-    AlignTrailing = Qt::AlignTrailing,
-    AlignHCenter = Qt::AlignHCenter,
-    AlignJustify = Qt::AlignJustify,
-    AlignAbsolute = Qt::AlignAbsolute,
-    AlignHorizontal_Mask = Qt::AlignHorizontal_Mask,
-
-    AlignTop = Qt::AlignTop,
-    AlignBottom = Qt::AlignBottom,
-    AlignVCenter = Qt::AlignVCenter,
-    AlignVertical_Mask = Qt::AlignVertical_Mask,
-
-    AlignCenter = Qt::AlignCenter,
-
-    AlignOutLeft   = Qt::AlignVCenter  << 2,
-    AlignOutRight  = AlignOutLeft  << 2,
-    AlignOutTop    = AlignOutRight << 2,
-    AlignOutBottom = AlignOutTop   << 2
-  };
-
-  static QString toQString( const char*, const int = -1 );
-  static QString toQString( const short*, const int = -1 );
-  static QString toQString( const unsigned char*, const int = -1 );
-  static QString toQString( const unsigned short*, const int = -1 );
-
-  static void    setTabOrder( QWidget*, ... );
-  static void    setTabOrder( const QWidgetList& );
-  static void    alignWidget( QWidget*, const QWidget*, const int );
-
-//  static void    simplifySeparators( QToolBar* );
-  static void    simplifySeparators( QWidget*, const bool = true );
-
-  static bool    isParent( QObject*, QObject* );
-
-  static QString dir( const QString&, const bool = true );
-  static QString file( const QString&, const bool = true );
-  static QString extension( const QString&, const bool = false );
-
-  static QString library( const QString& );
-
-  static QString tmpDir();
-  static bool    mkDir( const QString& );
-  static bool    rmDir( const QString& );
-  static bool    dos2unix( const QString& );
-  static QString addSlash( const QString& );
-
-  static int     rgbSet( const QColor& );
-  static int     rgbSet( const int, const int, const int );
-
-  static QColor  rgbSet( const int );
-  static void    rgbSet( const int, int&, int&, int& );
-
-  static QColor  scaleColor( const int, const int, const int );
-  static void    scaleColors( const int, QList<QColor>& );
-
-  static QImage  grayscale( const QImage& );
-  static QPixmap grayscale( const QPixmap& );
-  static QImage  transparentImage( const int, const int, const int = -1 );
-  static QPixmap transparentPixmap( const int, const int, const int = -1 );
-  static QPixmap composite( const QPixmap&, const int, const int, const QPixmap& = QPixmap() );
+    AlignLeft            = Qt::AlignLeft,            //!< align left side of one widget to the left side of another widget
+    AlignLeading         = Qt::AlignLeading,         //!< synonim for AlignLeft
+    AlignRight           = Qt::AlignRight,           //!< align right side of one widget to the right side of another widget
+    AlignTrailing        = Qt::AlignTrailing,        //!< synonim for AlignRight
+    AlignHCenter         = Qt::AlignHCenter,         //!< align one widget to the center of another widget in horizontal dimension
+    AlignJustify         = Qt::AlignJustify,         //!< synonym of Qt::AlignJustify
+    AlignAbsolute        = Qt::AlignAbsolute,        //!< synonym of Qt::AlignAbsolute
+    AlignHorizontal_Mask = Qt::AlignHorizontal_Mask, //!< synonym of Qt::AlignHorizontal_Mask
+
+    AlignTop             = Qt::AlignTop,             //!< align top side of one widget to the top side of another widget
+    AlignBottom          = Qt::AlignBottom,          //!< align bottom side of one widget to the bottom side of another widget
+    AlignVCenter         = Qt::AlignVCenter,         //!< align one widget to the center of another widget in vertical dimension
+    AlignVertical_Mask   = Qt::AlignVertical_Mask,   //!< synonym of Qt::AlignVertical_Mask
+
+    AlignCenter          = Qt::AlignCenter,          //!< align one widget to the center of another widget in both dimensions
+
+    AlignOutLeft         = Qt::AlignVCenter  << 2,   //!< align right side of one widget to the left side of another widget
+    AlignOutRight        = AlignOutLeft      << 2,   //!< align left side of one widget to the right side of another widget
+    AlignOutTop          = AlignOutRight     << 2,   //!< align bottom side of one widget to the top side of another widget
+    AlignOutBottom       = AlignOutTop       << 2    //!< align top side of one widget to the bottom side of another widget
+  } AlignmentFlags;
+
+  //! Path type, indicates required directory/file operation
+  typedef enum { 
+    PT_OpenFile,      //!< the file is opened
+    PT_SaveFile,      //!< the file is saved
+    PT_Directory      //!< the directory path is required
+  } PathType;
+
+  static QString     toQString( const char*, const int = -1 );
+  static QString     toQString( const short*, const int = -1 );
+  static QString     toQString( const unsigned char*, const int = -1 );
+  static QString     toQString( const unsigned short*, const int = -1 );
+
+  static void        setTabOrder( QWidget*, ... );
+  static void        setTabOrder( const QWidgetList& );
+  static void        alignWidget( QWidget*, const QWidget*, const int );
+
+  static void        simplifySeparators( QWidget*, const bool = true );
+
+  static bool        isParent( QObject*, QObject* );
+
+  static QString     dir( const QString&, const bool = true );
+  static QString     file( const QString&, const bool = true );
+  static QString     extension( const QString&, const bool = false );
+
+  static QString     library( const QString& );
+
+  static QString     tmpDir();
+  static bool        mkDir( const QString& );
+  static bool        rmDir( const QString& );
+  static bool        dos2unix( const QString& );
+  static QString     addSlash( const QString& );
+
+  static QCompleter* pathCompleter( const PathType, const QString& = QString() );
+
+  static int         rgbSet( const QColor& );
+  static int         rgbSet( const int, const int, const int );
+
+  static QColor      rgbSet( const int );
+  static void        rgbSet( const int, int&, int&, int& );
+
+  static QColor      scaleColor( const int, const int, const int );
+  static void        scaleColors( const int, QColorList& );
+
+  static QImage      grayscale( const QImage& );
+  static QPixmap     grayscale( const QPixmap& );
+  static QImage      transparentImage( const int, const int, const int = -1 );
+  static QPixmap     transparentPixmap( const int, const int, const int = -1 );
+  static QPixmap     composite( const QPixmap&, const int, const int, const QPixmap& = QPixmap() );
 };
 
 #endif
index 9da4b34173e2df7529fe2480c0690f2f44d266c9..1e46ce16d3d8d8231cec4cc9634468e53ed4cf79 100755 (executable)
 
 #include "QtxAction.h"
 
-#include <QtGui/qmenu.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qmenubar.h>
-#include <QtGui/qapplication.h>
+#include <QEvent>
+#include <QActionEvent>
+#include <QApplication>
 
 /*!
-       Name: QtxAction [public]
-       Desc: Constructs an action with given parent and name. If toggle is true the
-                 action will be a toggle action, otherwise it will be a command action.
+  \class QtxAction::ActionNotify
+  \brief Notify event used to signalize about event adding/removing.
+  \internal
 */
 
-QtxAction::QtxAction( QObject* parent, const char* name, bool toggle )
-: QAction( parent )
+class QtxAction::ActionNotify : public QEvent
+{
+public:
+  ActionNotify( bool add, QWidget* wid ) : QEvent( QEvent::User ), myAdd( add ), myWidget( wid ) {};
+  ~ActionNotify() {};
+
+  bool     isAdded() const { return myAdd; }
+  QWidget* widget() const { return myWidget; }
+
+private:
+  bool     myAdd;
+  QWidget* myWidget;
+};
+
+/*!
+  \class QtxAction
+  \brief Generic action class.
+
+  The class QtxAction inherits QWidgetAction class and can be used 
+  as base class when implementing any custom menu/toolbar actions.
+  It is necessary to subclass from QtxAction and redefine virtual 
+  callback methods addedTo(), removedFrom() (which are called automatically
+  when the action is added to the widget and removed from it) to customize
+  the action behavior.  
+*/
+
+/*!
+  \brief Constructor.
+
+  Creates an action owned by \a parent. 
+  Parameter \a toggle can be used to make the action checkable.
+
+  \param parent parent object
+  \param toggle if \c true the action will be a toggle action
+*/
+QtxAction::QtxAction( QObject* parent, bool toggle )
+: QWidgetAction( parent )
 {
-  setObjectName( name );
   setCheckable( toggle );
 
   QApplication::instance()->installEventFilter( this );
 }
 
 /*!
-       Name: QtxAction [public]
-       Desc: This constructor creates an action with the following properties: the
-                 description text, the icon or iconset icon, the menu text and keyboard
-                 accelerator. It is a child of given parent and named specified name.
-                 If toggle is true the action will be a toggle action, otherwise it will
-                 be a command action.
+  \brief Constructor.
+
+  Creates an action owned by \a parent. Parameters \a text,
+  \a icon, \a menuText and \a accel specify the action's attributes.
+  Parameter \a toggle can be used to make the action checkable.
+
+  \param text tooltip text
+  \param icon iconset
+  \param menuText menu text
+  \param accel shortcut key sequence
+  \param parent parent object
+  \param toggle if \c true the action will be a toggle action
 */
-
 QtxAction::QtxAction( const QString& text, const QIcon& icon,
-                      const QString& menuText, int accel,
-                      QObject* parent, const char* name, bool toggle )
-: QAction( icon, menuText, parent )
+                      const QString& menuText, int accel, QObject* parent, bool toggle )
+: QWidgetAction( parent )
 {
+  setIcon( icon );
+  setText( menuText );
   setToolTip( text );
   setShortcut( accel );
-  setObjectName( name );
   setCheckable( toggle );
 
   QApplication::instance()->installEventFilter( this );
 }
 
 /*!
-       Name: QtxAction [public]
-       Desc: This constructor creates an action with the following properties: the
-                 description text, the menu text and keyboard accelerator. It is a child
-                 of given parent and named specified name. If toggle is true the action
-                 will be a toggle action, otherwise it will be a command action.
-*/
+  \brief Constructor.
 
-QtxAction::QtxAction( const QString& text, const QString& menuText, int accel,
-                      QObject* parent, const char* name, bool toggle )
-: QAction( menuText, parent )
+  Creates an action owned by \a parent. Parameters \a text,
+  \a menuText and \a accel specify the action's attributes.
+  Parameter \a toggle can be used to make the action checkable.
+
+  \param text tooltip text
+  \param menuText menu text
+  \param accel shortcut key sequence
+  \param parent parent object
+  \param toggle if \c true the action is a toggle action
+*/
+QtxAction::QtxAction( const QString& text, const QString& menuText,
+                      int accel, QObject* parent, bool toggle )
+: QWidgetAction( parent )
 {
+  setText( menuText );
   setToolTip( text );
   setShortcut( accel );
-  setObjectName( name );
   setCheckable( toggle );
 
   QApplication::instance()->installEventFilter( this );
 }
 
 /*!
-       Name: ~QtxAction [virtual public]
-       Desc: Destructor.
+  \brief Destructor.
 */
-
 QtxAction::~QtxAction()
 {
 }
 
+/*!
+  \brief Customize action events.
+  
+  Sends a notification event to the action when it is added to 
+  the widget or removed from it in order to perform custom processing.
+
+  \param o object
+  \param e event
+  \return \c true if further event processing should be stopped
+  \sa customEvent(), addedTo(), removedFrom()
+*/
 bool QtxAction::eventFilter( QObject* o, QEvent* e )
 {
   if ( o && o->isWidgetType() )
   {
     if ( e->type() == QEvent::ActionAdded && ((QActionEvent*)e)->action() == this )
-      addedTo( (QWidget*)o );
+      QApplication::postEvent( this, new ActionNotify( true, (QWidget*)o ) );
     if ( e->type() == QEvent::ActionRemoved && ((QActionEvent*)e)->action() == this )
-      removedFrom( (QWidget*)o );
+      QApplication::postEvent( this, new ActionNotify( false, (QWidget*)o ) );
   }
-  return QAction::eventFilter( o, e );
+  return QWidgetAction::eventFilter( o, e );
 }
 
 /*!
-       Name: addTo [virtual public]
-       Desc: Adds this action to widget. Returns true if the action was added
-                 successfully and false otherwise.
-*/
+  \brief Called when the action is added to the widget.
 
-bool QtxAction::addTo( QWidget* w )
-{
-  if ( !w )
-    return false;
-
-  w->addAction( this );
-  return true;
-}
+  This method can be redefined in the subclasses to customize 
+  the action behavior. Base implementation does nothing. 
 
-/*!
-       Name: addTo [virtual public]
-       Desc: Adds this action to widget. If widget is QPopupMenu given index will
-                 be used for menu item inserting. Returns true if the action was added
-                 successfully and false otherwise.
+  \param w widget (should be menu or toolbar)
+  \sa removedFrom()
 */
-
-bool QtxAction::addTo( QWidget* w, const int index )
+void QtxAction::addedTo( QWidget* /*w*/ )
 {
-  if ( !w )
-    return false;
-
-  QAction* b = 0;
-  if ( 0 <= index && index < w->actions().count() )
-    b = w->actions().at( index );
-
-  w->insertAction( b, this );
-
-  return true;
 }
 
 /*!
-       Name: removeFrom [virtual public]
-       Desc: Removes this action from widget. Returns true if the action was removed
-                 successfully and false otherwise.
-*/
-
-bool QtxAction::removeFrom( QWidget* w )
-{
-  if ( !w )
-    return false;
+  \brief Called when the action is removed from the widget.
 
-  w->removeAction( this );
-  return true;
-}
+  This method can be redefined in the subclasses to customize
+  the action behavior. Base implementation does nothing.
 
-void QtxAction::addedTo( QWidget* )
+  \param w widget (should be menu or toolbar)
+  \sa addedTo()
+*/
+void QtxAction::removedFrom( QWidget* /*w*/ )
 {
 }
 
-void QtxAction::removedFrom( QWidget* )
+/*!
+  \brief Process notification events.
+  
+  Calls addedTo() method when the action is added to the widget
+  and removedFrom() when it is removed from the widget
+  in order to perform custom processing.
+
+  \param e noification event
+  \sa eventFilter(), addedTo(), removedFrom()
+*/
+void QtxAction::customEvent( QEvent* e )
 {
+  ActionNotify* ae = (ActionNotify*)e;
+  if ( ae->isAdded() )
+    addedTo( ae->widget() );
+  else
+    removedFrom( ae->widget() );
 }
index fa184e2c3dfed1768e132f1279dc141db6008edf..c1a20611041b6aae8faf735324a3abb0b24d308c 100755 (executable)
@@ -16,7 +16,7 @@
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-// File:      QtxAction.hxx
+// File:      QtxAction.h
 // Author:    Sergey TELKOV
 
 #ifndef QTXACTION_H
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtGui/qicon.h>
-#include <QtGui/qaction.h>
+#include <QWidgetAction>
+
+class QIcon;
 
 #ifdef WIN32
 #pragma warning ( disable:4251 )
 #endif
 
-class QMenu;
-
-class QTX_EXPORT QtxAction : public QAction
+class QTX_EXPORT QtxAction : public QWidgetAction
 {
   Q_OBJECT
 
+  class ActionNotify;
+
 public:
-  QtxAction( QObject* = 0, const char* = 0, bool = false );
-  QtxAction( const QString&, const QString&, int, QObject*, const char* = 0, bool = false );
-  QtxAction( const QString&, const QIcon&, const QString&, int, QObject*, const char* = 0, bool = false );
+  QtxAction( QObject* = 0, bool = false );
+  QtxAction( const QString&, const QString&, int, QObject*, bool = false );
+  QtxAction( const QString&, const QIcon&, const QString&, int, QObject*, bool = false );
   virtual ~QtxAction();
 
   virtual bool eventFilter( QObject*, QEvent* );
 
-  virtual bool addTo( QWidget* );
-  virtual bool addTo( QWidget*, const int );
-  virtual bool removeFrom( QWidget* );
-
 protected:
   virtual void addedTo( QWidget* );
   virtual void removedFrom( QWidget* );
+
+  virtual void customEvent( QEvent* );
 };
 
 #ifdef WIN32
index 78a3f582600c173f6627051d5dac80dc0d1c648e..f3b42a46d829c7879991961141d158c82fe3705a 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      QtxActionMenuMgr.cxx
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #include "QtxActionMenuMgr.h"
 
 #include "QtxAction.h"
 
-#include <QtCore/qlist.h>
-#include <QtCore/qfile.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qwidget.h>
-#include <QtGui/qmenubar.h>
-#include <QtGui/qmainwindow.h>
-
-#include <QtXml/qdom.h>
-
-// VSR: Uncomment this #define in order to allow dynamic menus support
-// (emit signals when popup menu is pre-activated)
-// Currently this support is disabled.
-//#define ENABLE_DYNAMIC_MENU
+#include <QMenu>
+#include <QMenuBar>
+#include <QWidget>
+#include <QMainWindow>
 
 /*!
-       Service functions
-       Level: Internal
-*/
-namespace {
-/*
-  QList<int> prepareIds( const QWidget* w )
-  {
-    QList<int> l;
-    const QMenuData* md = 0;
-    if ( w->inherits( "QMenuBar" ) )
-      md = ::qt_cast<QMenuBar*>( w );
-    else if ( w->inherits( "QPopupMenu" ) )
-      md = ::qt_cast<QPopupMenu*>( w );
-    if ( md )
-    {
-      for ( uint i = 0; i < md->count(); i++ )
-             l.append( md->idAt( i ) );
-    }
-    return l;
-  }
-
-  int getNewId( const QWidget* w, const QValueList<int>& l, bool retId = true )
-  {
-    const QMenuData* md = 0;
-    if ( w->inherits( "QMenuBar" ) )
-      md = ::qt_cast<QMenuBar*>( w );
-    else if ( w->inherits( "QPopupMenu" ) )
-      md = ::qt_cast<QPopupMenu*>( w );
-    if ( md )
-    {
-      for ( uint i = 0, j = 0; i < md->count() && j < l.count(); i++, j++ )
-             if ( md->idAt( i ) != l[ j ] )
-          return retId ? md->idAt( i ) : i;
-      if ( md->count() > l.count() )
-        return retId ? md->idAt( md->count()-1 ) : md->count() - 1;
-    }
-    return -1;
-  }
-
-  void dumpMenu( QWidget* w, bool before )
-  {
-    if ( !w )
-      return;
-
-    QMenuData* md = 0;
-    if ( w->inherits( "QMenuBar" ) )
-      md = ::qt_cast<QMenuBar*>( w );
-    else if ( w->inherits( "QPopupMenu" ) )
-      md = ::qt_cast<QPopupMenu*>( w );
-
-    if ( !md )
-      return;
-
-    printf( ">>> start dump menu (%s) >>>\n", before ? "before" : "after" );
-    for ( uint i = 0; i < md->count(); i++ )
-      printf( "%d: %d: %s\n", i, md->idAt( i ), md->text( md->idAt( i ) ).latin1() );
-    printf( "<<< end dump menu (%s) <<<\n", before ? "before" : "after" );
-  }
+  \class QtxActionMenuMgr::MenuNode
+  \brief Represents a menu item inside main menu structure.
+  \internal
 */
-};
 
-/*!
-       Class: QtxActionMenuMgr::MenuAction
-       Level: Internal
-*/
-
-class QtxActionMenuMgr::MenuAction : public QtxAction
+class QtxActionMenuMgr::MenuNode
 {
 public:
-  MenuAction( const QString&, const QString&, QObject*, const int = -1, const bool = false );
-  virtual ~MenuAction();
-
-private:
-  int          myId;
-  bool         myEmptyEnabled;
+  MenuNode();
+  MenuNode( MenuNode*, const int, const int, const int );
+  ~MenuNode();
+  
+  MenuNode* parent;       //!< parent menu node
+  int       id;           //!< menu nodeID
+  int       idx;          //!< menu node index 
+  int       group;        //!< menu group ID
+  bool      visible;      //!< visibility status
+  NodeList  children;     //!< children menu nodes list
 };
 
 /*!
-  Constructor for menu action
-  \param text - description text
-  \param menutext - menu text
-  \param parent - parent object
-  \param id - integer identificator of action
-  \param allowEmpty - if it is true, it makes possible to add this action with empty popup to menu
-*/
-/*
-QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, const QString& menuText,
-                                                                       QObject* parent, const int id, const bool allowEmpty )
-: QtxAction( text, menuText, 0, parent ),
-myId( id ),
-myPopup( 0 ),
-myEmptyEnabled( allowEmpty )
+  \brief Default constructor.
+  \internal
+*/
+QtxActionMenuMgr::MenuNode::MenuNode()
+: parent( 0 ), id( -1 ), idx( -1 ), group( -1 ), visible( true )
 {
-  myPopup = new QMenu();
 }
-*/
+
 /*!
-  Destructor: deletes internal popup
-*/
-/*
-QtxActionMenuMgr::MenuAction::~MenuAction()
+  \brief Constructor.
+  \internal
+  \param p parent menu node
+  \param _id menu node ID
+  \param _idx menu node index
+  \param _group menu node group ID
+*/
+QtxActionMenuMgr::MenuNode::MenuNode( MenuNode* p,
+                                     const int _id,
+                                     const int _idx,
+                                     const int _group )
+: parent( p ), id( _id ), idx( _idx ), group( _group ), visible( true )
 {
-  delete myPopup;
+  if ( p )
+    p->children.append( this );
 }
-*/
+
 /*!
-  Adds action to widget, for example, to popup menu or menu bar
+  \brief Destructor.
+  \internal
 */
-/*
-bool QtxActionMenuMgr::MenuAction::addTo( QWidget* w )
+QtxActionMenuMgr::MenuNode::~MenuNode()
 {
-  if ( !w )
-    return false;  // bad widget
-
-  if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) )
-    return false;  // not allowed widget type
-
-  if ( myIds.find( w ) != myIds.end() )
-    return false;  // already added
-
-  if ( !myPopup )
-    return false;  // bad own popup menu
-
-  if ( !myEmptyEnabled && !myPopup->actions().count() )
-    return false;  // not allowed empty menu
-
-  if ( w->inherits( "QPopupMenu" )  )
-  {
-    QValueList<int> l = prepareIds( w );
-    int idx;
-    if ( QtxAction::addTo( w ) && ( idx = getNewId( w, l, false ) ) != -1 )
-    {
-      QPopupMenu* pm = (QPopupMenu*)w;
-      myIds[ w ] = pm->idAt( idx );
-      if ( myId != -1 )
-             pm->setId( idx, myId );
-      setPopup( pm, myId != -1 ? myId : myIds[ w ], myPopup );
-    }
-  }
-  else if ( w->inherits( "QMenuBar" ) )
-  {
-    QValueList<int> l = prepareIds( w );
-    int idx;
-    if ( QtxAction::addTo( w ) && ( idx = getNewId( w, l, false ) ) != -1 )
-    {
-      QMenuBar* mb = (QMenuBar*)w;
-      myIds[ w ] = mb->idAt( idx );
-      if ( myId != -1 )
-         mb->setId( idx, myId );
-      setPopup( mb, myId != -1 ? myId : myIds[ w ], myPopup );
-    }
-
-  }
-  else
-    return false;
-
-  return true;
+  for ( NodeList::iterator it = children.begin(); it != children.end(); ++it )
+    delete *it;
 }
-*/
 
 /*!
-  Removes action from widget, for example, from popup menu or menu bar
-*/
-/*
-bool QtxActionMenuMgr::MenuAction::removeFrom( QWidget* w )
-{
-  if ( !w )
-    return false;  // bad widget
+  \class QtxActionMenuMgr
+  \brief Main menu actions manager.
 
-  if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) )
-    return false;  // not allowed widget type
+  Menu manager allows using of set of action for automatic generating of
+  application main menu and dynamic update of its contents.
 
-  if ( myIds.find( w ) == myIds.end() )
-    return false;  // not yet added
+  Use insert(), append() and remove() methods to create main menu.
+  Methods show(), hide() allow displaying/erasing of specified menu items.
 
-  if ( w->inherits( "QPopupMenu" ) )
-  {
-    if ( myId != -1 )
-    {
-      QPopupMenu* pm = (QPopupMenu*)w;
-      int idx = pm->indexOf( myId );
-      if ( idx != -1 )
-        pm->setId( idx, myIds[ w ] );
-    }
-    myIds.remove( w );
-    return QtxAction::removeFrom( w );;
-  }
-  else if ( w->inherits( "QMenuBar" ) )
-  {
-    if ( myId != -1 )
-    {
-      QMenuBar* mb = (QMenuBar*)w;
-      int idx = mb->indexOf( myId );
-      if ( idx != -1 )
-        mb->setId( idx, myIds[ w ] );
-    }
-    myIds.remove( w );
-    return QtxAction::removeFrom( w );
-  }
-  return false;
-}
-*/
+  Actions can be grouped with help of group identificator. Inside the popup
+  or main menu bar menu items are ordered by the group identifier (ascending).
 
-/*!
-  \return internal popup of action
-*/
-/*
-QMenu* QtxActionMenuMgr::MenuAction::popup() const
-{
-  return myPopup;
-}
+  Menu manager automatically optimizes the menu by removing extra separators,
+  hiding empty popup menus etc.
 */
 
 /*!
-       Class: QtxActionMenuMgr
-       Level: Public
+  \brief Constructor.
+  \param p parent main window
 */
 QtxActionMenuMgr::QtxActionMenuMgr( QMainWindow* p )
-: QtxActionMgr( p ),
-myMenu( p ? p->menuBar() : 0 )
+: QtxActionMgr( p ), 
+  myRoot( new MenuNode() ),
+  myMenu( p ? p->menuBar() : 0 )
 {
-  myRoot.id = -1;
-  myRoot.group = -1;
-
   if ( myMenu ) {
     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
-#ifdef ENABLE_DYNAMIC_MENU
-    if ( myMenu->inherits( "QMenuBar" ) )
-      connect( myMenu, SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) );
-#endif
   }
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param mw menu widget
+  \param p parent object
 */
 QtxActionMenuMgr::QtxActionMenuMgr( QWidget* mw, QObject* p )
-: QtxActionMgr( p ),
-myMenu( mw )
+: QtxActionMgr( p ), 
+  myRoot( new MenuNode() ),
+  myMenu( mw )
 {
-  myRoot.id = -1;
-  myRoot.group = -1;
-
-  if ( myMenu )
+  if ( myMenu ) {
     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+  }
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionMenuMgr::~QtxActionMenuMgr()
 {
-  for ( NodeList::iterator it = myRoot.children.begin(); it != myRoot.children.end() && myMenu; ++it )
+  for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr )
   {
-    QAction* a = itemAction( (*it)->id );
-    if ( !a )
-      a = menuAction( (*it)->id );
-
-//    if ( a )
-//      a->removeFrom( myMenu );
+    delete itr.value()->menu();
+    delete itr.value();
   }
 
-  for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr )
-    delete itr.value();
+  delete myRoot;
 }
 
 /*!
-  \return whether menu item corresponding to action is visible
-  \param actId - identificator of action
-  \param place - identificator of some parent action
+  \brief Check if an action with \a actId identifier is visible to
+  the parent action with \a place identifier.
+  \param actId action ID
+  \param place some parent action ID
+  \return \c true if an action is visible to the parent
+  \sa setVisible()
 */
 bool QtxActionMenuMgr::isVisible( const int actId, const int place ) const
 {
@@ -317,10 +161,11 @@ bool QtxActionMenuMgr::isVisible( const int actId, const int place ) const
 }
 
 /*!
-  Sets visible state of action
-  \param actId - identificator of action
-  \param place - identificator of some parent action
-  \param v - visibility state
+  \brief Set action's visibility flag.
+  \param actId action ID
+  \param place some parent action ID
+  \param v new visibility state
+  \sa isVisible()
 */
 void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool v )
 {
@@ -330,12 +175,18 @@ void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool
 }
 
 /*!
-  Insert action as children menu item
-  \param id - identificator of action
-  \param menus - few names of parent menu items, separated by '|'. It means sequence of menu items,
-  for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created.
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu name: it can be a sequence of strings, separated by '|' symbol.
+  For example, "File|Edit" means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param id action ID
+  \param menus menu name
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( const int id, const QString& menus, const int group, const int idx )
 {
@@ -343,12 +194,18 @@ int QtxActionMenuMgr::insert( const int id, const QString& menus, const int grou
 }
 
 /*!
-  Insert action as children menu item
-  \param a - action
-  \param menus - few names of parent menu items, separated by '|'. It means sequence of menu items,
-  for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created.
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu name: it can be a sequence of strings, separated by '|' symbol.
+  For example, "File|Edit" means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param a action
+  \param menus menu name
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( QAction* a, const QString& menus, const int group, const int idx )
 {
@@ -356,12 +213,19 @@ int QtxActionMenuMgr::insert( QAction* a, const QString& menus, const int group,
 }
 
 /*!
-  Insert action as children menu item
-  \param id - identificator of action
-  \param menus - list of names of parent menu items, separated by |. It means sequence of menu items,
-  for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created.
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu names list.
+  For example, string list consisting from two items "File" and "Edit"
+  means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param id action ID
+  \param menus menu names list
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int group, const int idx )
 {
@@ -373,12 +237,19 @@ int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int
 }
 
 /*!
-  Insert action as children menu item
-  \param a - action
-  \param menus - list of names of parent menu items. It means sequence of menu items,
-  for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created.
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu names list.
+  For example, string list consisting from two items "File" and "Edit"
+  means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param a action
+  \param menus menu names list
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int group, const int idx )
 {
@@ -390,40 +261,36 @@ int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int gr
 }
 
 /*!
-  Insert action as children menu item
-  \param id - identificator of action
-  \param pId - identificator of action corresponding to parent menu item
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+  \param id action ID
+  \param pId parent menu action ID
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( const int id, const int pId, const int group, const int idx )
 {
   if ( id == -1 )
     return -1;
 
-  MenuNode* pNode = pId == -1 ? &myRoot : find( pId );
+  MenuNode* pNode = pId == -1 ? myRoot : find( pId );
   if ( !pNode )
     return -1;
 
-  MenuNode* node = new MenuNode( pNode );
-  node->id = id;
-  node->idx = idx;
-  node->group = group;
-
-  pNode->children.append( node );
+  MenuNode* node = new MenuNode( pNode, id, idx, group );
 
   triggerUpdate( pNode->id, false );
 
-
   return node->id;
 }
 
 /*!
-  Insert action as children menu item
-  \param a - action
-  \param pId - identificator of action corresponding to parent menu item
-  \param group - group identificator
-  \param idx - index inside Qt menu
+  \brief Insert action to the menu.
+  \param a action
+  \param pId parent menu action ID
+  \param group group ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
 int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const int idx )
 {
@@ -431,18 +298,17 @@ int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const
 }
 
 /*!
-  Create and insert action as children menu item
-  \return identificator of inserted action
-  \param title - menu text of action
-  \param pId - identificator of action corresponding to parent menu item
-  \param group - group identificator
-  \param id - identificator of new action
-  \param idx - index inside Qt menu
-  \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu
-*/
-int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int id, const int idx, const bool allowEmpty )
+  \brief Create and insert menu item action to the menu.
+  \param title menu text
+  \param pId parent menu action ID
+  \param group group ID
+  \param id action ID
+  \param idx menu index inside the menu group
+  \return action ID
+*/
+int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int id, const int idx )
 {
-  MenuNode* pNode = pId == -1 ? &myRoot : find( pId );
+  MenuNode* pNode = pId == -1 ? myRoot : find( pId );
   if ( !pNode )
     return -1;
 
@@ -462,20 +328,12 @@ int QtxActionMenuMgr::insert( const QString& title, const int pId, const int gro
   int gid = (id == -1 || eNode ) ? generateId() : id;
 
   QAction* ma = new QAction( title, this );
-  ma->setMenu( new QMenu( myMenu ) );
+  ma->setMenu( new QMenu( 0 ) );
 
   connect( ma->menu(), SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
   connect( ma->menu(), SIGNAL( aboutToHide() ), this, SLOT( onAboutToHide() ) );
-#ifdef ENABLE_DYNAMIC_MENU
-  connect( ma->menu(), SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) );
-#endif
-
-  MenuNode* node = new MenuNode( pNode );
-  node->group = group;
-  node->idx = idx;
-  node->id = myMenus.insert( gid, ma ).key();
 
-  pNode->children.append( node );
+  MenuNode* node = new MenuNode( pNode, myMenus.insert( gid, ma ).key(), idx, group );
 
   triggerUpdate( pNode->id, false );
 
@@ -483,56 +341,66 @@ int QtxActionMenuMgr::insert( const QString& title, const int pId, const int gro
 }
 
 /*!
-  Create and insert action as children menu item
-  \return identificator of inserted action
-  \param title - menu text of action
-  \param menus - string list of parents' menu texts, separated by |
-  \param group - group identificator
-  \param id - identificator of new action
-  \param idx - index inside Qt menu
-  \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu
+  \brief Create and insert menu item action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu name: it can be a sequence of strings, separated by '|' symbol.
+  For example, "File|Edit" means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param title menu text
+  \param menus menu name
+  \param group group ID
+  \param id action ID
+  \param idx menu index inside the menu group
+  \return action ID
 */
-int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int id, const int idx, const bool allowEmpty )
+int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int id, const int idx )
 {
-  return insert( title, menus.split( "|", QString::SkipEmptyParts ), group, id, idx, allowEmpty );
+  return insert( title, menus.split( "|", QString::SkipEmptyParts ), group, id, idx );
 }
 
 /*!
-  Create and insert action as children menu item
-  \return identificator of inserted action
-  \param title - menu text of action
-  \param menus - list of parents menu items
-  \param group - group identificator
-  \param id - identificator of new action
-  \param idx - index inside Qt menu
-  \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu
-*/
-int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int id, const int idx, const bool allowEmpty )
+  \brief Create and insert menu item action to the menu.
+
+  Insert an action to the named menu. The \a menus parameter represents 
+  the menu names list.
+  For example, string list consisting from two items "File" and "Edit"
+  means \c File->Edit submenu.
+  If submenu doesn't exist, it will be created.
+
+  \param title menu text
+  \param menus menu names list
+  \param group group ID
+  \param id action ID
+  \param idx menu index inside the menu group
+  \return action ID
+*/
+int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int id, const int idx )
 {
   int pId = createMenu( menus, -1 );
-  return insert( title, pId, group, id, idx, allowEmpty );
+  return insert( title, pId, group, id, idx );
 }
 
 /*!
-  Create and append action as last children
-  \return identificator of inserted action
-  \param title - menu text of action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
-  \param id - identificator of new action
-  \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu
-*/
-int QtxActionMenuMgr::append( const QString& title, const int pId, const int group, const int id, const bool allowEmpty )
+  \brief Create and add menu item action to the end of menu.
+  \param title menu text
+  \param pId parent menu action ID
+  \param group group ID
+  \param id action ID
+  \return action ID
+*/
+int QtxActionMenuMgr::append( const QString& title, const int pId, const int group, const int id )
 {
-  return insert( title, pId, group, id, allowEmpty );
+  return insert( title, pId, group, id );
 }
 
 /*!
-  Create and append action as last children
-  \return identificator of inserted action
-  \param id - identificator of existing action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
+  \brief Create and add menu item action to the end of menu.
+  \param id action ID
+  \param pId parent menu action ID
+  \param group group ID
+  \return action ID
 */
 int QtxActionMenuMgr::append( const int id, const int pId, const int group )
 {
@@ -540,11 +408,11 @@ int QtxActionMenuMgr::append( const int id, const int pId, const int group )
 }
 
 /*!
-  Create and append action as last children
-  \return identificator of inserted action
-  \param a - action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
+  \brief Create and add menu item action to the end of menu.
+  \param a action
+  \param pId parent menu action ID
+  \param group group ID
+  \return action ID
 */
 int QtxActionMenuMgr::append( QAction* a, const int pId, const int group )
 {
@@ -552,25 +420,24 @@ int QtxActionMenuMgr::append( QAction* a, const int pId, const int group )
 }
 
 /*!
-  Create and insert action as first children
-  \return identificator of inserted action
-  \param title - menu text of action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
-  \param id - identificator of new action
-  \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu
-*/
-int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group, const int id, const bool allowEmpty )
+  \brief Create and add menu item action to the beginning of menu.
+  \param title menu text
+  \param pId parent menu action ID
+  \param group group ID
+  \param id action ID
+  \return action ID
+*/
+int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group, const int id )
 {
-  return insert( title, pId, group, id, 0, allowEmpty );
+  return insert( title, pId, group, id, 0 );
 }
 
 /*!
-  Create and insert action as last children
-  \return identificator of inserted action
-  \param id - identificator of existing action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
+  \brief Create and add menu item action to the beginning of menu.
+  \param id action ID
+  \param pId parent menu action ID
+  \param group group ID
+  \return action ID
 */
 int QtxActionMenuMgr::prepend( const int id, const int pId, const int group )
 {
@@ -578,11 +445,11 @@ int QtxActionMenuMgr::prepend( const int id, const int pId, const int group )
 }
 
 /*!
-  Create and insert action as last children
-  \return identificator of inserted action
-  \param a - action
-  \param pId - id of action corresponding to parent menu item
-  \param group - group identificator
+  \brief Create and add menu item action to the beginning of menu.
+  \param a action
+  \param pId parent menu action ID
+  \param group group ID
+  \return action ID
 */
 int QtxActionMenuMgr::prepend( QAction* a, const int pId, const int group )
 {
@@ -590,8 +457,8 @@ int QtxActionMenuMgr::prepend( QAction* a, const int pId, const int group )
 }
 
 /*!
-  Removes menu item corresponding to action
-  \param id - identificator of action
+  \brief Remove menu item with given \a id.
+  \param id menu action ID
 */
 void QtxActionMenuMgr::remove( const int id )
 {
@@ -600,14 +467,14 @@ void QtxActionMenuMgr::remove( const int id )
 }
 
 /*!
-  Removes menu item
-  \param id - identificator of action
-  \param pId - identificator of action corresponding to parent menu item
-  \param group - group identificator
+  \brief Remove menu item with given \a id.
+  \param id menu action ID
+  \param pId parent menu action ID
+  \param group group ID
 */
 void QtxActionMenuMgr::remove( const int id, const int pId, const int group )
 {
-  MenuNode* pNode = pId == -1 ? &myRoot : find( pId );
+  MenuNode* pNode = pId == -1 ? myRoot : find( pId );
   if ( !pNode )
     return;
 
@@ -625,8 +492,9 @@ void QtxActionMenuMgr::remove( const int id, const int pId, const int group )
 }
 
 /*!
-  Shows menu item corresponding to action
-  \param id - identificator of action
+  \brief Show menu item with given \a id.
+  \param id menu action ID
+  \sa hide()
 */
 void QtxActionMenuMgr::show( const int id )
 {
@@ -634,8 +502,9 @@ void QtxActionMenuMgr::show( const int id )
 }
 
 /*!
-  Hides menu item corresponding to action
-  \param id - identificator of action
+  \brief Hide menu item with given \a id.
+  \param id menu action ID
+  \sa show()
 */
 void QtxActionMenuMgr::hide( const int id )
 {
@@ -643,8 +512,10 @@ void QtxActionMenuMgr::hide( const int id )
 }
 
 /*!
-  \return shown status of menu item corresponding to action
-  \param id - identificator of action
+  \brief Get visibility status for menu item with given \a id.
+  \param id menu action ID
+  \return \c true if an item is shown
+  \sa setShown()
 */
 bool QtxActionMenuMgr::isShown( const int id ) const
 {
@@ -656,9 +527,10 @@ bool QtxActionMenuMgr::isShown( const int id ) const
 }
 
 /*!
-  Sets shown status of menu item corresponding to action
-  \param id - identificator of action
-  \param on - new shown status
+  \brief Set visibility status for menu item with given \a id.
+  \param id menu action ID
+  \param on new visibility status
+  \sa isShown()
 */
 void QtxActionMenuMgr::setShown( const int id, const bool on )
 {
@@ -670,13 +542,15 @@ void QtxActionMenuMgr::setShown( const int id, const bool on )
     if ( (*it)->visible != on )
     {
       (*it)->visible = on;
-      triggerUpdate( (*it)->parent ? (*it)->parent->id : myRoot.id, false );
+      triggerUpdate( (*it)->parent ? (*it)->parent->id : myRoot->id, false );
     }
   }
 }
 
 /*!
-  Changes the specified menu title
+  \brief Change menu title for the action with given \a id.
+  \param id menu action ID
+  \param title new menu title
 */
 void QtxActionMenuMgr::change( const int id, const QString& title )
 {
@@ -685,6 +559,11 @@ void QtxActionMenuMgr::change( const int id, const QString& title )
     a->setText( title );
 }
 
+/*!
+  \brief Called when the submenu is about to show.
+  
+  Emits the signal menuAboutToShow(QMenu*).
+*/
 void QtxActionMenuMgr::onAboutToShow()
 {
   QMenu* m = ::qobject_cast<QMenu*>( sender() );
@@ -692,6 +571,11 @@ void QtxActionMenuMgr::onAboutToShow()
     emit menuAboutToShow( m );
 }
 
+/*!
+  \brief Called when the submenu is about to hide.
+  
+  Emits the signal menuAboutToHide(QMenu*).
+*/
 void QtxActionMenuMgr::onAboutToHide()
 {
   QMenu* m = ::qobject_cast<QMenu*>( sender() );
@@ -700,7 +584,11 @@ void QtxActionMenuMgr::onAboutToHide()
 }
 
 /*!
-  SLOT: called when corresponding menu is destroyed, clears internal pointer to menu
+  \brief Called when the corresponding menu object is destroyed.
+
+  Clears internal pointer to menu to disable crashes.
+  
+  \param obj (menu) object being destroyed
 */
 void QtxActionMenuMgr::onDestroyed( QObject* obj )
 {
@@ -708,39 +596,33 @@ void QtxActionMenuMgr::onDestroyed( QObject* obj )
     myMenu = 0;
 }
 
+
+/*!
+  \fn void QtxActionMenuMgr::menuAboutToShow( QMenu* m )
+  \brief Emitted when the menu is about to be shown.
+  \param m menu being shown
+*/
+
+/*!
+  \fn void QtxActionMenuMgr::menuAboutToHide( QMenu* m )
+  \brief Emitted when the menu is about to be hidden.
+  \param m menu being hidden
+*/
+
 /*!
-  SLOT: called when menu item is highlighted
+  \brief Get the menu widget.
+  \return menu widget (QMenuBar)
 */
-void QtxActionMenuMgr::onHighlighted( int id )
+QWidget* QtxActionMenuMgr::menuWidget() const
 {
-  const QObject* snd = sender();
-  int pid = 0, realId;
-  if ( myMenu && snd == myMenu )
-    pid = -1;
-  else
-  {
-    for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr )
-    {
-      if ( itr.value()->menu() && itr.value()->menu() == snd )
-             pid = itr.key();
-    }
-  }
-  if ( pid )
-  {
-    realId = findId( id, pid );
-    if ( realId != -1 )
-    {
-      emit menuHighlighted( pid, realId );
-      triggerUpdate( realId );
-    }
-  }
+  return myMenu;
 }
 
 /*!
-  Assignes new menu with manager
-  \param mw - new menu
+  \brief Assign new menu widget to the menu manager.
+  \param mw new menu widget
 */
-void QtxActionMenuMgr::setWidget( QWidget* mw )
+void QtxActionMenuMgr::setMenuWidget( QWidget* mw )
 {
   if ( myMenu == mw )
     return;
@@ -752,29 +634,33 @@ void QtxActionMenuMgr::setWidget( QWidget* mw )
 
   if ( myMenu )
     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+
+  triggerUpdate( -1, true );
 }
 
 /*!
-  \return menu node by it's place description
-  \param actId - identificator of action
-  \param pId - identificator of action corresponding to start menu item
-  \param rec - recursive search
+  \brief Search menu node.
+  \param id menu action ID
+  \param pId parent menu item ID
+  \param rec if \c true perform recursive search
+  \return menu node or 0 if it is not found
 */
-QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int actId, const int pId, const bool rec ) const
+QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, const int pId, const bool rec ) const
 {
-  return find( actId, find( pId ), rec );
+  return find( id, find( pId ), rec );
 }
 
 /*!
-  \return menu node by it's place description
-  \param actId - identificator of action
-  \param startNode - start menu item
-  \param rec - recursive search
+  \brief Search menu node.
+  \param id menu action ID
+  \param startNode start menu node (if 0, search from root node)
+  \param rec if \c true perform recursive search
+  \return menu node or 0 if it is not found
 */
 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode, const bool rec ) const
 {
   MenuNode* node = 0;
-  MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
+  MenuNode* start = startNode ? startNode : myRoot;
   for ( NodeList::iterator it = start->children.begin(); it != start->children.end() && !node; ++it )
   {
     if ( (*it)->id == id )
@@ -786,15 +672,15 @@ QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* star
 }
 
 /*!
-  Finds menu node
-  \return true if at least one node is found
-  \param id - identificator of action
-  \param lst - list to be filled with found nodes
-  \param startNode - start menu item
+  \brief Search recursively all menu nodes with given \a id.
+  \param id menu action ID
+  \param NodeList resulting list of menu nodes
+  \param startNode start menu node (if 0, search from root node)
+  \return \c true if at least one node is found
 */
 bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) const
 {
-  MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
+  MenuNode* start = startNode ? startNode : myRoot;
   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
   {
     MenuNode* node = *it;
@@ -807,11 +693,11 @@ bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode )
 }
 
 /*!
-  Finds menu node
-  \return menu node
-  \param title - menu text of searched node
-  \param pId - id of action corresponding to start menu item
-  \param rec - recursive searching
+  \brief Search menu node.
+  \param title menu item title
+  \param pId parent menu item ID
+  \param rec if \c true perform recursive search
+  \return menu node or 0 if it is not found
 */
 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, const int pId, const bool rec ) const
 {
@@ -819,15 +705,15 @@ QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, const
 }
 
 /*!
-  Finds menu node
-  \return true if at least one node is found
-  \param title - menu text of node
-  \param lst - list to be filled with found nodes
-  \param startNode - start menu item
+  \brief Search recursively all menu nodes with given \a title.
+  \param title menu item title
+  \param NodeList resulting list of menu nodes
+  \param startNode start menu node (if 0, search from root node)
+  \return \c true if at least one node is found
 */
 bool QtxActionMenuMgr::find( const QString& title, NodeList& lst, MenuNode* startNode ) const
 {
-  MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
+  MenuNode* start = startNode ? startNode : myRoot;
   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
   {
     QAction* a = itemAction( (*it)->id );
@@ -842,16 +728,16 @@ bool QtxActionMenuMgr::find( const QString& title, NodeList& lst, MenuNode* star
 }
 
 /*!
-  Finds menu node
-  \return menu node
-  \param title - menu text of searched node
-  \param startNode - start menu item
-  \param rec - recursive searching
+  \brief Search menu node.
+  \param title menu item title
+  \param startNode start menu node (if 0, search from root node)
+  \param rec if \c true perform recursive search
+  \return menu node or 0 if it is not found
 */
 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, MenuNode* startNode, const bool rec ) const
 {
   MenuNode* node = 0;
-  MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot;
+  MenuNode* start = startNode ? startNode : myRoot;
   for ( NodeList::iterator it = start->children.begin(); it != start->children.end() && !node; ++it )
   {
     QAction* a = itemAction( (*it)->id );
@@ -866,14 +752,14 @@ QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, MenuNo
 }
 
 /*!
-  Find id among children
-  \return id (>0) if on success or -1 on fail
-  \param id - id to be searched
-  \param pid - id of parent, among children of that 'id' must be searched
+  \brief Find menu item by given ID (one-level only).
+  \param id menu action ID
+  \param pid parent meun item ID
+  \return id (>0) on success or -1 if menu item is not found
 */
 int QtxActionMenuMgr::findId( const int id, const int pid ) const
 {
-  MenuNode* start = pid != -1 ? find( pid ) : (MenuNode*)&myRoot;
+  MenuNode* start = pid != -1 ? find( pid ) : myRoot;
   if ( start )
   {
     for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
@@ -886,13 +772,13 @@ int QtxActionMenuMgr::findId( const int id, const int pid ) const
 }
 
 /*!
-  Removes child
-  \param id - id of child to be removed
-  \param startNode - parent menu item
+  \brief Removes menu node (with all its children).
+  \param id menu action ID
+  \param startNode parent menu node which search starts from (if 0, search starts from root)
 */
 void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode )
 {
-  MenuNode* start = startNode ? startNode : &myRoot;
+  MenuNode* start = startNode ? startNode : myRoot;
   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
   {
     if ( (*it)->id == id )
@@ -903,8 +789,9 @@ void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode )
 }
 
 /*!
-  \return menu item action by id
-  \param id - id of action
+  \brief Get action by \a id.
+  \param id action ID
+  \return action or 0 if \a id is invalid
 */
 QAction* QtxActionMenuMgr::itemAction( const int id ) const
 {
@@ -912,8 +799,9 @@ QAction* QtxActionMenuMgr::itemAction( const int id ) const
 }
 
 /*!
-  \return menu action by id
-  \param id - id of action
+  \brief Get submenu action by \a id.
+  \param id submenu ID
+  \return submenu action or 0 if action is not found
 */
 QAction* QtxActionMenuMgr::menuAction( const int id ) const
 {
@@ -926,18 +814,38 @@ QAction* QtxActionMenuMgr::menuAction( const int id ) const
 }
 
 /*!
-  Updates menu ( isUpdatesEnabled() must return true )
-  \param startNode - first menu item to be updated
-  \param rec - recursive update
-  \param updParent - update also parent item (without recursion)
-  \sa isUpdatesEnabled()
+  \brief Get submenu action by \a id.
+  \param id submenu ID
+  \return submenu action or 0 if it is not found
+*/
+int QtxActionMenuMgr::menuActionId( QAction* a ) const
+{
+  int id = -1;
+  for ( MenuMap::ConstIterator itr = myMenus.begin(); itr != myMenus.end() && id == -1; ++itr )
+  {
+    if ( itr.value() == a )
+      id = itr.key();
+  }
+  return id;
+}
+
+/*!
+  \brief Update menu.
+
+  Does nothing if update is disabled.
+
+  \param startNode start menu item to be updated
+  \param rec if \c true, perform recursive update
+  \param updParent if \c true update also parent item (without recursion)
+
+  \sa isUpdatesEnabled() and setUpdatesEnabled()
 */
 void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bool updParent )
 {
   if ( !isUpdatesEnabled() )
     return;
 
-  MenuNode* node = startNode ? startNode : &myRoot;
+  MenuNode* node = startNode ? startNode : myRoot;
 
   QWidget* mw = menuWidget( node );
   if ( !mw )
@@ -1010,7 +918,9 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo
 }
 
 /*!
-  Updates menu (virtual variant). To be redefined for custom activity on menu updating
+  \brief Internal update.
+  
+  Customizes the menu update processing.
 */
 void QtxActionMenuMgr::internalUpdate()
 {
@@ -1022,8 +932,9 @@ void QtxActionMenuMgr::internalUpdate()
 }
 
 /*!
-  \return true if widget is non-empty menu
-  \param wid - widget to be checked
+  \brief Check if menu widget has any actions.
+  \param wid widget to be checked
+  \return \c true if widget contains action(s)
 */
 bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const
 {
@@ -1034,12 +945,14 @@ bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const
 }
 
 /*!
-  \return popup of menu item
-  \param node - menu item
+  \brief Get menu widget for the given \a node.
+  \param node menu node
+  \return popup menu or main menu corresponding to the menu node
+  (or 0 if it is not found)
 */
-QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node) const
+QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node ) const
 {
-  if ( !node || node == &myRoot )
+  if ( !node || node == myRoot )
      return myMenu;
 
   if ( !myMenus.contains( node->id ) || !myMenus[node->id] )
@@ -1049,8 +962,8 @@ QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node) const
 }
 
 /*!
-  Removes excess separators of menu
-  \param wid - menu to be processed
+  \brief Remove extra separators from menu widget.
+  \param wid menu widget to be processed
 */
 void QtxActionMenuMgr::simplifySeparators( QWidget* wid )
 {
@@ -1058,9 +971,9 @@ void QtxActionMenuMgr::simplifySeparators( QWidget* wid )
 }
 
 /*!
-  Removes special symbols (&) from string
-  \param txt string to be processed
-  \return clear variant of string
+  \brief Remove special symbols (&) from string to get clear menu title.
+  \param txt string to be processed
+  \return clear title
 */
 QString QtxActionMenuMgr::clearTitle( const QString& txt ) const
 {
@@ -1076,9 +989,10 @@ QString QtxActionMenuMgr::clearTitle( const QString& txt ) const
 }
 
 /*!
-  Creates and inserts many menu items
-  \param lst - list of menu texts
-  \param pId - id of action corresponding to parent menu item
+  \brief Create and inserts menu item recursively.
+  \param lst list of menu names
+  \param pId parent menu item ID
+  \return created menu item ID (last in the chain)
 */
 int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId )
 {
@@ -1096,10 +1010,10 @@ int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId )
 }
 
 /*!
-  Loads actions description from file
-  \param fname - name of file
-  \param r - reader of file
-  \return true on success
+  \brief Load actions description from the file.
+  \param fname file name
+  \param r action reader
+  \return \c true on success and \c false on error
 */
 bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r )
 {
@@ -1108,9 +1022,10 @@ bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r )
 }
 
 /*!
-  \return true if item has such child
-  \param title - menu text of child
-  \param pid - id of action corresponding to item
+  \brief Check if the parent menu contains menu item with given \a title.
+  \param title menu title
+  \param pid parent menu item ID
+  \return \c true if parent menu item contains such child item
 */
 bool QtxActionMenuMgr::containsMenu( const QString& title, const int pid ) const
 {
@@ -1118,9 +1033,10 @@ bool QtxActionMenuMgr::containsMenu( const QString& title, const int pid ) const
 }
 
 /*!
-  \return true if item has such child
-  \param id - id of action corresponding to child
-  \param pid - id of action corresponding to item
+  \brief Check if the parent menu contains menu item with given \a id.
+  \param id menu item ID
+  \param pid parent menu item ID
+  \return \c true if parent menu item contains such child item
 */
 bool QtxActionMenuMgr::containsMenu( const int id, const int pid ) const
 {
@@ -1128,7 +1044,23 @@ bool QtxActionMenuMgr::containsMenu( const int id, const int pid ) const
 }
 
 /*!
-  \Sets trigger for delayed update
+  \brief Get menu by the specified identifier.
+  \param id menu item ID
+  \return menu pointer or 0 if menu is not found
+*/
+QMenu* QtxActionMenuMgr::findMenu( const int id ) const
+{
+  QMenu* m = 0;
+  QAction* a = menuAction( id );
+  if ( a )
+    m = a->menu();
+  return m;
+}
+
+/*!
+  \brief Perform delayed menu update.
+  \param id menu item ID
+  \param rec if \c true, perform recursive update
 */
 void QtxActionMenuMgr::triggerUpdate( const int id, const bool rec )
 {
@@ -1141,20 +1073,23 @@ void QtxActionMenuMgr::triggerUpdate( const int id, const bool rec )
 }
 
 /*!
-  \Sets trigger for delayed update
+  \brief Called when delayed content update is performed.
+
+  Customizes the content update operation.
 */
 void QtxActionMenuMgr::updateContent()
 {
-  // Warning: For correct updating it is necessary to update the most enclosed submenu firstly
-  //          because not updated empty submenu will be skipped. Now the submenu are iterated in
-  //          ascending order their identifiers. For a submenu with automatically generated identifiers
-  //          will work correctly as the uppermost submenu have the biggest number (identifiers generated
-  //          reduction from -1). Generally when any submenu will have positive identifiers are obviously
-  //          appropriated can to work not truly. In this case it is required to improve the given method
-  //          and to add preliminary sorting a submenu on depth of an enclosure.
+  // Warning: For correct updating it is necessary to update the most enclosed submenu in first turn
+  //          because not updated empty submenu will be skipped. Now the submenus are iterated in
+  //          ascending order according to their identifiers. For a submenus with automatically generated 
+  //          identifiers this will work correctly since the uppermost submenus have the biggest number
+  //          (identifiers are generated by decrementing 1 starting from -1). In general, if any submenu
+  //          have positive identifiers this method might not work correctly. In this case it would be
+  //          necessary to improve this method and to add preliminary sorting a submenus by depth of an 
+  //          enclosure.
   for ( QMap<int, bool>::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it )
   {
-    MenuNode* node = it.key() == -1 ? &myRoot : find( it.key() );
+    MenuNode* node = it.key() == -1 ? myRoot : find( it.key() );
     if ( node )
       updateMenu( node, it.value() );
   }
@@ -1162,29 +1097,38 @@ void QtxActionMenuMgr::updateContent()
 }
 
 /*!
-  Constructor
-  \param r - menu reader
-  \param mgr - menu manager
+  \class QtxActionMenuMgr::MenuCreator
+  \brief Menu actions creator.
+
+  Used by Reader to create actions by reading descriptions from the file
+  and fill in the action manager with the actions.
+*/
+
+/*!
+  \brief Constructor.
+  \param r menu actions reader
+  \param mgr menu manager
 */
 QtxActionMenuMgr::MenuCreator::MenuCreator( QtxActionMgr::Reader* r, QtxActionMenuMgr* mgr )
 : QtxActionMgr::Creator( r ),
-myMgr( mgr )
+  myMgr( mgr )
 {
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionMenuMgr::MenuCreator::~MenuCreator()
 {
 }
 
 /*!
-  Appends new menu items
-  \param tag - tag of item
-  \param subMenu - it has submenu
-  \param attr - list of attributes
-  \param pId - id of action corresponding to parent item
+  \brief Create and append to the action manager a new action.
+  \param tag item tag name
+  \param subMenu \c true if this item is submenu
+  \param attr attributes map
+  \param pId parent action ID
+  \return menu action ID
 */
 int QtxActionMenuMgr::MenuCreator::append( const QString& tag, const bool subMenu,
                                            const ItemAttributes& attr, const int pId )
index e1cf03493764a3edd2375e5f8a06c72f2e60ae6f..96d15b51b4feea3e8c0897583dfd1cdfb682d84c 100644 (file)
@@ -17,7 +17,7 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      QtxActionMenuMgr.h
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #ifndef QTXACTIONMENUMGR_H
 #define QTXACTIONMENUMGR_H
 #include "Qtx.h"
 #include "QtxActionMgr.h"
 
-#include <QtCore/qlist.h>
-#include <QtCore/qstringlist.h>
+#include <QList>
 
-class QPopupMenu;
+class QMenu;
 class QMainWindow;
+class QStringList;
 
 #ifdef WIN32
 #pragma warning( disable:4251 )
 #endif
 
-/*!
-  \class QtxActionMenuMgr
-  Allows to use set of action to automatically build main menu.
-  With help of methods insert/append/remove it is possible to 
-  describe whole structure of menu. Method hide allows
-  to temporary remove some items from menu, method show allows to 
-  recreate them.
-  Actions can be grouped with help of group identifictor.
-  Inside popup or menu bar items have order by increasing group id.
-  This manager is able to attune menu: to remove excess separators,
-  to remove empty popup menu etc.
-*/
 class QTX_EXPORT QtxActionMenuMgr : public QtxActionMgr
 {
   Q_OBJECT
 
   class MenuNode;
 
-  typedef QList<MenuNode*> NodeList;
-
-  /*!
-    \class MenuNode
-    Represents a menu item inside main menu structure.
-    For internal purposes only
-  */
-  class MenuNode
-  {
-  public:
-    MenuNode() : parent( 0 ), visible( true ) {};
-    MenuNode( MenuNode* p ) : parent( p ), visible( true ) {};
-    ~MenuNode()
-    {
-      for ( NodeList::iterator it = children.begin(); it != children.end(); ++it )
-        delete *it;
-    }
-
-    int       id;
-    int       idx;
-    int       group;
-    MenuNode* parent;
-    bool      visible;
-    NodeList  children;
-  };
-
-  class MenuAction;
+  typedef QList<MenuNode*> NodeList;  //!< menu nodes list
 
 protected:
   class MenuCreator;
@@ -89,6 +51,8 @@ public:
   QtxActionMenuMgr( QWidget*, QObject* );
   virtual ~QtxActionMenuMgr();
 
+  QWidget*     menuWidget() const;
+
   virtual bool isVisible( const int, const int ) const;
   virtual void setVisible( const int, const int, const bool );
 
@@ -101,17 +65,17 @@ public:
   virtual int  insert( const int, const int, const int, const int = -1 );
   int          insert( QAction*, const int, const int, const int = -1 );
 
-  int          insert( const QString&, const QString&, const int, const int = -1, const int = -1, const bool = false );
-  int          insert( const QString&, const QStringList&, const int, const int = -1, const int = -1, const bool = false );
-  virtual int  insert( const QString&, const int, const int, const int = -1, const int = -1, const bool = false );
+  int          insert( const QString&, const QString&, const int, const int = -1, const int = -1 );
+  int          insert( const QString&, const QStringList&, const int, const int = -1, const int = -1 );
+  virtual int  insert( const QString&, const int, const int, const int = -1, const int = -1 );
 
   int          append( const int, const int, const int );
   int          append( QAction*, const int, const int );
-  int          append( const QString&, const int, const int, const int = -1, const bool = false );
+  int          append( const QString&, const int, const int, const int = -1 );
 
   int          prepend( const int, const int, const int );
   int          prepend( QAction*, const int, const int );
-  int          prepend( const QString&, const int, const int, const int = -1, const bool = false );
+  int          prepend( const QString&, const int, const int, const int = -1 );
 
   void         remove( const int );
   void         remove( const int, const int, const int = -1 );
@@ -129,20 +93,20 @@ public:
   bool         containsMenu( const QString&, const int ) const;
   bool         containsMenu( const int, const int ) const;
 
-private Q_SLOTS:
+  QMenu*       findMenu( const int ) const;
+
+private slots:
   void         onAboutToShow();
   void         onAboutToHide();
-  void         onHighlighted( int );
   void         onDestroyed( QObject* );
 
-Q_SIGNALS:
+signals:
   void         menuAboutToShow( QMenu* );
   void         menuAboutToHide( QMenu* );
 
-  void         menuHighlighted( int, int );
-
 protected:
-  void         setWidget( QWidget* );
+  void         setMenuWidget( QWidget* );
+
   MenuNode*    find( const int, const int, const bool = true ) const;
   MenuNode*    find( const int, MenuNode* = 0, const bool = true ) const;
   bool         find( const int, NodeList&, MenuNode* = 0 ) const;
@@ -155,9 +119,10 @@ protected:
 
   QAction*     itemAction( const int ) const;
   QAction*     menuAction( const int ) const;
+  int          menuActionId( QAction* ) const;
 
   void         updateMenu( MenuNode* = 0, const bool = true, const bool = true );
-  virtual void internalUpdate();  
+  virtual void internalUpdate();
   virtual void updateContent();
 
 private:
@@ -170,19 +135,15 @@ private:
   void         triggerUpdate( const int, const bool rec = true );
 
 private:
-  typedef QMap<int, QAction*> MenuMap;
-
+  typedef QMap<int, QAction*> MenuMap;     //!< actions map
+  
 private:
-  MenuNode     myRoot;
-  QWidget*     myMenu;
-  MenuMap      myMenus;
-  QMap<int, bool> myUpdateIds;
+  MenuNode*       myRoot;        //!< root menu node
+  QWidget*        myMenu;        //!< menu widget
+  MenuMap         myMenus;       //!< actions map
+  QMap<int, bool> myUpdateIds;   //!< list of actions ID being updated
 };
 
-/*!
-  \class QtxActionMenuMgr::MenuCreator
-  Allows to create automatically main menu by data read from file
-*/
 class QtxActionMenuMgr::MenuCreator : public QtxActionMgr::Creator
 {
 public:
@@ -193,7 +154,7 @@ public:
                       const ItemAttributes&, const int );
 
 private:
-  QtxActionMenuMgr* myMgr;
+  QtxActionMenuMgr* myMgr;       //!< menu manager
 };
 
 
index bd6a6bd5e84ceb265018306856809ca27c068c13..366dd24e8b5453f1dd43be7b81b474a398f226e6 100644 (file)
@@ -1,41 +1,42 @@
 // 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
 //
 // File:      QtxActionMgr.cxx
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #include "Qtx.h"
 #include "QtxActionMgr.h"
 #include "QtxAction.h"
-
-#include <QtCore/qfile.h>
-#include <QtCore/qtimer.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qwidget.h>
-#include <QtGui/qtoolbar.h>
-#include <QtGui/qapplication.h>
-
-#include <QtXml/qdom.h>
+#include <QFile>
+#include <QTimer>
+#ifndef QT_NO_DOM
+#include <QDomDocument>
+#include <QDomNode>
+#include <QCoreApplication>
+#endif
 
 typedef QList< QPointer<QAction> > qtx_actionlist;
 static qtx_actionlist qtx_separator_actions;
 
+/*!
+  \brief Clean all cashed separator actions.
+  \internal
+*/
 void qtxSeparatorActionCleanup()
 {
   for ( qtx_actionlist::iterator it = qtx_separator_actions.begin(); it != qtx_separator_actions.end(); ++it )
@@ -43,8 +44,9 @@ void qtxSeparatorActionCleanup()
 }
 
 /*!
-       Class: QtxActionMenuMgr::SeparatorAction
-       Level: Internal
+  \class QtxActionMgr::SeparatorAction
+  \brief Separator action class.
+  \internal
 */
 
 class QtxActionMgr::SeparatorAction : public QtxAction
@@ -55,7 +57,9 @@ public:
 };
 
 /*!
-  Constructor
+  \brief Constructor.
+  \internal
+  \param parent parent object
 */
 QtxActionMgr::SeparatorAction::SeparatorAction( QObject* parent )
 : QtxAction( parent )
@@ -64,39 +68,65 @@ QtxActionMgr::SeparatorAction::SeparatorAction( QObject* parent )
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionMgr::SeparatorAction::~SeparatorAction()
 {
 }
 
 /*!
-       Class: QtxActionMgr
-       Level: Public
+  \class QtxActionMgr
+  \brief Manages a set of actions accessible by unique identifier.
+  
+  Base class for menu, toolbar actions containers and popup menu creators.
+
+  Actions are registered in the manager with the registerAction() method
+  and unregistered from it with the unRegisterAction() method.
+
+  Functions action() and actionId() allow getting action by its identifier
+  and vice versa. Method contains() returns \c true if the action with 
+  the specified identifier is already registered.
+
+  To get total number of the registered actions can be retrieved by
+  the method count(). Function isEmpty() returns \c true if manager does not
+  contains any actions. The list of all actions identifiers can be retrieved
+  with the idList() function.
+
+  The method separator() allows creating a separator action which can be
+  used in the menus or toolbars to separate logical groups of actions.
+  
+  To enable/disable any action by its identifier, use setEnabled() method.
 */
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param parent parent object
 */
 QtxActionMgr::QtxActionMgr( QObject* parent )
 : QObject( parent ),
-myUpdate( true ),
-myUpdTimer( 0 )
+  myUpdate( true ),
+  myUpdTimer( 0 )
 {
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionMgr::~QtxActionMgr()
 {
 }
 
 /*!
-  Stores action in internal map
-  If action with such id is registered already, then it will be unregistered
-  \param a - action to be registered
-  \param userId - proposed id (if it is less than 0, then id will be generated automatically)
+  \brief Register an action in the internal map.
+
+  If \a userId is less than 0, the identifier for the action 
+  is generated automatically. If action with given \a userId 
+  is already registered, it will be re-registered.
+
+  \param a action to be registered
+  \param userId action ID
+  \return action ID (the same as userId or generated one)
+  \sa unRegisterAction()
 */
 int QtxActionMgr::registerAction( QAction* a, const int userId )
 {
@@ -123,8 +153,9 @@ int QtxActionMgr::registerAction( QAction* a, const int userId )
 }
 
 /*!
-  Removes action from internal map
-  \param id - action id
+  \brief Unregister action from internal map.
+  \param id action ID
+  \sa registerAction()
 */
 void QtxActionMgr::unRegisterAction( const int id )
 {
@@ -133,8 +164,10 @@ void QtxActionMgr::unRegisterAction( const int id )
 }
 
 /*!
-  \return action by id
-  \param id - action id
+  \brief Get action by specified identifier.
+  \param id action ID
+  \return action (or 0 if \a id is invalid)
+  \sa actionId()
 */
 QAction* QtxActionMgr::action( const int id ) const
 {
@@ -145,8 +178,10 @@ QAction* QtxActionMgr::action( const int id ) const
 }
 
 /*!
-  \return id by action
-  \param a - action
+  \brief Get action identifier.
+  \param a action
+  \return action ID (or -1 if action is not found)
+  \sa action()
 */
 int QtxActionMgr::actionId( const QAction* a ) const
 {
@@ -164,8 +199,9 @@ int QtxActionMgr::actionId( const QAction* a ) const
 }
 
 /*!
-  \return true if internal map contains such id
-  \param id - action id
+  \brief Check if an action with given \a id is registered in the action manager.
+  \param id action ID
+  \return \c true if internal map contains action with such identifier
 */
 bool QtxActionMgr::contains( const int id ) const
 {
@@ -173,7 +209,9 @@ bool QtxActionMgr::contains( const int id ) const
 }
 
 /*!
-  \return count of actions in internal map
+  \brief Get total number of registered actions.
+  \return number of actions in the internal map
+  \sa isEmpty()
 */
 int QtxActionMgr::count() const
 {
@@ -181,7 +219,9 @@ int QtxActionMgr::count() const
 }
 
 /*!
-  \return true if internal map is empty
+  \brief Check if there are no actions registered in the action manager.
+  \return \c true if internal map is empty
+  \sa count()
 */
 bool QtxActionMgr::isEmpty() const
 {
@@ -189,15 +229,18 @@ bool QtxActionMgr::isEmpty() const
 }
 
 /*!
-  Fills list with ids of registered actions
+  \brief Get all registered actions identifiers.
+  \return list of actions identifiers
 */
-void QtxActionMgr::idList( QIntList& lst ) const
+QIntList QtxActionMgr::idList() const
 {
-  lst = myActions.keys();
+  return myActions.keys();
 }
 
 /*!
-  \return true if updates are enabled
+  \brief Check if update is enabled.
+  \return \c true if update is enabled
+  \sa setUpdatesEnabled(), update()
 */
 bool QtxActionMgr::isUpdatesEnabled() const
 {
@@ -205,8 +248,9 @@ bool QtxActionMgr::isUpdatesEnabled() const
 }
 
 /*!
-  Enables/disables updates
-  \param upd - new state
+  \brief Enable/disable update operation.
+  \param upd new state
+  \sa isUpdatesEnabled(), update()
 */
 void QtxActionMgr::setUpdatesEnabled( const bool upd )
 {
@@ -214,23 +258,44 @@ void QtxActionMgr::setUpdatesEnabled( const bool upd )
 }
 
 /*!
-  \return true if action is visible (by default \return always true)
+  \brief Check if an action with \a actId identifier is visible to
+  the parent action with \a place identifier.
+
+  This method can be redefined in subclasses.
+  Base implementatin always returns \c true.
+
+  \param actId action ID
+  \param place some parent action ID
+  \return \c true if an action is visible to the parent
+  \sa setVisible()
 */
-bool QtxActionMgr::isVisible( const int, const int ) const
+bool QtxActionMgr::isVisible( const int /*actId*/, const int /*place*/ ) const
 {
   return true;
 }
 
 /*!
-  Sets visibility of action (by default, empty implementation)
+  \brief Set action's visibility flag.
+
+  This method can be redefined in subclasses.
+  Base implementatin does nothing.
+
+  \param actId action ID
+  \param place some parent action ID
+  \param v new visibility state
+  \sa isVisible()
 */
-void QtxActionMgr::setVisible( const int, const int, const bool )
+void QtxActionMgr::setVisible( const int /*actId*/, const int /*place*/, const bool /*v*/ )
 {
 }
 
 /*!
-  Updates actions, check isUpdatesEnabled() and call internalUpdate()
-  \sa isUpdatesEnabled(), internalUpdate()
+  \brief Update actions.
+
+  Calls virtual function internalUpdate to update the contents.
+  Does nothing if update is disabled.
+
+  \sa setUpdatesEnabled(), isUpdatesEnabled(), internalUpdate()
 */
 void QtxActionMgr::update()
 {
@@ -243,14 +308,19 @@ void QtxActionMgr::update()
 }
 
 /*!
-  Real update (to be redefined in successors)
+  \brief Internal update.
+
+  This method is called by update() function and can be redefined 
+  in subclasses to customize update operation. Base implementation
+  does nothing.
 */
 void QtxActionMgr::internalUpdate()
 {
 }
 
 /*!
-  \return global free id
+  \brief Generate unique action identifier.
+  \return new ID
 */
 int QtxActionMgr::generateId() const
 {
@@ -259,8 +329,9 @@ int QtxActionMgr::generateId() const
 }
 
 /*!
-  \return true if action is enabled
-  \param id - action id
+  \brief Check is action with given \a id is enabled.
+  \param id action ID
+  \return \c true if action is enabled
 */
 bool QtxActionMgr::isEnabled( const int id ) const
 {
@@ -272,25 +343,30 @@ bool QtxActionMgr::isEnabled( const int id ) const
 }
 
 /*!
-  Enables/disables action
-  \param id - action id
-  \param en - new state
+  Enable/disable action with given \a id.
+  \param id action ID
+  \param enable new state
 */
-void QtxActionMgr::setEnabled( const int id, const bool en )
+void QtxActionMgr::setEnabled( const int id, const bool enable )
 {
   QAction* a = action( id );
   if ( a )
-    a->setEnabled( en );
+    a->setEnabled( enable );
 }
 
 /*!
-  \return action for separator
-  If this action doesn't exist, then it will be created
-  \param individual - if it is false, then action will be shared, otherwise it will be created on every call
+  \brief Create new separator action.
+
+  If \a own is \c true, then the caller is responsible for the action
+  destroying. If \a own is \c false, new separator action will be owned by the
+  action manager which will destroy it on application exit.
+
+  \param own ownership flag
+  \return new separator action
 */
-QAction* QtxActionMgr::separator( const bool individual )
+QAction* QtxActionMgr::separator( const bool own )
 {
-  if ( individual )
+  if ( own )
     return new SeparatorAction();
 
   if ( qtx_separator_actions.isEmpty() )
@@ -303,7 +379,10 @@ QAction* QtxActionMgr::separator( const bool individual )
 }
 
 /*!
-  \initialise timer for delayed update
+  \brief Perform delayed update.
+
+  Does nothing if update is disabled.
+  \sa isUpdatesEnabled(), setUpdatesEnabled(), update()
 */
 void QtxActionMgr::triggerUpdate()
 {
@@ -322,15 +401,22 @@ void QtxActionMgr::triggerUpdate()
 }
 
 /*!
-  \perform delayed update
-  \default implementation is empty
+  \brief Internal content update operation.
+
+  Called automatically by onUpdateContent() when the delayed update
+  is triggered. Base implementation does nothing.
+
+  \sa triggerUpdate(), onUpdateContent()
 */
 void QtxActionMgr::updateContent()
-{}
+{
+}
 
 /*!
-  \perform delayed update
-  \default implementation is empty
+  \brief Called when delayed update is performed (via timer event).
+
+  Calls virtual method updateContent() which can be redefined in the
+  subclasses to customize the content update operation.
 */
 void QtxActionMgr::onUpdateContent()
 {
@@ -338,26 +424,30 @@ void QtxActionMgr::onUpdateContent()
 }
 
 /*!
-       Class: QtxActionMgr::Reader
-       Level: Public
+  \class QtxActionMgr::Reader
+  \brief Generic actions description files reader class.
+
+  This class is used to read files of some format to create actions 
+  and fill an action manager with the actions automatically.
 */
 
 /*!
-  Constructor
+  \brief Constructor.
 */
 QtxActionMgr::Reader::Reader()
 {
 }
 
 /*!
-  Destructor
+  \brief Destructor
 */
 QtxActionMgr::Reader::~Reader()
 {
 }
 
 /*!
-  \return list of options
+  \brief Get the list of options.
+  \return options list
 */
 QStringList QtxActionMgr::Reader::options() const
 {
@@ -365,9 +455,13 @@ QStringList QtxActionMgr::Reader::options() const
 }
 
 /*!
-  \return value of option
-  \param name - option name
-  \param def - default option value (is returned, if there is no such option)
+  \brief Get option value.
+  
+  If there is no such option the default value (\a def) is returned.
+
+  \param name option name
+  \param def default option value
+  \return option value
 */
 QString QtxActionMgr::Reader::option( const QString& name, const QString& def ) const
 {
@@ -378,19 +472,40 @@ QString QtxActionMgr::Reader::option( const QString& name, const QString& def )
 }
 
 /*!
-  Sets value of option
-  \param name option name
-  \param value - option value
+  \brief Set option value.
+  \param name option name
+  \param value new option value
 */
 void QtxActionMgr::Reader::setOption( const QString& name, const QString& value )
 {
   myOptions[ name ] = value;
 }
 
+/*!
+  \fn bool QtxActionMgr::Reader::read( const QString& fname, Creator& cr ) const
+  \brief Read the file and fill and action manager with actions 
+         by using help actions creator. 
+
+  This method should be redefined in the subclasses.
+  
+  \param fname XML file name
+  \param cr actions creator
+  \return \c true on success and \c false in case of error
+*/
 
 /*!
-       Class: QtxActionMgr::XMLReader
-       Level: Public
+  \class QtxActionMgr::XMLReader
+  \brief XML file reader.
+
+  This class is used to read files of XML format to create 
+  actions and fill an action manager with actions automatically.
+*/
+
+/*!
+  \brief Constructor.
+  \param root root XML tag name
+  \param item menu item XML tag name
+  \param dir resources directory (containing icons, etc)
 */
 QtxActionMgr::XMLReader::XMLReader( const QString& root,
                                     const QString& item,
@@ -412,20 +527,22 @@ QtxActionMgr::XMLReader::XMLReader( const QString& root,
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionMgr::XMLReader::~XMLReader()
 {
 }
 
 /*!
-  Reads file and fills action manager with help of creator
-  \param fname - file name
-  \param cr - creator
+  \brief Read the file and fill and action manager with actions 
+         by using actions creator.
+  \param fname XML file name
+  \param cr actions creator
+  \return \c true on success and \c false in case of error
 */
 bool QtxActionMgr::XMLReader::read( const QString& fname, Creator& cr ) const
 {
-  bool res = false;  
+  bool res = false;
 
 #ifndef QT_NO_DOM
 
@@ -464,10 +581,10 @@ bool QtxActionMgr::XMLReader::read( const QString& fname, Creator& cr ) const
 }
 
 /*!
-  Create item by xml node
-  \param parent_node - parent node
-  \param parent_id - parent id
-  \param cr - creator
+  \brief Read XML mode and create an item if requied.
+  \param parent_node parent XML file node
+  \param parent_id parent action ID
+  \param cr actions creator
 */
 void QtxActionMgr::XMLReader::read( const QDomNode& parent_node,
                                     const int parent_id,
@@ -504,14 +621,17 @@ void QtxActionMgr::XMLReader::read( const QDomNode& parent_node,
 }
 
 /*!
-  \return true if node satisfies pattern
+  \brief Check node name correspondance to some pattern.
+  \param node XML file node
+  \param pattern node name pattern
+  \return \c true if node satisfies pattern
 */
 bool QtxActionMgr::XMLReader::isNodeSimilar( const QDomNode& node,
                                              const QString& pattern ) const
 {
   if( node.nodeName()==pattern )
     return true;
-  
+
   QDomDocument temp;
   QString mes;
   temp.setContent( pattern, true, &mes );
@@ -529,24 +649,30 @@ bool QtxActionMgr::XMLReader::isNodeSimilar( const QDomNode& node,
   return ok;
 }
 
-
 /*!
-       Class: QtxActionMgr::Creator
-       Level: Public
+  \class QtxActionMgr::Creator
+  \brief Generic actions creator class.
+
+  Used by Reader to create actions and fill in the action 
+  manager with the actions.
 */
 
 /*!
-  \return integer value by attributes
-  \param attrs - attributes
-  \param name - name of attribute
-  \param def - default value (is returned on fail)
+  \brief Get integer attribute value from the attribute map.
+
+  Returns default value (\a def) if the attribute is not found.
+
+  \param attrs attributes map
+  \param name attribute name
+  \param def default attribute value
+  \return attribute value
 */
 int QtxActionMgr::Creator::intValue( const ItemAttributes& attrs,
                                      const QString& name, int def )
 {
   if( attrs.contains( name ) )
   {
-    bool ok; 
+    bool ok;
     int res = attrs[ name ].toInt( &ok );
     if( ok )
       return res;
@@ -555,10 +681,14 @@ int QtxActionMgr::Creator::intValue( const ItemAttributes& attrs,
 }
 
 /*!
-  \return string value by attributes
-  \param attrs - attributes
-  \param name - name of attribute
-  \param def - default value (is returned on fail)
+  \brief Get string attribute value from the attribute map.
+
+  Returns default value (\a def) if the attribute is not found.
+
+  \param attrs attributes map
+  \param name attribute name
+  \param def default attribute value
+  \return attribute value
 */
 QString QtxActionMgr::Creator::strValue( const ItemAttributes& attrs,
                                          const QString& name,
@@ -571,7 +701,8 @@ QString QtxActionMgr::Creator::strValue( const ItemAttributes& attrs,
 }
 
 /*!
-   Constructor
+  \brief Constructor.
+  \param r action reader
 */
 QtxActionMgr::Creator::Creator( QtxActionMgr::Reader* r )
 : myReader( r )
@@ -579,14 +710,15 @@ QtxActionMgr::Creator::Creator( QtxActionMgr::Reader* r )
 }
 
 /*!
-   Destructor
+  \brief Destructor.
 */
 QtxActionMgr::Creator::~Creator()
 {
 }
 
 /*!
-  \return corresponding reader
+  \brief Get actions reader.
+  \return actions reader
 */
 QtxActionMgr::Reader* QtxActionMgr::Creator::reader() const
 {
@@ -594,16 +726,22 @@ QtxActionMgr::Reader* QtxActionMgr::Creator::reader() const
 }
 
 /*!
-  Connects action to some slots (default implementation is empty)
+  \brief Connect action to some specific slot(s).
+
+  This method can be redefined in subclasses. 
+  Base implementation does nothing.
+
+  \param a action
 */
-void QtxActionMgr::Creator::connect( QAction* ) const
+void QtxActionMgr::Creator::connect( QAction* /*a*/ ) const
 {
 }
 
 /*!
-  Loads pixmap 
-  \param fname - file name
-  \param pix - to return loaded pixmap
+  \brief Load pixmap from the file.
+  \param fname file name
+  \param pix used to return pixmap
+  \return \c true if pixmap is loaded successfully and \c false in case of error
 */
 bool QtxActionMgr::Creator::loadPixmap( const QString& fname, QPixmap& pix ) const
 {
@@ -619,3 +757,19 @@ bool QtxActionMgr::Creator::loadPixmap( const QString& fname, QPixmap& pix ) con
 
   return res;
 }
+
+/*!
+  \fn int QtxActionMgr::Creator::append( const QString& tag, 
+                                         const bool subMenu, 
+                                         const ItemAttributes& attr,
+                                         const int pId )
+  \brief Create (and probably append to the action manager) new action.
+
+  This method should be redefined in the subclasses.
+  
+  \param tag item tag name
+  \param subMenu \c true if this item is submenu
+  \param attr attributes map
+  \param pId parent action ID
+  \return item (for example action) ID
+*/
index a2fee6b7f40525ebe8735e5676dbf29ec626e21b..98d99e3c6f6c392a54897b2d915fab080a459ca8 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      QtxActionMgr.h
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #ifndef QTXACTIONMGR_H
 #define QTXACTIONMGR_H
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qpointer.h>
+#include <QMap>
+#include <QObject>
+#include <QPointer>
 
 class QTimer;
 class QAction;
@@ -37,11 +37,6 @@ class QDomNode;
 #endif
 
 
-/*!
-  \class QtxActionMgr
-  Contains set of actions accessible by id.
-  Base class for menu, popup creators and other action containers.
-*/
 class QTX_EXPORT QtxActionMgr : public QObject
 {
   Q_OBJECT 
@@ -68,7 +63,7 @@ public:
 
   int              count() const;
   bool             isEmpty() const;
-  void             idList( QIntList& ) const;
+  QIntList         idList() const;
 
   bool             isUpdatesEnabled() const;
   virtual void     setUpdatesEnabled( const bool );
@@ -87,7 +82,6 @@ protected:
   virtual void     internalUpdate();
   int              generateId() const;
 
-  //! initialise timer for delayed update
   void             triggerUpdate();
   virtual void     updateContent();
 
@@ -95,23 +89,19 @@ private slots:
   void             onUpdateContent();
 
 private:
-  typedef QPointer<QAction>    ActionPtr;
-  typedef QMap<int, ActionPtr> ActionMap;
+  typedef QPointer<QAction>    ActionPtr; //!< Action guarded pointer
+  typedef QMap<int, ActionPtr> ActionMap; //!< Actions map
 
 private:
-  bool             myUpdate;
-  ActionMap        myActions;
-  QTimer*          myUpdTimer;
+  bool             myUpdate;     //!< update flag
+  ActionMap        myActions;    //!< actions map
+  QTimer*          myUpdTimer;   //!< update timer
 };
 
 
-QTX_EXPORT typedef QMap<QString, QString> ItemAttributes;
+QTX_EXPORT typedef QMap<QString, QString> ItemAttributes; //!< attributes map
 
-/*!
-  \class QtxActionMgr::Creator
-  Allows to fill automatically action manager with actions created by data from file
-*/
-class QtxActionMgr::Creator
+class QTX_EXPORT QtxActionMgr::Creator
 {
 public:
   Creator( QtxActionMgr::Reader* );
@@ -119,57 +109,47 @@ public:
 
   Reader* reader() const;
 
-  virtual int append( const QString&, const bool,
-                      const ItemAttributes&, const int ) = 0;
-  virtual void connect( QAction* ) const;
+  virtual int    append( const QString&, const bool,
+                        const ItemAttributes&, const int ) = 0;
+  virtual void   connect( QAction* ) const;
 
-  virtual bool loadPixmap( const QString&, QPixmap& ) const;
+  virtual bool   loadPixmap( const QString&, QPixmap& ) const;
 
 protected:
   static int     intValue( const ItemAttributes&, const QString&, const int );
   static QString strValue( const ItemAttributes&, const QString&,
-                                      const QString& = QString::null );
+                          const QString& = QString::null );
 private:
-  QtxActionMgr::Reader*  myReader;
+  QtxActionMgr::Reader*  myReader;  //!< actions reader
 };
 
-/*!
-  \class QtxActionMgr::Reader
-  This class is used to read files of some format
-  to create actions and to fill action manager automatically
-*/
-class QtxActionMgr::Reader
+class QTX_EXPORT QtxActionMgr::Reader
 {
 public:
-  QTX_EXPORT Reader();
-  QTX_EXPORT virtual ~Reader();
+  Reader();
+  virtual ~Reader();
 
-  QTX_EXPORT QStringList  options() const;
-  QTX_EXPORT QString      option( const QString&, const QString& = QString::null ) const;
-  QTX_EXPORT void         setOption( const QString&, const QString& );
+  QStringList    options() const;
+  QString        option( const QString&, const QString& = QString::null ) const;
+  void           setOption( const QString&, const QString& );
 
-  QTX_EXPORT virtual bool read( const QString&, Creator& ) const = 0;
+  virtual bool   read( const QString&, Creator& ) const = 0;
 
 private:
-  QMap< QString, QString > myOptions;
+  QMap< QString, QString > myOptions;  //!< options map
 };
 
-/*!
-  \class QtxActionMgr::Reader
-  This class is used to read files of XML format
-  to create actions and to fill action manager automatically
-*/
-class QtxActionMgr::XMLReader : public Reader
+class QTX_EXPORT QtxActionMgr::XMLReader : public Reader
 {
 public:
-  QTX_EXPORT XMLReader( const QString&, const QString&, const QString& );
-  QTX_EXPORT virtual ~XMLReader();
+  XMLReader( const QString&, const QString&, const QString& );
+  virtual ~XMLReader();
 
-  QTX_EXPORT virtual bool read( const QString&, Creator& ) const;
+  virtual bool   read( const QString&, Creator& ) const;
 
 protected:
-  QTX_EXPORT virtual void read( const QDomNode&, const int, Creator& ) const;
-  QTX_EXPORT virtual bool isNodeSimilar( const QDomNode&, const QString& ) const;
+  virtual void   read( const QDomNode&, const int, Creator& ) const;
+  virtual bool   isNodeSimilar( const QDomNode&, const QString& ) const;
 };
 
 
diff --git a/src/Qtx/QtxActionSet.cxx b/src/Qtx/QtxActionSet.cxx
new file mode 100644 (file)
index 0000000..b25caad
--- /dev/null
@@ -0,0 +1,370 @@
+// 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
+//
+// File:      QtxActionSet.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxActionSet.h"
+
+/*!
+  \class QtxActionSet
+  \brief An action class which is represented in the menu bar (or toolbar) as
+  a group of items (which can be customized).
+
+  Example: Window menu in the MDI application with menu items:
+  - Cascade
+  - Tile vertically
+  - Tile horizontally
+  - <separator>
+  - Window1
+  - Window2
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent object
+*/
+QtxActionSet::QtxActionSet( QObject* parent )
+: QtxAction( parent )
+{
+  connect( this, SIGNAL( changed() ), this, SLOT( onChanged() ) );
+
+  setVisible( false );
+
+  update();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxActionSet::~QtxActionSet()
+{
+}
+
+/*!
+  \brief Get list of child actions.
+  \return list of assigned actions
+*/
+QList<QAction*> QtxActionSet::actions() const
+{
+  return mySet;
+}
+
+/*!
+  \brief Assign child actions.
+  \param lst list of actions
+*/
+void QtxActionSet::setActions( const QList<QAction*>& lst )
+{
+  for ( ActionList::iterator it = mySet.begin(); it != mySet.end(); ++it )
+  {
+    if ( !lst.contains( *it ) )
+      delete *it;
+  }
+
+  mySet.clear();
+
+  insertActions( lst );
+}
+
+/*!
+  \brief Insert actions at the specified position.
+  \param lst list of actions
+  \param index position in the action list (if < 0, items are appended to the end of list)
+*/
+void QtxActionSet::insertActions( const QList<QAction*>& lst, const int index )
+{
+  int idx = qMin( index < 0 ? mySet.count() : index, mySet.count() );
+
+  for ( QList<QAction*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    QAction* a = *it;
+    int ident = generateId();
+
+    a->setParent( this );
+    mySet.insert( idx++, a );
+    a->setData( ident );
+
+    connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onActionTriggered( bool ) ) );
+  }
+
+  update();
+}
+
+/*!
+  \brief Insert action at the specified position.
+
+  If \a id < 0, it is generated automatically.
+
+  \param a action being inserted
+  \param id action ID
+  \param index position in the action list (if < 0, item is appended to the end of list)
+  \return action identifier
+*/
+int QtxActionSet::insertAction( QAction* a, const int id, const int index )
+{
+  if ( !a )
+    return -1;
+
+  int ident = id < 0 ? generateId() : id;
+  int idx = qMin( index < 0 ? mySet.count() : index, mySet.count() );
+
+  a->setParent( this );
+  mySet.insert( idx, a );
+  a->setData( ident );
+
+  connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onActionTriggered( bool ) ) );
+
+  update();
+
+  return ident;
+}
+
+/*!
+  \brief Insert action at the specified position.
+
+  If \a id < 0, it is generated automatically.
+
+  \param txt action text
+  \param id action ID
+  \param index position in the action list (if < 0, item is appended to the end of list)
+  \return action identifier
+*/
+int QtxActionSet::insertAction( const QString& txt, const int id, const int index )
+{
+  return insertAction( new QtxAction( txt, txt, 0, this ), id, index );
+}
+
+/*!
+  \brief Insert action at the specified position.
+
+  If \a id < 0, it is generated automatically.
+
+  \param txt action text
+  \param icon action icon
+  \param id action ID
+  \param index position in the action list (if < 0, item is appended to the end of list)
+  \return action identifier
+*/
+int QtxActionSet::insertAction( const QString& txt, const QIcon& icon, const int id, const int index )
+{
+  return insertAction( new QtxAction( txt, icon, txt, 0, this ), id, index );
+}
+
+/*!
+  \brief Remove specified action.
+
+  An action is removed from the action list and destroyed.
+
+  \param a action to be removed.
+*/
+void QtxActionSet::removeAction( QAction* a )
+{
+  if ( !mySet.contains( a ) )
+    return;
+
+  mySet.removeAll( a );
+  delete a;
+}
+
+/*!
+  \brief Remove specified action.
+
+  An action is removed from the action list and destroyed.
+
+  \param id action identifier
+*/
+void QtxActionSet::removeAction( const int id )
+{
+  removeAction( action( id ) );
+}
+
+/*!
+  \brief Remove all actions.
+
+  An actions list is cleared and all actions are destroyed.
+*/
+void QtxActionSet::clear()
+{
+  qDeleteAll( mySet );
+  mySet.clear();
+
+  update();
+}
+
+/*!
+  \brief Called when action is changed.
+  
+  Update action state.
+*/
+void QtxActionSet::onChanged()
+{
+  if ( !isVisible() || !isEmptyAction() )
+    return;
+
+  bool block = signalsBlocked();
+  blockSignals( true );
+  setVisible( false );
+  blockSignals( block );
+}
+
+/*!
+  \brief Called when some action is activated by the user.
+  \param on toggled state (not used)
+*/
+void QtxActionSet::onActionTriggered( bool /*on*/ )
+{
+  QAction* a = ::qobject_cast<QAction*>( sender() );
+  if ( !a )
+    return;
+
+  int id = actionId( a );
+  if ( id != -1 )
+    emit triggered( id );
+  emit triggered( a );
+}
+
+/*!
+  \brief Called when this action set is added to the menu bar (or toolbar).
+  \param w widget this action set is added to
+*/
+void QtxActionSet::addedTo( QWidget* w )
+{
+  QtxAction::addedTo( w );
+
+  update( w );
+}
+
+/*!
+  \brief Called when this action set is removed from the menu bar (or toolbar).
+  \param w widget this action set is removed from
+*/
+void QtxActionSet::removedFrom( QWidget* w )
+{
+  QtxAction::removedFrom( w );
+
+  update( w );
+}
+
+/*!
+  \brief Get action by specified identifier.
+  \param id action ID
+  \return action or 0 if it is not found
+*/
+QAction* QtxActionSet::action( int id ) const
+{
+  QAction* a = 0;
+  for ( ActionList::const_iterator it = mySet.begin(); it != mySet.end() && !a; ++it )
+  {
+    if ( actionId( *it ) == id )
+      a = *it;
+  }
+  return a;
+}
+
+/*!
+  \brief Get action identifier for the action.
+  \param a action
+  \return action ID or -1 if it is not found
+*/
+int QtxActionSet::actionId( QAction* a ) const
+{
+  int id = -1;
+  if ( a && a->data().canConvert( QVariant::Int ) )
+    id = a->data().toInt();
+  return id;
+}
+
+/*!
+  \brief Set action identifier for the action.
+  \param a action
+  \param id new action ID
+*/
+void QtxActionSet::setActionId( QAction* a, const int id )
+{
+  if ( !a || id == -1 )
+    return;
+
+  a->setData( id );
+}
+
+/*!
+  \brief Getneration unique action identifier
+  \return generation action ID
+*/
+int QtxActionSet::generateId() const
+{
+  QMap<int, int> map;
+  for ( ActionList::const_iterator it = mySet.begin(); it != mySet.end(); ++it )
+    map.insert( (*it)->data().toInt(), 0 );
+
+  int id = -2;
+  while ( map.contains( id ) )
+    id--;
+
+  return id;
+}
+
+/*!
+  \brief Update action set.
+*/
+void QtxActionSet::update()
+{
+  QList<QWidget*> lst = associatedWidgets();
+  for ( QList<QWidget*>::iterator it = lst.begin(); it != lst.end(); ++it )
+    update( *it );
+}
+
+/*!
+  \brief Update action set for the specified widget.
+  \param w a widget this action is added to
+*/
+void QtxActionSet::update( QWidget* w )
+{
+  if ( !w )
+    return;
+
+  for ( ActionList::iterator it = mySet.begin(); it != mySet.end(); ++it )
+    w->removeAction( *it );
+
+  if ( !associatedWidgets().contains( w ) )
+    return;
+
+  for ( int i = 0; i < mySet.count(); i++ )
+  {
+    QAction* a = mySet.at( i );
+    w->insertAction( this, a );
+  }
+}
+
+bool QtxActionSet::isEmptyAction() const
+{
+  return true;
+}
+
+/*!
+  \fn void QtxActionSet::triggered( int id );
+  \brief Emitted when some child action is activated by the user.
+  \param action ID
+*/
+
+/*!
+  \fn void QtxActionSet::triggered( QAction* a );
+  \brief Emitted when some child action is activated by the user.
+  \param a action being activated
+*/
diff --git a/src/Qtx/QtxActionSet.h b/src/Qtx/QtxActionSet.h
new file mode 100644 (file)
index 0000000..4de8997
--- /dev/null
@@ -0,0 +1,89 @@
+// 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
+//
+// File:      QtxActionSet.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXACTIONSET_H
+#define QTXACTIONSET_H
+
+#include "QtxAction.h"
+
+#include <QList>
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxActionSet : public QtxAction
+{
+  Q_OBJECT
+
+public:
+  QtxActionSet( QObject* = 0 );
+  virtual ~QtxActionSet();
+
+  QList<QAction*> actions() const;
+  void            setActions( const QList<QAction*>& );
+
+  void            insertActions( const QList<QAction*>&, const int = -1 );
+
+  int             insertAction( QAction*, const int id = -1, const int = -1 );
+  int             insertAction( const QString&, const int id = -1, const int = -1 );
+  int             insertAction( const QString&, const QIcon&, const int id = -1, const int = -1 );
+
+  void            removeAction( QAction* );
+  void            removeAction( const int );
+
+  void            clear();
+
+signals:
+  void            triggered( int );
+  void            triggered( QAction* );
+
+private slots:
+  void            onChanged();
+  void            onActionTriggered( bool = false );
+
+protected:
+  virtual void    addedTo( QWidget* );
+  virtual void    removedFrom( QWidget* );
+
+  QAction*        action( int ) const;
+  int             actionId( QAction* ) const;
+  void            setActionId( QAction*, const int );
+
+  virtual bool    isEmptyAction() const;
+
+private:
+  void            update();
+  void            update( QWidget* );
+  int             generateId() const;
+
+private:
+  typedef QList<QAction*>     ActionList;
+
+private:
+  ActionList      mySet;      //!< actions list
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
index ed0455cc314ca8ff67589abd0e00920a1c57cb17..a13c60e3ca72c5570cc8c690142137cfb177c726 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      QtxActionToolMgr.cxx
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #include "QtxActionToolMgr.h"
 
 #include "QtxAction.h"
 #include "QtxToolBar.h"
 
-#include <QtGui/qmainwindow.h>
+#include <QMainWindow>
 
 /*!
-  Constructor
+  \class QtxActionToolMgr::ToolNode
+  \brief Represents a toolbutton inside toolbar structure.
+  \internal
+*/
+
+/*!
+  \fn QtxActionToolMgr::ToolNode::ToolNode()
+  \internal
+  \brief Default constructor.
+*/
+
+/*!
+  \fn QtxActionToolMgr::ToolNode::ToolNode( const int _id )
+  \brief Constructor.
+  \internal
+  \param _id toolbar node ID
+*/
+
+/*!
+  \class QtxActionToolMgr
+  \brief Toolbar actions manager.
+  
+  Toolbar manager allows using of set of action for automatic generating of
+  application toolbars and dynamic update of toolbars contents.
+
+  Use insert(), append() and remove() methods to create toolbar and add actions to it.
+  Methods show(), hide() allow displaying/erasing of specified toolbar items.
+
+  Toolbar manager automatically optimizes toolbars by removing extra separators, etc.
+*/
+
+/*!
+  \brief Constructor.
+  \param p parent main window
 */
 QtxActionToolMgr::QtxActionToolMgr( QMainWindow* p )
 : QtxActionMgr( p ),
-myMainWindow( p )
+  myMainWindow( p )
 {
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionToolMgr::~QtxActionToolMgr()
 {
 }
 
 /*!
-  \return desktop
+  \brief Get parent main window.
+  \return main window pointer
 */
 QMainWindow* QtxActionToolMgr::mainWindow() const
 {
@@ -51,26 +85,30 @@ QMainWindow* QtxActionToolMgr::mainWindow() const
 }
 
 /*!
-  Creates toolbar 
-  \return id of just created toolbar
-  \param name - name of toolbar
-  \param tid - proposed id (if such id is used already, then it will be returned without creation)
+  \brief Create toolbar and assign \a id to it.
+
+  If \a tid is less than 0, the identifier is generated automatically.
+  If toolbar with given \a tid is already registered, the toolbar will not be created.
+
+  \param title toolbar title
+  \param tid requested toolbar ID
+  \return id of created/found toolbar
 */
-int QtxActionToolMgr::createToolBar( const QString& name, const int tid )
+int QtxActionToolMgr::createToolBar( const QString& title, const int tid )
 {
   static int _toolBarId = -1;
 
   int tbId = -1;
   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && tbId == -1; ++it )
   {
-    if ( it.value().toolBar->windowTitle().toLower() == name.toLower() )
+    if ( it.value().toolBar->windowTitle().toLower() == title.toLower() )
       tbId = it.key();
   }
 
   if ( tbId != -1 )
     return tbId;
 
-  QToolBar* tb = find( name, mainWindow() );
+  QToolBar* tb = find( title, mainWindow() );
 
   tbId = tid < 0 ? --_toolBarId : tid;
 
@@ -81,7 +119,8 @@ int QtxActionToolMgr::createToolBar( const QString& name, const int tid )
   {
     tb = new QtxToolBar( true, mainWindow() );
     mainWindow()->addToolBar( tb );
-    tb->setWindowTitle( name );
+    tb->setWindowTitle( title );
+    tb->setObjectName( title );
   }
 
   tInfo.toolBar = tb;
@@ -91,16 +130,17 @@ int QtxActionToolMgr::createToolBar( const QString& name, const int tid )
 }
 
 /*!
-  \return toolbar by title
-  \param label - toolbar title
-  \param mw - desktop
+  \brief Search toolbar with given \a title owned by main window \mw. 
+  \param title toolbar title
+  \param mw main window
+  \return toolbar or 0 if it is not found
 */
-QToolBar* QtxActionToolMgr::find( const QString& label, QMainWindow* mw ) const
+QToolBar* QtxActionToolMgr::find( const QString& title, QMainWindow* mw ) const
 {
   if ( !mw )
     return 0;
 
-  QString pattern = label.toLower();
+  QString pattern = title.toLower();
 
   QToolBar* res = 0;
   QList<QToolBar*> toolbars = qFindChildren<QToolBar*>( mw );
@@ -113,8 +153,8 @@ QToolBar* QtxActionToolMgr::find( const QString& label, QMainWindow* mw ) const
 }
 
 /*!
-  Removes toolbar
-  \param tid - toolbar id
+  \brief Remove toolbar.
+  \param tid toolbar ID
 */
 void QtxActionToolMgr::removeToolBar( const int tid )
 {
@@ -126,19 +166,20 @@ void QtxActionToolMgr::removeToolBar( const int tid )
 }
 
 /*!
-  Removes toolbar
-  \param tname - toolbar name
+  \brief Remove toolbar.
+  \param title toolbar title
 */
-void QtxActionToolMgr::removeToolBar( const QString& tname )
+void QtxActionToolMgr::removeToolBar( const QString& title )
 {
-  removeToolBar( find( tname ) );
+  removeToolBar( find( title ) );
 }
 
 /*!
-  Insert action into toolbar
-  \param id - identificator of action
-  \param tId - identificator of toolbar
-  \param idx - position inside toolbar
+  \brief Insert action into toolbar.
+  \param id action ID
+  \param tid toolbar ID
+  \param idx action index in the toolbar (if < 0, action is appended to the end)
+  \return action ID
 */
 int QtxActionToolMgr::insert( const int id, const int tid, const int idx )
 {
@@ -148,8 +189,7 @@ int QtxActionToolMgr::insert( const int id, const int tid, const int idx )
   if ( containsAction( id, tid ) )
     remove( id, tid );
 */
-  ToolNode node;
-  node.id = id;
+  ToolNode node( id );
 
   NodeList& list = myToolBars[tid].nodes;
   int index = idx < 0 ? list.count() : qMin( idx, (int)list.count() );
@@ -160,42 +200,46 @@ int QtxActionToolMgr::insert( const int id, const int tid, const int idx )
 }
 
 /*!
-  Insert action into toolbar
-  \param act - action
-  \param tId - identificator of toolbar
-  \param pos - position inside toolbar
+  \brief Insert action into toolbar.
+  \param a action
+  \param tid toolbar ID
+  \param idx action index in the toolbar (if < 0, action is appended to the end)
+  \return action ID
 */
-int QtxActionToolMgr::insert( QAction* act, const int tid, const int pos )
+int QtxActionToolMgr::insert( QAction* a, const int tid, const int idx )
 {
-  return insert( registerAction( act ), tid, pos );
+  return insert( registerAction( a ), tid, idx );
 }
 
 /*!
-  Insert action into toolbar
-  \param id - identificator of action
-  \param tname - name of toolbar
-  \param pos - position inside toolbar
+  \brief Insert action into toolbar.
+  \param id action ID
+  \param title toolbar title
+  \param idx action index in the toolbar (if < 0, action is appended to the end)
+  \return action ID
 */
-int QtxActionToolMgr::insert( const int id, const QString& tname, const int pos )
+int QtxActionToolMgr::insert( const int id, const QString& title, const int idx )
 {
-  return insert( id, createToolBar( tname ), pos );
+  return insert( id, createToolBar( title ), idx );
 }
 
 /*!
-  Insert action into toolbar
-  \param act - action
-  \param tname - name of toolbar
-  \param pos - position inside toolbar
+  \brief Insert action into toolbar.
+  \param a action
+  \param title toolbar title
+  \param idx action index in the toolbar (if < 0, action is appended to the end)
+  \return action ID
 */
-int QtxActionToolMgr::insert( QAction* act, const QString& tname, const int pos )
+int QtxActionToolMgr::insert( QAction* a, const QString& title, const int idx )
 {
-  return insert( registerAction( act ), createToolBar( tname ), pos );
+  return insert( registerAction( a ), createToolBar( title ), idx );
 }
 
 /*!
-  Append action into toolbar as last toolbutton
-  \param id - identificator of action
-  \param tId - identificator of toolbar
+  \brief Append action to the end of toolbar.
+  \param id action ID
+  \param tid toolbar ID
+  \return action ID
 */
 int QtxActionToolMgr::append( const int id, const int tid )
 {
@@ -203,39 +247,43 @@ int QtxActionToolMgr::append( const int id, const int tid )
 }
 
 /*!
-  Append action into toolbar as last toolbutton
-  \param act - action
-  \param tId - identificator of toolbar
+  \brief Append action to the end of toolbar.
+  \param a action
+  \param tid toolbar ID
+  \return action ID
 */
-int QtxActionToolMgr::append( QAction* act, const int tid )
+int QtxActionToolMgr::append( QAction* a, const int tid )
 {
-  return insert( act, tid );
+  return insert( a, tid );
 }
 
 /*!
-  Append action into toolbar as last toolbutton
-  \param id - identificator of action
-  \param tname - toolbar name
+  \brief Append action to the end of toolbar.
+  \param id action ID
+  \param title toolbar title
+  \return action ID
 */
-int QtxActionToolMgr::append( const int id, const QString& tname )
+int QtxActionToolMgr::append( const int id, const QString& title )
 {
-  return insert( id, tname );
+  return insert( id, title );
 }
 
 /*!
-  Append action into toolbar as last toolbutton
-  \param act - action
-  \param tname - toolbar name
+  \brief Append action to the end of toolbar.
+  \param a action
+  \param title toolbar title
+  \return action ID
 */
-int QtxActionToolMgr::append( QAction* act, const QString& tname )
+int QtxActionToolMgr::append( QAction* a, const QString& title )
 {
-  return insert( act, tname );
+  return insert( a, title );
 }
 
 /*!
-  Append action into toolbar as first toolbutton
-  \param id - identificator of action
-  \param tId - identificator of toolbar
+  \brief Insert action to the beginning of toolbar.
+  \param id action ID
+  \param tid toolbar ID
+  \return action ID
 */
 int QtxActionToolMgr::prepend( const int id, const int tid )
 {
@@ -243,39 +291,42 @@ int QtxActionToolMgr::prepend( const int id, const int tid )
 }
 
 /*!
-  Append action into toolbar as first toolbutton
-  \param act - action
-  \param tId - identificator of toolbar
+  \brief Insert action to the beginning of toolbar.
+  \param a action
+  \param tid toolbar ID
+  \return action ID
 */
-int QtxActionToolMgr::prepend( QAction* act, const int tid )
+int QtxActionToolMgr::prepend( QAction* a, const int tid )
 {
-  return insert( act, tid, 0 );
+  return insert( a, tid, 0 );
 }
 
 /*!
-  Append action into toolbar as first toolbutton
-  \param id - identificator of action
-  \param tname - toolbar name
+  \brief Insert action to the beginning of toolbar.
+  \param id action ID
+  \param title toolbar title
+  \return action ID
 */
-int QtxActionToolMgr::prepend( const int id, const QString& tname )
+int QtxActionToolMgr::prepend( const int id, const QString& title )
 {
-  return insert( id, tname, 0 );
+  return insert( id, title, 0 );
 }
 
 /*!
-  Append action into toolbar as first toolbutton
-  \param act - action
-  \param tname - toolbar name
+  \brief Insert action to the beginning of toolbar.
+  \param a action ID
+  \param title toolbar title
+  \return action ID
 */
-int QtxActionToolMgr::prepend( QAction* act, const QString& tname )
+int QtxActionToolMgr::prepend( QAction* a, const QString& title )
 {
-  return insert( act, tname, 0 );
+  return insert( a, title, 0 );
 }
 
 /*!
-  Remove action from toolbar
-  \param id - identificator of action
-  \param tId - identificator of toolbar
+  \brief Remove action from toolbar.
+  \param id action ID
+  \param tid toolbar ID
 */
 void QtxActionToolMgr::remove( const int id, const int tid )
 {
@@ -296,18 +347,19 @@ void QtxActionToolMgr::remove( const int id, const int tid )
 }
 
 /*!
-  Remove action from toolbar
-  \param id - identificator of action
-  \param tname - name of toolbar
+  \brief Remove action from toolbar.
+  \param id action ID
+  \param title toolbar title
 */
-void QtxActionToolMgr::remove( const int id, const QString& tname )
+void QtxActionToolMgr::remove( const int id, const QString& title )
 {
-  remove( id, find( tname ) );
+  remove( id, find( title ) );
 }
 
 /*!
-  \return toolbar by it's id
-  \param tId - identificator of toolbar
+  \brief Get toolbar by given \a tid.
+  \param tid toolbar ID
+  \return toolbar or 0 if it is not found
 */
 QToolBar* QtxActionToolMgr::toolBar( const int tid ) const
 {
@@ -318,17 +370,19 @@ QToolBar* QtxActionToolMgr::toolBar( const int tid ) const
 }
 
 /*!
-  \return toolbar by it's name
-  \param tname - name of toolbar
+  \brief Get toolbar by given \a title.
+  \param title toolbar title
+  \return toolbar or 0 if it is not found
 */
-QToolBar* QtxActionToolMgr::toolBar( const QString& tname ) const
+QToolBar* QtxActionToolMgr::toolBar( const QString& title ) const
 {
-  return toolBar( find( tname ) );
+  return toolBar( find( title ) );
 }
 
 /*!
-  \return true if manager contains toolbar with such id
-  \param tId - identificator of toolbar
+  \brief Check if toolbar with given \a id already registered.
+  \param tid toolbar ID
+  \return \c true if toolbar is registered in the toolbar manager
 */
 bool QtxActionToolMgr::hasToolBar( const int tid ) const
 {
@@ -336,18 +390,20 @@ bool QtxActionToolMgr::hasToolBar( const int tid ) const
 }
 
 /*!
-  \return true if manager contains toolbar with such name
-  \param tname - name of toolbar
+  \brief Check if toolbar with given \a id already registered.
+  \param title toolbar title
+  \return \c true if toolbar is registered in the toolbar manager
 */
-bool QtxActionToolMgr::hasToolBar( const QString& tname ) const
+bool QtxActionToolMgr::hasToolBar( const QString& title ) const
 {
-  return find( tname ) != -1;
+  return find( title ) != -1;
 }
 
 /*!
-  \return true if toolbar contains action
-  \param id - identificator of action
-  \param tId - identificator of toolbar
+  \brief Check if toolbar contains given action.
+  \param id action ID
+  \param tid toolbar ID
+  \return \c true if toolbar contains action
 */
 bool QtxActionToolMgr::containsAction( const int id, const int tid ) const
 {
@@ -365,7 +421,9 @@ bool QtxActionToolMgr::containsAction( const int id, const int tid ) const
 }
 
 /*!
-  SLOT: called when toolbar is destroyed, removes just destroyed toolbar from map
+  \brief Called when toolbar is destroyed.
+
+  Clears internal pointer to the toolbar to disable crashes.
 */
 void QtxActionToolMgr::onToolBarDestroyed()
 {
@@ -373,49 +431,51 @@ void QtxActionToolMgr::onToolBarDestroyed()
 }
 
 /*!
-  \return id of toolbar by it's name
-  \param tname - name of toolbar
+  \brief Search toolbar by given \a name.
+  \param title toolbar title
+  \return toolbar ID or -1 if it is not found
 */
-int QtxActionToolMgr::find( const QString& tname ) const
+int QtxActionToolMgr::find( const QString& title ) const
 {
   int id = -1;
   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
   {
-    if ( it.value().toolBar->windowTitle() == tname )
+    if ( it.value().toolBar->windowTitle() == title )
       id = it.key();
   }
   return id;
 }
 
 /*!
-  \return id of toolbar
-  \param t - toolbar
+  \brief Get toolbar identifier.
+  \param tb toolbar
+  \return toolbar ID or -1 if toolbar is not registered
 */
-int QtxActionToolMgr::find( QToolBar* t ) const
+int QtxActionToolMgr::find( QToolBar* tb ) const
 {
   int id = -1;
   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
   {
-    if ( it.value().toolBar == t )
+    if ( it.value().toolBar == tb )
       id = it.key();
   }
   return id;
 }
 
 /*!
-  Updates toolbar
-  \param tId - toolbar id
+  \brief Update toolbar.
+  \param tid toolbar ID
 */
-void QtxActionToolMgr::updateToolBar( const int tId )
+void QtxActionToolMgr::updateToolBar( const int tid )
 {
   if ( !isUpdatesEnabled() )
     return;
 
-  if ( !myToolBars.contains( tId ) )
+  if ( !myToolBars.contains( tid ) )
     return;
 
-  QToolBar* tb = myToolBars[tId].toolBar;
-  const NodeList& list = myToolBars[tId].nodes;
+  QToolBar* tb = myToolBars[tid].toolBar;
+  const NodeList& list = myToolBars[tid].nodes;
 
   for ( NodeList::const_iterator it = list.begin(); it != list.end(); ++it )
   {
@@ -429,7 +489,7 @@ void QtxActionToolMgr::updateToolBar( const int tId )
 
   for ( NodeList::const_iterator itr = list.begin(); itr != list.end(); ++itr )
   {
-    if ( !isVisible( (*itr).id, tId ) )
+    if ( !isVisible( (*itr).id, tid ) )
       continue;
 
     QAction* a = action( (*itr).id );
@@ -442,7 +502,7 @@ void QtxActionToolMgr::updateToolBar( const int tId )
 }
 
 /*!
-  Updates all toolbars
+  \brief Update all registered toolbars.
 */
 void QtxActionToolMgr::internalUpdate()
 {
@@ -456,35 +516,36 @@ void QtxActionToolMgr::internalUpdate()
 }
 
 /*!
-  Removes excess separators from toolbar
+  \brief Remove extra separators from the toolbar.
+  \param tb toolbar
 */
-void QtxActionToolMgr::simplifySeparators( QToolBar* t )
+void QtxActionToolMgr::simplifySeparators( QToolBar* tb )
 {
-  Qtx::simplifySeparators( t );
+  Qtx::simplifySeparators( tb );
 }
 
 /*!
-  Shows action in all toolbars
-  \param actId - action id
+  \brief Show action (in all toolbars).
+  \param id action ID
 */
-void QtxActionToolMgr::show( const int actId )
+void QtxActionToolMgr::show( const int id )
 {
-  setShown( actId, true );
+  setShown( id, true );
 }
 
 /*!
-  Hides action in all toolbars
-  \param actId - action id
+  \brief Hide action (in all toolbars).
+  \param id action ID
 */
-void QtxActionToolMgr::hide( const int actId )
+void QtxActionToolMgr::hide( const int id )
 {
-  setShown( actId, false );
+  setShown( id, false );
 }
 
 /*!
-  Changes shown status of action in all toolbars
-  \param id - action id
-  \param on - new shown status
+  \brief Set visibility status for toolbar action with given \a id.
+  \param id action ID
+  \param on new visibility status
 */
 void QtxActionToolMgr::setShown( const int id, const bool on )
 {
@@ -493,8 +554,9 @@ void QtxActionToolMgr::setShown( const int id, const bool on )
 }
 
 /*!
-  \return true if action is shown in all toolbars
-  \param id - action id
+  \brief Get visibility status for toolbar action with given \a id.
+  \param id action ID
+  \return \c true if action is shown in all toolbars
 */
 bool QtxActionToolMgr::isShown( const int id ) const
 {
@@ -521,39 +583,41 @@ bool QtxActionToolMgr::isShown( const int id ) const
 }
 
 /*!
-  \return shown status of action in toolbar
-  \param id - action id
-  \param tId - toolbar id
+  \brief Check if an action with given \a id is visible in the toolbar \a tid.
+  \param id action ID
+  \param tid toolbar ID
+  \return \c true if action is shown in the toolbar
 */
-bool QtxActionToolMgr::isVisible( const int id, const int tId ) const
+bool QtxActionToolMgr::isVisible( const int id, const int tid ) const
 {
-  if ( !myToolBars.contains( tId ) )
+  if ( !myToolBars.contains( tid ) )
     return false;
 
   bool vis = false;
-  const NodeList& lst = myToolBars[tId].nodes;
+  const NodeList& lst = myToolBars[tid].nodes;
   for ( NodeList::const_iterator it = lst.begin(); it != lst.end() && !vis; ++it )
   {
     const ToolNode& node = *it;
     if ( node.id == id )
+
       vis = node.visible;
   }
   return vis;
 }
 
 /*!
-  Changes action shown status in certain toolbar
-  \param id - action id
-  \param tId - toolbar id
-  \param on - new shown status
+  \brief Show/hide action with given \a id in the toolbar \a tid.
+  \param id action ID
+  \param tid toolbar ID
+  \param on new visibility status
 */
-void QtxActionToolMgr::setVisible( const int id, const int tId, const bool on )
+void QtxActionToolMgr::setVisible( const int id, const int tid, const bool on )
 {
-  if ( !myToolBars.contains( tId ) )
+  if ( !myToolBars.contains( tid ) )
     return;
 
   bool changed = false;
-  NodeList& lst = myToolBars[tId].nodes;
+  NodeList& lst = myToolBars[tid].nodes;
   for ( NodeList::iterator it = lst.begin(); it != lst.end(); ++it )
   {
     ToolNode& node = *it;
@@ -565,13 +629,14 @@ void QtxActionToolMgr::setVisible( const int id, const int tId, const bool on )
   }
 
   if ( changed )
-    triggerUpdate( tId );
+    triggerUpdate( tid );
 }
 
 /*!
-  Loads toolbar content from file
-  \param fname - file name
-  \param r - reader
+  \brief Load toolbar contents from the file.
+  \param fname file name
+  \param r actions reader
+  \return \c true on success and \c false on error
 */
 bool QtxActionToolMgr::load( const QString& fname, QtxActionMgr::Reader& r )
 {
@@ -580,7 +645,9 @@ bool QtxActionToolMgr::load( const QString& fname, QtxActionMgr::Reader& r )
 }
 
 /*!
-  \Perform delayed update
+  \brief Called when delayed content update is performed.
+
+  Customizes the content update operation.
 */
 void QtxActionToolMgr::updateContent()
 {
@@ -593,17 +660,28 @@ void QtxActionToolMgr::updateContent()
 }
 
 /*!
-  \ Sets trigger to update
+  \brief Perform delayed toolbar update.
+  \param tid toolbar ID
 */
-void QtxActionToolMgr::triggerUpdate( const int id )
+void QtxActionToolMgr::triggerUpdate( const int tid )
 {
-  myUpdateIds.insert( id, 0 );
+  myUpdateIds.insert( tid, 0 );
   QtxActionMgr::triggerUpdate();
 }
 
+
+/*!
+  \class QtxActionToolMgr::ToolCreator
+  \brief Toolbars creator.
+
+  Used by Reader to create actions by reading descriptions from the file,
+  create toolbars and fill in the toolbara with the actions.
+*/
+
 /*!
-       Class: QtxActionToolMgr::ToolCreator
-       Level: Public
+  \brief Constructor.
+  \param r actions reader
+  \param mgr toolbar manager
 */
 QtxActionToolMgr::ToolCreator::ToolCreator( QtxActionMgr::Reader* r,
                                             QtxActionToolMgr* mgr )
@@ -613,21 +691,22 @@ QtxActionToolMgr::ToolCreator::ToolCreator( QtxActionMgr::Reader* r,
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxActionToolMgr::ToolCreator::~ToolCreator()
 {
 }
 
 /*!
-  Appends new tool buttons
-  \param tag - tag of toolmenu
-  \param subMenu - it has submenu (not used here)
-  \param attr - list of attributes
-  \param pId - id of action corresponding to parent item
+  \brief Create and append to the action manager a new toolbar or toolbar action.
+  \param tag item tag name
+  \param subMenu \c true if this item is submenu (not used)
+  \param attr attributes map
+  \param tid toolbar ID
+  \return toolbar or toolbar action ID
 */
-int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool subMenu,
-                                           const ItemAttributes& attr, const int tId )
+int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool /*subMenu*/,
+                                           const ItemAttributes& attr, const int tid )
 {  
   if( !myMgr || !reader() )
     return -1;
@@ -643,10 +722,10 @@ int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool subMen
           toggle  = reader()->option( "toggle",    "toggle"    );
 
   int res = -1, actId = intValue( attr, id, -1 );
-  if( tId==-1 )
+  if( tid==-1 )
     res = myMgr->createToolBar( strValue( attr, label ), intValue( attr, id, -1 ) );
   else if( tag==sep )
-    res = myMgr->insert( separator(), tId, intValue( attr, pos, -1 ) );
+    res = myMgr->insert( separator(), tid, intValue( attr, pos, -1 ) );
   else
   {
     QIcon set;
@@ -663,7 +742,7 @@ int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool subMen
         
     connect( newAct );
     int aid = myMgr->registerAction( newAct, actId );
-    res = myMgr->insert( aid, tId, intValue( attr, pos, -1 ) );
+    res = myMgr->insert( aid, tid, intValue( attr, pos, -1 ) );
   }
 
   return res;
index b8b39227d46f831a47800c2cbb1e2d1ca99550e4..be8bda268f510805071295862cc0a995929a8524 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      QtxActionToolMgr.h
-// Author:    Alexander SOLOVYEV, Sergey TELKOV
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
 #ifndef QTXACTIONTOOLMGR_H
 #define QTXACTIONTOOLMGR_H
 
 #include "Qtx.h"
-
-#include <QtCore/qmap.h>
-#include <QtCore/qlist.h>
-
-#include <QtGui/qaction.h>
-
 #include "QtxActionMgr.h"
 
+#include <QMap>
+#include <QList>
+
 class QToolBar;
 class QMainWindow;
+class QAction;
 
 #ifdef WIN32
 #pragma warning( disable:4251 )
 #endif
 
-/*!
-  \class QtxActionToolMgr
-  Allows to use set of action to automatically build set of toolbars.
-  With help of methods insert/append/remove it is possible to 
-  describe toolbars and its internal structure.
-  This manager is able to attune toolbar by removing excess separators
-*/
 class QTX_EXPORT QtxActionToolMgr : public QtxActionMgr
 {
   Q_OBJECT
 
-  /*!
-    \class ToolNode
-    Represents a toolbutton inside toolbar
-    For internal purposes only
-  */
   class ToolNode
   {
   public:
     ToolNode() : id( -1 ), visible( true ) {};
+    ToolNode( const int _id ) : id( _id ), visible( true ) {};
 
-    int       id;
-    bool      visible;
+    int       id;          //!< tool node ID
+    bool      visible;     //!< visibility status
   };
 
-  typedef QList<ToolNode> NodeList;
+  typedef QList<ToolNode> NodeList;    //!< toolbar nodes list
 
 protected:
   class ToolCreator;
@@ -132,19 +119,15 @@ private:
   void            triggerUpdate( const int );
 
 private:
-  typedef struct { NodeList nodes; QToolBar* toolBar; } ToolBarInfo;
-  typedef QMap<int, ToolBarInfo>                        ToolBarMap;
+  typedef struct { NodeList nodes; QToolBar* toolBar; } ToolBarInfo;   //!< toolbar info
+  typedef QMap<int, ToolBarInfo>                        ToolBarMap;    //!< toolbars map
 
 private:
-  ToolBarMap      myToolBars;
-  QMainWindow*    myMainWindow;
-  QMap<int,int>   myUpdateIds;
+  ToolBarMap      myToolBars;      //!< toobars map
+  QMainWindow*    myMainWindow;    //!< parent main window
+  QMap<int,int>   myUpdateIds;     //!< list of actions ID being updated
 };
 
-/*!
-  \class QtxActionToolMgr::ToolCreator
-  Allows to create automatically toolbar by data read from file
-*/
 class QtxActionToolMgr::ToolCreator : public QtxActionMgr::Creator
 {
 public:
@@ -155,7 +138,7 @@ public:
                       const ItemAttributes&, const int );
 
 private:
-  QtxActionToolMgr* myMgr;
+  QtxActionToolMgr* myMgr;         //!< toolbar manager
 };
 
 #endif
diff --git a/src/Qtx/QtxColorButton.cxx b/src/Qtx/QtxColorButton.cxx
new file mode 100644 (file)
index 0000000..d921487
--- /dev/null
@@ -0,0 +1,358 @@
+// 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
+//
+// File:      QtxColorButton.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxColorButton.h"
+
+#include <QMenu>
+#include <QStyle>
+#include <QLayout>
+#include <QBitmap>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QColorDialog>
+#include <QStyleOptionToolButton>
+
+/*!
+  \class QtxColorButton
+  \brief The QtxColorButton class implements a widget for color
+  preference items editing.
+
+  The color preference item is represented as the colored button with
+  assocoiated popup menu whihc is called when the user presses the small 
+  arrow button near it. The popup menu allows selecting of the color
+  from the predefined set. In addition it contains the button which
+  invokes standard "Select color" dialog box.
+
+  Initial color value can be set with setColor() method. Chosen color
+  can be retrieved with the color() method.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+QtxColorButton::QtxColorButton( QWidget* parent )
+: QToolButton( parent )
+{
+  setCheckable( false );
+  setPopupMode( MenuButtonPopup );
+
+  QMenu* pm = new QMenu( this );
+  QGridLayout* grid = new QGridLayout( pm );
+  grid->setMargin( 5 );
+  grid->setSpacing( 0 );
+
+  QList<QColor> cList = colorsList();
+  int w = 8;
+  int h = cList.count() / w;
+
+  for ( int y = 0; y < h; y++ )
+  {
+    for ( int x = 0; x < w; x++ )
+    {
+      QColor c = cList.at( x * h + y ).toRgb();
+      QToolButton* btn = new QToolButton( pm );
+      btn->setAutoRaise( true );
+      btn->setCheckable( true );
+      myColors.insert( btn, c );
+      grid->addWidget( btn, y, x );
+      
+      btn->installEventFilter( this );
+
+      connect( btn, SIGNAL( clicked( bool ) ), this, SLOT( onToggled( bool ) ) );
+
+      updateButton( btn );
+    }
+  }
+
+  QToolButton* other = new QToolButton( pm );
+  other->setText( tr( "Other colors..." ) );
+  other->setAutoRaise( true );
+  other->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  grid->addWidget( other, grid->rowCount(), 0, 1, grid->columnCount() );
+  connect( other, SIGNAL( clicked( bool ) ), this, SLOT( onDialogClicked( bool ) ) );
+
+  other->installEventFilter( this );
+
+  setMenu( pm );
+
+  connect( this, SIGNAL( clicked( bool ) ), this, SLOT( onClicked( bool ) ) );
+  connect( pm,   SIGNAL( aboutToShow() ),   this, SLOT( onAboutToShow() ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxColorButton::~QtxColorButton()
+{
+}
+
+/*!
+  \brief Get currently selected color.
+
+  Returns null QColor if no color is selected.
+
+  \return selected color
+  \sa setColor()
+*/
+QColor QtxColorButton::color() const
+{
+  return myColors.contains( this ) ? myColors[this] : QColor();
+}
+
+/*!
+  \brief Set color.
+  \param c color to be set as current
+  \sa color()
+*/
+void QtxColorButton::setColor( const QColor& c )
+{
+  myColors.insert( this, c );
+  updateState();
+  update();
+}
+
+/*!
+  \brief Filter events for the child widgets.
+  \param o event receiver object
+  \param e event
+  \return \c true if the event should be filtered
+*/
+bool QtxColorButton::eventFilter( QObject* o, QEvent* e )
+{
+  if ( e->type() == QEvent::Leave )
+    updateButton( qobject_cast<QToolButton*>( o ) );
+  return QToolButton::eventFilter( o, e );
+}
+
+/*!
+  \brief Called when the popup menu is about to show.
+
+  Updates the menu and child widgets state.
+*/
+void QtxColorButton::onAboutToShow()
+{
+  updateState();
+}
+
+/*!
+  \brief Called when the button is clicked by the user.
+
+  Emits the signal clicked( QColor ).
+
+  \param on button state (not used)
+*/
+void QtxColorButton::onClicked( bool /*on*/ )
+{
+  emit clicked( color() );
+}
+
+/*!
+  \brief Called when any color selection button from popup menu
+  is clicked.
+
+  Changes the currently selected color and emits the signal
+  changed( QColor ).
+
+  \param on button state
+*/
+void QtxColorButton::onToggled( bool on )
+{
+  const QToolButton* tb = ::qobject_cast<QToolButton*>( sender() );
+  if ( !tb )
+    return;
+
+  QColor old = color();
+
+  if ( on && myColors.contains( tb ) )
+  {
+    myColors.insert( this, myColors[tb] );
+    updateButton( this );
+  }
+
+  if ( menu() )
+    menu()->hide();
+
+  updateState();
+
+  if ( old != color() )
+    emit changed( color() );
+}
+
+/*!
+  \brief Called the "Other colors" child button from popup menu
+  is clicked.
+
+  Invokes standard "Select color" dialog box allowing user to select
+  custom color. If the current color is changed by the user, emits 
+  the signal changed( QColor ).
+
+  \param on (not used)
+*/
+void QtxColorButton::onDialogClicked( bool )
+{
+  QColor c = QColorDialog::getColor( color(), this );
+  if ( !c.isValid() )
+    return;
+
+  QColor old = color();
+
+  setColor( c );
+
+  if ( old != color() )
+    emit changed( color() );
+}
+
+/*!
+  \brief Customize paint event for the widget.
+  \param e paint event
+*/
+void QtxColorButton::paintEvent( QPaintEvent* e )
+{
+  QToolButton::paintEvent( e );
+
+  if ( !color().isValid() )
+    return;
+
+  QStyleOptionToolButton opt;
+  opt.initFrom( this );
+  opt.text = text();
+  opt.icon = icon();
+  opt.features = QStyleOptionToolButton::Menu;
+
+  QRect r = style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton );
+  r.setTopLeft( r.topLeft() + QPoint( 2, 2 ) );
+  r.setBottomRight( r.bottomRight() - QPoint( 2, 2 ) );
+
+  QPixmap pix( r.size() );
+  pix.fill( palette().color( backgroundRole() ) );
+  drawColor( &pix, color() );
+
+  QPainter p( this );
+  p.drawPixmap( r, pix );
+  p.end();
+}
+
+/*!
+  \brief Update widget state.
+*/
+void QtxColorButton::updateState()
+{
+  QList<QToolButton*> bList = qFindChildren<QToolButton*>( menu() );
+  for ( QList<QToolButton*>::iterator cit = bList.begin(); cit != bList.end(); ++cit )
+    updateButton( *cit );
+}
+
+/*!
+  \brief Update child button state.
+  \param btn child button
+*/
+void QtxColorButton::updateButton( QToolButton* btn )
+{
+  QColor c = color().toRgb();
+  bool block = btn->signalsBlocked();
+  btn->blockSignals( true );
+  btn->setChecked( false );
+  if ( myColors.contains( btn ) ) {
+    btn->setIcon( buttonIcon( myColors[btn] ) );
+    btn->setChecked( myColors[btn].toRgb() == c );
+  }
+  btn->setDown( false );
+  btn->blockSignals( block );
+}
+
+/*!
+  \brief Generate (if necessary) or get the icon for the button.
+  \param c color to be used for the icon
+  \return icon pixmap for the button
+*/
+QPixmap QtxColorButton::buttonIcon( const QColor& c ) const
+{
+  static QMap<int, QPixmap> pixMap;
+
+  if ( pixMap.contains( c.rgb() ) )
+    return pixMap[c.rgb()];
+
+  QPixmap pix( 16, 16 );
+
+  QColor bg = Qt::white;
+  if ( bg == c )
+    bg = Qt::gray;
+  pix.fill( bg );
+
+  drawColor( &pix, c );
+
+  pix.setMask( pix.createHeuristicMask() );
+
+  pixMap.insert( c.rgb(), pix );
+
+  return pix;
+}
+
+/*!
+  \brief Draw pixmap.
+  \param pd paint device
+  \param c color
+  \param m margin
+*/
+void QtxColorButton::drawColor( QPaintDevice* pd, const QColor& c, const int m ) const
+{
+  if ( !pd )
+    return;
+
+  QPainter p( pd );
+  p.setPen( Qt::black );
+  p.fillRect( m, m, pd->width() - 2 * m - 1, pd->height() - 2 * m - 1, QBrush( c ) );
+  p.drawRect( m, m, pd->width() - 2 * m - 1, pd->height() - 2 * m - 1 );
+  p.end();
+}
+
+/*!
+  \brief Get predefined list of colors to be used in the popup menu.
+  \return list of colors
+*/
+QList<QColor> QtxColorButton::colorsList() const
+{
+  QList<QColor> lst;
+
+  for ( int g = 0; g < 4; g++ )
+  {
+    for ( int r = 0; r < 4; r++ )
+    {
+      for ( int b = 0; b < 3; b++ )
+        lst.append( QColor( qRgb( r * 255 / 3, g * 255 / 3, b * 255 / 2 ) ) );
+    }
+  }
+  return lst;
+}
+
+/*!
+  \fn void QtxColorButton::clicked( QColor color );
+  \brief This signal is emitted when the widget button is clicked by 
+         the user.
+  \param color current color
+*/
+
+/*!
+  \fn void QtxColorButton::changed( QColor color );
+  \brief This signal is emitted when the current color is changed.
+  \param color new current color
+*/
diff --git a/src/Qtx/QtxColorButton.h b/src/Qtx/QtxColorButton.h
new file mode 100644 (file)
index 0000000..bb7a37e
--- /dev/null
@@ -0,0 +1,75 @@
+// 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
+//
+// File:      QtxColorButton.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXCOLORBUTTON_H
+#define QTXCOLORBUTTON_H
+
+#include "Qtx.h"
+
+#include <QMap>
+#include <QColor>
+#include <QPixmap>
+#include <QToolButton>
+
+class QPaintDevice;
+
+class QTX_EXPORT QtxColorButton : public QToolButton
+{
+  Q_OBJECT
+
+public:
+  QtxColorButton( QWidget* = 0 );
+  virtual ~QtxColorButton();
+
+  QColor        color() const;
+  void          setColor( const QColor& );
+
+  bool          eventFilter( QObject*, QEvent* );
+
+signals:
+  void          clicked( QColor );
+  void          changed( QColor );
+
+private slots:
+  void          onAboutToShow();
+  void          onClicked( bool );
+  void          onToggled( bool );
+  void          onDialogClicked( bool );
+
+protected:
+  virtual void  paintEvent( QPaintEvent* );
+
+private:
+  QList<QColor> colorsList() const;
+
+  void          updateState();
+  void          updateButton( QToolButton* );
+  QPixmap       buttonIcon( const QColor& ) const;
+  void          drawColor( QPaintDevice*, const QColor&, const int = 1 ) const;
+
+private:
+  typedef QMap<const QToolButton*, QColor> ColorMap;
+
+private:
+  ColorMap      myColors;
+};
+
+#endif
index 2a62d888e567b8699a483ac15eb61662df3451c5..97b61a2b30d624380e53998f266422fa61356a4f 100755 (executable)
 
 #include "QtxColorScale.h"
 
-#include <QtCore/qmap.h>
-#include <QtCore/qregexp.h>
-#include <QtCore/qstringlist.h>
-
-#include <QtGui/qimage.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qbitmap.h>
-#include <QtGui/qpainter.h>
-#include <QtGui/qtextdocument.h>
+#include <QMap>
+#include <QRegExp>
+#include <QStringList>
+#include <QPixmap>
+#include <QPainter>
+#include <QTextDocument>
 
 #include <math.h>
 
 /*!
-  Constructor
+  \class QtxColorScale
+  \brief Color Scale widget.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+  \param f widget flags
 */
 QtxColorScale::QtxColorScale( QWidget* parent, Qt::WindowFlags f )
 : QFrame( parent, f ),
-myMin( 0.0 ),
-myMax( 1.0 ),
-myTitle( "" ),
-myInterval( 10 ),
-myFormat( "%.4g" ),
-myColorMode( Auto ),
-myLabelMode( Auto ),
-myLabelPos( Right ),
-myTitlePos( Center ),
-myDumpMode( NoDump ),
-myFlags( AtBorder | WrapTitle )
+  myMin( 0.0 ),
+  myMax( 1.0 ),
+  myTitle( "" ),
+  myFormat( "%.4g" ),
+  myInterval( 10 ),
+  myDumpMode( NoDump ),
+  myColorMode( Auto ),
+  myLabelMode( Auto ),
+  myFlags( AtBorder | WrapTitle ),
+  myLabelPos( Right ),
+  myTitlePos( Center )
 {
-       setWindowTitle( tr ( "Color scale" ) );
+  setWindowTitle( tr ( "Color scale" ) );
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param num number of color scale intervals
+  \param parent parent widget
+  \param f widget flags
 */
 QtxColorScale::QtxColorScale( const int num, QWidget* parent, Qt::WindowFlags f )
 : QFrame( parent, f ),
-myMin( 0.0 ),
-myMax( 1.0 ),
-myTitle( "" ),
-myInterval( num ),
-myFormat( "%.4g" ),
-myColorMode( Auto ),
-myLabelMode( Auto ),
-myLabelPos( Right ),
-myTitlePos( Center ),
-myDumpMode( NoDump ),
-myFlags( AtBorder | WrapTitle )
+  myMin( 0.0 ),
+  myMax( 1.0 ),
+  myTitle( "" ),
+  myFormat( "%.4g" ),
+  myInterval( num ),
+  myDumpMode( NoDump ),
+  myColorMode( Auto ),
+  myLabelMode( Auto ),
+  myFlags( AtBorder | WrapTitle ),
+  myLabelPos( Right ),
+  myTitlePos( Center )
 {
-       setWindowTitle( tr ( "Color scale" ) );
+  setWindowTitle( tr ( "Color scale" ) );
 }
 
 /*!
-  Destructor
+  \brief Destructor.
+
+  Does nothing for the moment.
 */
 QtxColorScale::~QtxColorScale()
 {
 }
 
 /*!
-  \returns minimal limit of scale.
+  \brief Get color scale minimum value.
+  \return lower limit of the color scale
 */
 double QtxColorScale::minimum() const
 {
-       return myMin;
+  return myMin;
 }
 
 /*!
-  \return maximal limit of scale.
+  \brief Get color scale maximum value.
+  \return upper limit of the color scale
 */
 double QtxColorScale::maximum() const
 {
-       return myMax;
+  return myMax;
 }
 
 /*!
-  \return range (minimal and maximal limits) of scale.
+  \brief Get color scale range.
+  \param min returning lower limit of the color scale
+  \param max returning upper limit of the color scale
 */
 void QtxColorScale::range( double& min, double& max ) const
 {
-       min = myMin;
-       max = myMax;
+  min = myMin;
+  max = myMax;
 }
 
 /*!
-  \return the current title string.
+  \brief Get color scale title.
+  \return current title
 */
 QString QtxColorScale::title() const
 {
-       return myTitle;
+  return myTitle;
 }
 
 /*!
-  \returns the current format of number presentation in labels for Auto label mode (sprintf specification).
+  \brief Get current format of the number presentation.
+
+  This format is used to output values in the color scale labels
+  in "Auto" label mode. The format uses sprintf specification.
+
+  \return current format
 */
 QString QtxColorScale::format() const
 {
-       return myFormat;
+  return myFormat;
 }
 
 /*!
-  \return dump mode.
+  \brief Get Color scale dump mode.
+  \return current dump mode (QtxColorScale::DumpMode)
 */
 int QtxColorScale::dumpMode() const
 {
-       return myDumpMode;
+  return myDumpMode;
 }
 
 /*!
-  \return label mode.
+  \brief Get label mode.
+  \return current label mode (QtxColorScale::Mode)
 */
 int QtxColorScale::labelMode() const
 {
-       return myLabelMode;
+  return myLabelMode;
 }
 
 /*!
-  \return color mode.
+  \brief Get color mode.
+  \return current color mode (QtxColorScale::Mode)
 */
 int QtxColorScale::colorMode() const
 {
-       return myColorMode;
+  return myColorMode;
 }
 
 /*!
-  \return intervals number of color scale.
+  \brief Get number of color scale intervals.
+  \return number of intervals
 */
 int QtxColorScale::intervalsNumber() const
 {
-       return myInterval;
+  return myInterval;
 }
 
 /*!
-  \return the user label of specified interval.
+  \brief Get user label for the specified color scale interval.
+  \param idx interval index
+  \return user label for specified interval
 */
 QString QtxColorScale::label( const int idx ) const
 {
-       QString res;
-       if ( idx >= 0 && idx < (int)myLabels.count() )
-               res = myLabels[idx];
-       return res;
+  QString res;
+  if ( idx >= 0 && idx < (int)myLabels.count() )
+    res = myLabels[idx];
+  return res;
 }
 
 /*!
-  \return the user color of specified interval.
+  \brief Get user color for the specified color scale interval.
+  \param idx interval index
+  \return user color for specified interval
 */
 QColor QtxColorScale::color( const int idx ) const
 {
-       QColor res;
-       if ( idx >= 0 && idx < (int)myColors.count() )
-               res = myColors[idx];
-       return res;
+  QColor res;
+  if ( idx >= 0 && idx < (int)myColors.count() )
+    res = myColors[idx];
+  return res;
 }
 
 /*!
-  \return the user labels.
+  \brief Get user labels for all color scale intervals.
+  \param list returning labels list
 */
 void QtxColorScale::labels( QStringList& list ) const
 {
-       list = myLabels;
+  list = myLabels;
 }
 
 /*!
-  \return the user color.
+  \brief Get user colors for all color scale intervals.
+  \param list returning colors list
 */
 void QtxColorScale::colors( QList<QColor>& list ) const
 {
-       list = myColors;
+  list = myColors;
 }
 
 /*!
-  \return the label position.
+  \brief Get label position.
+  \return label position (QtxColorScale::Position)
 */
 int QtxColorScale::labelPosition() const
 {
-       return myLabelPos;
+  return myLabelPos;
 }
 
 /*!
-  \return the title position.
+  \brief Get title position.
+  \return title position (QtxColorScale::Position)
 */
 int QtxColorScale::titlePosition() const
 {
-       return myTitlePos;
+  return myTitlePos;
 }
 
 /*!
-  Sets the minimum limit.
+  \brief Set color scale minimum value.
+  \param val lower limit of the color scale
 */
 void QtxColorScale::setMinimum( const double val )
 {
-       setRange( val, maximum() );
+  setRange( val, maximum() );
 }
 
 /*!
-  Sets the maximum limit.
+  \brief Set color scale maximum value.
+  \param val upper limit of the color scale
 */
 void QtxColorScale::setMaximum( const double val )
 {
-       setRange( minimum(), val );
+  setRange( minimum(), val );
 }
 
 /*!
-  Sets the minimum and maximum limits.
+  \brief Set color scale range.
+  \param min lower limit of the color scale
+  \param max upper limit of the color scale
 */
 void QtxColorScale::setRange( const double min, const double max )
 {
-       if ( myMin == min && myMax == max )
-               return;
-
-       myMin = min;
-       myMax = max;
-
-       myPrecise = QString::null;
+  if ( myMin == min && myMax == max )
+    return;
+  
+  myMin = min;
+  myMax = max;
+  
+  myPrecise = QString::null;
 
-       if ( colorMode() == Auto || labelMode() == Auto )
-               updateScale();
+  if ( colorMode() == Auto || labelMode() == Auto )
+    updateScale();
 }
 
 /*!
-  Sets the title string.
+  \brief Set color scale title.
+  \param str new title
 */
 void QtxColorScale::setTitle( const QString& str )
 {
-       if ( myTitle == str )
-               return;
-
-       myTitle = str;
-       updateScale();
+  if ( myTitle == str )
+    return;
+  
+  myTitle = str;
+  updateScale();
 }
 
 /*!
-  Sets the format of number presentation in labels for
-  Auto label mode (sprintf specification).
+  \brief Set current format of the number presentation.
+  \sa format()
+  \param format new number presentation format
 */
 void QtxColorScale::setFormat( const QString& format )
 {
-       if ( myFormat == format )
-               return;
+  if ( myFormat == format )
+    return;
 
-       myFormat = format;
-       myPrecise = QString::null;
-       if ( colorMode() == Auto )
-               updateScale();
+  myFormat = format;
+  myPrecise = QString::null;
+  if ( colorMode() == Auto )
+    updateScale();
 }
 
 /*!
-  Sets the number of intervals.
+  \brief Set number of color scale intervals.
+  \param num number of intervals
 */
 void QtxColorScale::setIntervalsNumber( const int num )
 {
-       if ( myInterval == num || num < 1 )
-               return;
-
-       myInterval = num;
-       myPrecise = QString::null;
-
-       updateScale();
+  if ( myInterval == num || num < 1 )
+    return;
+  
+  myInterval = num;
+  myPrecise = QString::null;
+  
+  updateScale();
 }
 
 /*!
-  Sets the user label for specified interval. If number
-  of interval is negative then user label will be added
-  as new at the end of list.
+  \brief Set user label for the specified color scale interval.
+
+  If number of interval is negative then user label will be added
+  as new to the end of list.
+
+  \param txt user label
+  \param idx interval index
 */
 void QtxColorScale::setLabel( const QString& txt, const int idx )
 {
-       bool changed = false;
-       uint i = idx < 0 ? myLabels.count() : idx;
-       if ( i < myLabels.count() )
-       {
-               changed = myLabels[i] != txt;
-               myLabels[i] = txt;
-       }
-       else
-       {
-               changed = true;
-               while ( i >= myLabels.count() )
-                   myLabels.append( "" );
-               myLabels[i] = txt;
-       }
-       if ( changed )
-               updateScale();
-}
-
-/*!
-  Sets the user color for specified interval. If number
-  of interval is negative then user color will be added
-  as new at the end of list.
+  bool changed = false;
+  int i = idx < 0 ? myLabels.count() : idx;
+  if ( i < myLabels.count() )
+  {
+    changed = myLabels[i] != txt;
+    myLabels[i] = txt;
+  }
+  else
+  {
+    changed = true;
+    while ( i >= myLabels.count() )
+      myLabels.append( "" );
+    myLabels[i] = txt;
+  }
+  if ( changed )
+    updateScale();
+}
+
+/*!
+  \brief Set user color for the specified color scale interval.
+
+  If number of interval is negative then user color will be added
+  as new to the end of list.
+
+  \param clr user color
+  \param idx interval index
 */
 void QtxColorScale::setColor( const QColor& clr, const int idx )
 {
-       bool changed = false;
-       uint i = idx < 0 ? myColors.count() : idx;
-       if ( i < myColors.count() )
-       {
-               changed = myColors[i] != clr;
-               myColors[i] = clr;
-       }
-       else
-       {
-               changed = true;
-        while ( i >= myColors.count() )
-            myColors.append( QColor() );
-               myColors[i] = clr;
-       }
-       if ( changed )
-               updateScale();
+  bool changed = false;
+  int i = idx < 0 ? myColors.count() : idx;
+  if ( i < myColors.count() )
+  {
+    changed = myColors[i] != clr;
+    myColors[i] = clr;
+  }
+  else
+  {
+    changed = true;
+    while ( i >= myColors.count() )
+      myColors.append( QColor() );
+    myColors[i] = clr;
+  }
+  if ( changed )
+    updateScale();
 }
 
 /*!
-  Replace the all user label with specified list.
+  \brief Set user labels for all color scale intervals.
+  \param list new labels list
 */
 void QtxColorScale::setLabels( const QStringList& list )
 {
-       if ( list.isEmpty() )
-               return;
+  if ( list.isEmpty() )
+    return;
 
-       myLabels = list;
-       updateScale();
+  myLabels = list;
+  updateScale();
 }
 
 /*!
-  Replace the all user colors with specified list.
+  \brief Set user colors for all color scale intervals.
+  \param list new colors list
 */
 void QtxColorScale::setColors( const QList<QColor>& list )
 {
-       if ( list.isEmpty() )
-           return;
+  if ( list.isEmpty() )
+    return;
 
-       myColors = list;
-       updateScale();
+  myColors = list;
+  updateScale();
 }
 
 /*!
-  Sets the color mode (Auto or User).
+  \brief Set color scale color mode.
+  \param mode new color mode (QtxColorScale::Mode)
 */
 void QtxColorScale::setColorMode( const int mode )
 {
-       if ( myColorMode == mode )
-               return;
-
-       myColorMode = mode;
-       updateScale();
+  if ( myColorMode == mode )
+    return;
+  
+  myColorMode = mode;
+  updateScale();
 }
 
 /*!
-  Sets the dump mode.
+  \brief Set color scale dump mode.
+  \param mode new dump mode (QtxColorScale::DumpMode)
 */
 void QtxColorScale::setDumpMode( const int mode )
 {
-       myDumpMode = mode;
+  myDumpMode = mode;
 }
 
 /*!
-  Sets the label mode (Auto or User).
+  \brief Set color scale label mode.
+  \param mode new label mode (QtxColorScale::Mode)
 */
 void QtxColorScale::setLabelMode( const int mode )
 {
-       if ( myLabelMode != mode )
-       {
-               myLabelMode = mode;
-               updateScale();
-       }
+  if ( myLabelMode != mode )
+  {
+    myLabelMode = mode;
+    updateScale();
+  }
 }
 
 /*!
-  Sets the label position.
+  \brief Set label position.
+  \param pos new label position (QtxColorScale::Position)
 */
 void QtxColorScale::setLabelPosition( const int pos )
 {
-       if ( myLabelPos != pos && pos >= None && pos <= Center )
-       {
-               myLabelPos = pos;
-               updateScale();
-       }
+  if ( myLabelPos != pos && pos >= None && pos <= Center )
+  {
+    myLabelPos = pos;
+    updateScale();
+  }
 }
 
 /*!
-  Sets the title position.
+  \brief Set title position.
+  \param pos new title position (QtxColorScale::Position)
 */
 void QtxColorScale::setTitlePosition( const int pos )
 {
-       if ( myTitlePos != pos && pos >= None && pos <= Center )
-       {
-               myTitlePos = pos;
-               updateScale();
-       }
+  if ( myTitlePos != pos && pos >= None && pos <= Center )
+  {
+    myTitlePos = pos;
+    updateScale();
+  }
 }
 
 /*!
-  Set the specified flags.
+  \brief Set color scale flags.
+  \param flags new flags
 */
 void QtxColorScale::setFlags( const int flags )
 {
-       int prev = myFlags;
-       myFlags |= flags;
-       if ( prev != myFlags )
-               updateScale();
+  int prev = myFlags;
+  myFlags |= flags;
+  if ( prev != myFlags )
+    updateScale();
 }
 
 /*!
-  \return true if specified flags are setted.
+  \brief Test color scale flags.
+  \return \c true if specified flags are set
 */
 bool QtxColorScale::testFlags( const int flags ) const
 {
-       return ( myFlags & flags ) == flags;
+  return ( myFlags & flags ) == flags;
 }
 
 /*!
-  Clear (reset) the specified flags.
+  \brief Clear (reset) color scale flags.
+  \param flags color scale flags to be cleared
 */
 void QtxColorScale::clearFlags( const int flags )
 {
-       int prev = myFlags;
-       myFlags &= ~flags;
-       if ( prev != myFlags )
-               updateScale();
+  int prev = myFlags;
+  myFlags &= ~flags;
+  if ( prev != myFlags )
+    updateScale();
 }
 
 /*!
+  \brief Get widget's minumum size hint.
   \return minimum size hint
 */
 QSize QtxColorScale::minimumSizeHint() const
 {
   QSize sz = calculateSize( true, myFlags, titlePosition() != None, labelPosition() != None, true );
-       return sz + QSize( frameWidth(), frameWidth() );
+  return sz + QSize( frameWidth(), frameWidth() );
 }
 
 /*!
+  \brief Get widget's default size hint.
   \return size hint
 */
 QSize QtxColorScale::sizeHint() const
 {
   QSize sz = calculateSize( false, myFlags, titlePosition() != None, labelPosition() != None, true );
-       return sz + QSize( frameWidth(), frameWidth() );
+  return sz + QSize( frameWidth(), frameWidth() );
 }
 
 /*!
-  Dump color scale into pixmap with current size.
+  \brief Calculate color scale size.
+  \param min if \c true, color scale size is calculated to be as smallest as possible
+  \param flags color scale flags
+  \param title color scale title
+  \param labels if \c true take into account labels
+  \param colors if \c true take into account colors
+  \return color scale size
 */
 QSize QtxColorScale::calculateSize( const bool min, const int flags, const bool title,
-                                                                                   const bool labels, const bool colors ) const
+                                   const bool labels, const bool colors ) const
 {
-       int num = intervalsNumber();
-
-       int spacer = 5;
-       int textWidth = 0;
-       int textHeight = fontMetrics().height();
-       int colorWidth = 20;
-
-       if ( labels && colors )
+  int num = intervalsNumber();
+  
+  int spacer = 5;
+  int textWidth = 0;
+  int textHeight = fontMetrics().height();
+  int colorWidth = 20;
+  
+  if ( labels && colors )
   {
     QtxColorScale* that = (QtxColorScale*)this;
     QString fmt = that->myFormat;
 
-               for ( int idx = 0; idx < num; idx++ )
-                       textWidth = qMax( textWidth, fontMetrics().width( getLabel( idx ) ) );
-
+    for ( int idx = 0; idx < num; idx++ )
+      textWidth = qMax( textWidth, fontMetrics().width( getLabel( idx ) ) );
+    
     if ( !min )
       that->myFormat = that->myFormat.replace( QRegExp( "g" ), "f" );
-
-               for ( int index = 0; index < num; index++ )
-                       textWidth = qMax( textWidth, fontMetrics().width( getLabel( index ) ) );
-
+    
+    for ( int index = 0; index < num; index++ )
+      textWidth = qMax( textWidth, fontMetrics().width( getLabel( index ) ) );
+    
     that->myFormat = fmt;
   }
+  
+  int scaleWidth = 0;
+  int scaleHeight = 0;
+  
+  int titleWidth = 0;
+  int titleHeight = 0;
+  
+  if ( flags & AtBorder )
+  {
+    num++;
+    if ( min && title && !myTitle.isEmpty() )
+      titleHeight += 10;
+  }
+  
+  if ( colors )
+  {
+    scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
+    if ( min )
+      scaleHeight = qMax( 2 * num, 3 * textHeight );
+    else
+      scaleHeight = (int)( 1.5 * ( num + 1 ) * textHeight );
+  }
 
-       int scaleWidth = 0;
-       int scaleHeight = 0;
-
-       int titleWidth = 0;
-       int titleHeight = 0;
-
-       if ( flags & AtBorder )
-       {
-               num++;
-               if ( min && title && !myTitle.isEmpty() )
-                       titleHeight += 10;
-       }
-
-       if ( colors )
-       {
-               scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
-               if ( min )
-                       scaleHeight = qMax( 2 * num, 3 * textHeight );
-               else
-                       scaleHeight = (int)( 1.5 * ( num + 1 ) * textHeight );
-       }
-
-       if ( title )
-       {
-               QTextDocument* srt = textDocument( flags );
-               if ( srt )
-               {
-                       QPainter p( (QtxColorScale*)this );
-                       if ( scaleWidth )
-                               srt->setTextWidth( scaleWidth );
-
-                       titleHeight = srt->size().height() + spacer;
-                       titleWidth = srt->size().width() + 10;
-
-               }
+  if ( title )
+  {
+    QTextDocument* srt = textDocument( flags );
+    if ( srt )
+    {
+      QPainter p( (QtxColorScale*)this );
+      if ( scaleWidth )
+       srt->setTextWidth( scaleWidth );
+      
+      titleHeight = (int)srt->size().height() + spacer;
+      titleWidth = (int)srt->size().width() + 10;
+      
+    }
     delete srt;
-       }
-
-       int W = qMax( titleWidth, scaleWidth ) + width() - contentsRect().width();
-       int H = scaleHeight + titleHeight + height() - contentsRect().height();
+  }
 
-       return QSize( W, H );
+  int W = qMax( titleWidth, scaleWidth ) + width() - contentsRect().width();
+  int H = scaleHeight + titleHeight + height() - contentsRect().height();
+  
+  return QSize( W, H );
 }
 
 /*!
-  Dump color scale into pixmap with current size.
+  \brief Dump color scale into pixmap with current size.
+  \return generated pixmap
 */
 QPixmap QtxColorScale::dump() const
 {
-       QPixmap aPix;
-  
-       if ( dumpMode() != NoDump )
-       {
-               aPix = QPixmap( size() );
-               if ( !aPix.isNull() )
-               {
-                       bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
-                       bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
-                                                labelPosition() != None;
-                       bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
-                                                titlePosition() != None;
+  QPixmap aPix;
+  
+  if ( dumpMode() != NoDump )
+  {
+    aPix = QPixmap( size() );
+    if ( !aPix.isNull() )
+    {
+      bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
+      bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
+       labelPosition() != None;
+      bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
+       titlePosition() != None;
       QColor bgc = palette().color( backgroundRole() );
-                       QPainter p;
-                       p.begin( &aPix );
-                       p.fillRect( 0, 0, aPix.width(), aPix.height(), bgc );
-                       drawScale( &p, bgc, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
-                       p.end();
-               }
-       }
-
-       return aPix;
+      QPainter p;
+      p.begin( &aPix );
+      p.fillRect( 0, 0, aPix.width(), aPix.height(), bgc );
+      drawScale( &p, bgc, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
+      p.end();
+    }
+  }
+  
+  return aPix;
 }
 
 /*!
-  Dump color scale into pixmap with specified size.
+  \brief Dump color scale into pixmap with the specified size.
+  \param w pixmap width
+  \param h pixmap height
+  \return generated pixmap
 */
 QPixmap QtxColorScale::dump( const int w, const int h ) const
 {
-       return dump( palette().color( backgroundRole() ), w, h );
+  return dump( palette().color( backgroundRole() ), w, h );
 }
 
 /*!
-  Dump color scale into pixmap with specified size and background color.
+  \brief Dump color scale into pixmap with the specified size and background color.
+  \param bg pixmap background color
+  \param w pixmap width
+  \param h pixmap height
+  \return generated pixmap
 */
 QPixmap QtxColorScale::dump( const QColor& bg, const int w, const int h ) const
 {
-       QPixmap aPix;
-       if ( dumpMode() != NoDump )
-       {
-               bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
-               bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
-                                        labelPosition() != None;
-               bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
-                                        titlePosition() != None;
-
-               int W = w;
-               int H = h;
-               if ( W < 0 || H < 0 )
-               {
-                       QSize sz = calculateSize( false, myFlags & ~WrapTitle, title, label, scale );
-
-                       if ( W < 0 )
-                               W = sz.width();
-                       if ( H < 0 )
-                               H = sz.height();
-               }
-
-               aPix = QPixmap( W, H );
-               if ( !aPix.isNull() )
-               {
-                       QPainter p;
-                       p.begin( &aPix );
-                       p.fillRect( 0, 0, aPix.width(), aPix.height(), bg );
-                       drawScale( &p, bg, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
-                       p.end();
-               }
-       }
-
-       return aPix;
+  QPixmap aPix;
+  if ( dumpMode() != NoDump )
+  {
+    bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
+    bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
+      labelPosition() != None;
+    bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
+      titlePosition() != None;
+    
+    int W = w;
+    int H = h;
+    if ( W < 0 || H < 0 )
+    {
+      QSize sz = calculateSize( false, myFlags & ~WrapTitle, title, label, scale );
+      
+      if ( W < 0 )
+       W = sz.width();
+      if ( H < 0 )
+       H = sz.height();
+    }
+    
+    aPix = QPixmap( W, H );
+    if ( !aPix.isNull() )
+    {
+      QPainter p;
+      p.begin( &aPix );
+      p.fillRect( 0, 0, aPix.width(), aPix.height(), bg );
+      drawScale( &p, bg, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
+      p.end();
+    }
+  }
+  
+  return aPix;
 }
 
 /*!
-  Show the color scale. [Reimplemented]
+  \brief Show color scale (reimplemented from QFrame).
 */
 void QtxColorScale::show()
 {
-       QFrame::show();
+  QFrame::show();
 }
 
 /*!
-  Hides the color scale. [Reimplemented]
+  \brief Hide color scale (reimplemented from QFrame).
 */
 void QtxColorScale::hide()
 {
-       QFrame::hide();
+  QFrame::hide();
 }
 
 /*!
-  Draw color scale contents. [Reimplemented]
+  \brief Draw color scale (reimplemented from QFrame).
+  \param p painter
 */
 void QtxColorScale::drawContents( QPainter* p )
 {
-       if ( !updatesEnabled() )
-               return;
-
-       QRect aDrawRect = contentsRect();
-
-       drawScale( p, false/*testFlags( Transparent )*/, aDrawRect.x(),
-                          aDrawRect.y(), aDrawRect.width(), aDrawRect.height(),
-                          titlePosition() != None, labelPosition() != None, true );
+  if ( !updatesEnabled() )
+    return;
+  
+  QRect aDrawRect = contentsRect();
+  
+  drawScale( p, false/*testFlags( Transparent )*/, aDrawRect.x(),
+            aDrawRect.y(), aDrawRect.width(), aDrawRect.height(),
+            titlePosition() != None, labelPosition() != None, true );
 }
 
 /*!
-  Draw color scale contents.
+  \brief Draw color scale contents.
+  \param p painter
+  \param transp if \c true color scale is drawn on transparent background
+  \param X color scale x coordinate
+  \param Y color scale y coordinate
+  \param W color scale width
+  \param H color scale height
+  \param drawTitle if \c true, draw title
+  \param drawLabel if \c true, draw labels
+  \param drawColors if \c true, draw colors
 */
 void QtxColorScale::drawScale( QPainter* p, const bool transp, const int X, const int Y,
-                               const int W, const int H, const bool title,
-                               const bool label, const bool scale ) const
+                               const int W, const int H, const bool drawTitle,
+                               const bool drawLabel, const bool drawColors ) const
 {
-       QPixmap cache( W, H );
-       QPainter cp( &cache );
-
-       drawScale( &cp, palette().color( backgroundRole() ), transp, 0, 0, W, H, title, label, scale );
-       cp.end();
-
-       p->drawPixmap( X, Y, cache );
+  QPixmap cache( W, H );
+  QPainter cp( &cache );
+  
+  drawScale( &cp, palette().color( backgroundRole() ), transp, 0, 0, W, H, drawTitle, drawLabel, drawColors );
+  cp.end();
+  
+  p->drawPixmap( X, Y, cache );
 }
 
 /*!
-  Draw color scale contents.
+  \brief Draw color scale contents.
+  \param p painter
+  \param bg background color
+  \param transp if \c true color scale is drawn on transparent background
+  \param X color scale x coordinate
+  \param Y color scale y coordinate
+  \param W color scale width
+  \param H color scale height
+  \param drawTitle if \c true, draw title
+  \param drawLabel if \c true, draw labels
+  \param drawColors if \c true, draw colors
 */
 void QtxColorScale::drawScale( QPainter* p, const QColor& bg, const bool transp,
                                const int X, const int Y, const int W, const int H,
                                const bool drawTitle, const bool drawLabel, const bool drawColors ) const
 {
-       if ( !transp )
-               p->fillRect( X, Y, W, H, bg );
-
-       int num = intervalsNumber();
-
-       int labPos = labelPosition();
-
-       int spacer = 5;
-       int textWidth = 0;
-       int textHeight = p->fontMetrics().height();
-
-       QString aTitle = title();
-
-       int titleWidth = 0;
-       int titleHeight = 0;
-
-       if ( qGray( bg.rgb() ) < 128 )
-               p->setPen( QColor( 255, 255, 255 ) );
-       else
+  if ( !transp )
+    p->fillRect( X, Y, W, H, bg );
+  
+  int num = intervalsNumber();
+  
+  int labPos = labelPosition();
+  
+  int spacer = 5;
+  int textWidth = 0;
+  int textHeight = p->fontMetrics().height();
+  
+  QString aTitle = title();
+  
+  int titleWidth = 0;
+  int titleHeight = 0;
+  
+  if ( qGray( bg.rgb() ) < 128 )
+    p->setPen( QColor( 255, 255, 255 ) );
+  else
     p->setPen( QColor( 0, 0, 0 ) );
-
-       // Draw title
-       if ( drawTitle )
-       {
-               QTextDocument* srt = textDocument( myFlags );
-               if ( srt )
-               {
-                       srt->setTextWidth( W - 10 );
-                       titleHeight = srt->size().height() + spacer;
-                       titleWidth = srt->size().width();
+  
+  // Draw title
+  if ( drawTitle )
+  {
+    QTextDocument* srt = textDocument( myFlags );
+    if ( srt )
+    {
+      srt->setTextWidth( W - 10 );
+      titleHeight = (int)srt->size().height() + spacer;
+      titleWidth = (int)srt->size().width();
       p->save();
       p->translate( X + 5, Y );
-                       srt->drawContents( p );
+      srt->drawContents( p );
       p->restore();
-               }
+    }
     delete srt;
-       }
-
-       bool reverse = testFlags( Reverse );
-
-       QList<QColor>  colors;
-       QList<QString> labels;
-       for ( int idx = 0; idx < num; idx++ )
-       {
-               if ( reverse )
-               {
-                       colors.append( getColor( idx ) );
-                       labels.append( getLabel( idx ) );
-               }
-               else
-               {
-                       colors.prepend( getColor( idx ) );
-                       labels.prepend( getLabel( idx ) );
-               }
-       }
-
-       if ( testFlags( AtBorder ) )
-       {
-               if ( reverse )
-                       labels.append( getLabel( num ) );
-               else
-                       labels.prepend( getLabel( num ) );
-               if ( drawLabel )
-                       textWidth = qMax( textWidth, p->fontMetrics().width( labels.last() ) );
-       }
-
-       if ( drawLabel )
-       {
-               const QFontMetrics& fm = p->fontMetrics();
-               for ( QStringList::ConstIterator it = labels.begin(); it != labels.end(); ++it )
-                       textWidth = qMax( textWidth, fm.width( *it) );
-       }
-
-       int lab = labels.count();
-
-       double spc = ( H - ( ( qMin( lab, 2 ) + qAbs( lab - num - 1 ) ) * textHeight ) - titleHeight );
-       double val = spc != 0 ? 1.0 * ( lab - qMin( lab, 2 ) ) * textHeight / spc : 0;
-       double iPart;
-       double fPart = modf( val, &iPart );
-       int filter = (int)iPart + ( fPart != 0 ? 1 : 0 );
-       filter = qMax( filter, 1 );
-
-       double step = 1.0 * ( H - ( lab - num + qAbs( lab - num - 1 ) ) * textHeight - titleHeight ) / num;
-
-       int ascent = p->fontMetrics().ascent();
-       int colorWidth = qMax( 5, qMin( 20, W - textWidth - 3 * spacer ) );
-       if ( labPos == Center || !drawLabel )
-               colorWidth = W - 2 * spacer;
-
-       // Draw colors
-       int x = X + spacer;
-       switch ( labPos )
-       {
-       case Left:
-           x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
-               break;
-       }
-
-       double offset = 1.0 * textHeight / 2 * ( lab - num + qAbs( lab - num - 1 ) ) + titleHeight;
-       QList<QColor>::Iterator cit = colors.begin();
+  }
+
+  bool reverse = testFlags( Reverse );
+  
+  QList<QColor>  colors;
+  QList<QString> labels;
+  for ( int idx = 0; idx < num; idx++ )
+  {
+    if ( reverse )
+    {
+      colors.append( getColor( idx ) );
+      labels.append( getLabel( idx ) );
+    }
+    else
+    {
+      colors.prepend( getColor( idx ) );
+      labels.prepend( getLabel( idx ) );
+    }
+  }
+  
+  if ( testFlags( AtBorder ) )
+  {
+    if ( reverse )
+      labels.append( getLabel( num ) );
+    else
+      labels.prepend( getLabel( num ) );
+    if ( drawLabel )
+      textWidth = qMax( textWidth, p->fontMetrics().width( labels.last() ) );
+  }
+  
+  if ( drawLabel )
+  {
+    const QFontMetrics& fm = p->fontMetrics();
+    for ( QStringList::ConstIterator it = labels.begin(); it != labels.end(); ++it )
+      textWidth = qMax( textWidth, fm.width( *it) );
+  }
+  
+  int lab = labels.count();
+  
+  double spc = ( H - ( ( qMin( lab, 2 ) + qAbs( lab - num - 1 ) ) * textHeight ) - titleHeight );
+  double val = spc != 0 ? 1.0 * ( lab - qMin( lab, 2 ) ) * textHeight / spc : 0;
+  double iPart;
+  double fPart = modf( val, &iPart );
+  int filter = (int)iPart + ( fPart != 0 ? 1 : 0 );
+  filter = qMax( filter, 1 );
+  
+  double step = 1.0 * ( H - ( lab - num + qAbs( lab - num - 1 ) ) * textHeight - titleHeight ) / num;
+  
+  int ascent = p->fontMetrics().ascent();
+  int colorWidth = qMax( 5, qMin( 20, W - textWidth - 3 * spacer ) );
+  if ( labPos == Center || !drawLabel )
+    colorWidth = W - 2 * spacer;
+  
+  // Draw colors
+  int x = X + spacer;
+  switch ( labPos )
+  {
+  case Left:
+    x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
+    break;
+  }
+
+  double offset = 1.0 * textHeight / 2 * ( lab - num + qAbs( lab - num - 1 ) ) + titleHeight;
+  QList<QColor>::Iterator cit = colors.begin();
   uint ci = 0;
-       for ( ci = 0; cit != colors.end() && drawColors; ++cit, ci++ )
-       {
-               int y = (int)( Y + ci * step + offset );
-               int h = (int)( Y + ( ci + 1 ) * step + offset ) - y;
-               p->fillRect( x, y, colorWidth, h, *cit );
-       }
-
-       if ( drawColors )
-               p->drawRect( int( x - 1 ), int( Y + offset - 1 ), int( colorWidth + 2 ), int( ci * step + 2 ) );
-
-       // Draw labels
-       offset = 1.0 * qAbs( lab - num - 1 ) * ( step - textHeight ) / 2 +
-                                                1.0 * qAbs( lab - num - 1 ) * textHeight / 2;
-       offset += titleHeight;
-       if ( drawLabel && !labels.isEmpty() )
-       {
-               int i1 = 0;
-               int i2 = lab - 1;
-               int last1( i1 ), last2( i2 );
-               int x = X + spacer;
-               switch ( labPos )
-               {
-               case Center:
-                       x += ( colorWidth - textWidth ) / 2;
-                       break;
-               case Right:
-                       x += colorWidth + spacer;
-                       break;
-               }
-               while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) )
-               {
-                       int pos1 = i1;
-                       int pos2 = lab - 1 - i2;
-                       if ( filter && !( pos1 % filter ) )
-                       {
-                               p->drawText( x, (int)( Y + i1 * step + ascent + offset ), labels[i1] );
-                               last1 = i1;
-                       }
-                       if ( filter && !( pos2 % filter ) )
-                       {
-                               p->drawText( x, (int)( Y + i2 * step + ascent + offset ), labels[i2] );
-                               last2 = i2;
-                       }
-                       i1++;
-                       i2--;
-               }
-               int pos = i1;
-               int i0 = -1;
-               while ( pos <= i2 && i0 == -1 )
-               {
-                       if ( filter && !( pos % filter ) &&
-                                qAbs( pos - last1 ) >= filter && qAbs( pos - last2 ) >= filter )
-                               i0 = pos;
-                       pos++;
-               }
-
-               if ( i0 != -1 )
-                       p->drawText( x, (int)( Y + i0 * step + ascent + offset ), labels[i0] );
-       }
-}
-
-/*!
-  \return the format for number labels.
+  for ( ci = 0; cit != colors.end() && drawColors; ++cit, ci++ )
+  {
+    int y = (int)( Y + ci * step + offset );
+    int h = (int)( Y + ( ci + 1 ) * step + offset ) - y;
+    p->fillRect( x, y, colorWidth, h, *cit );
+  }
+  
+  if ( drawColors )
+    p->drawRect( int( x - 1 ), int( Y + offset - 1 ), int( colorWidth + 2 ), int( ci * step + 2 ) );
+  
+  // Draw labels
+  offset = 1.0 * qAbs( lab - num - 1 ) * ( step - textHeight ) / 2 +
+    1.0 * qAbs( lab - num - 1 ) * textHeight / 2;
+  offset += titleHeight;
+  if ( drawLabel && !labels.isEmpty() )
+  {
+    int i1 = 0;
+    int i2 = lab - 1;
+    int last1( i1 ), last2( i2 );
+    int x = X + spacer;
+    switch ( labPos )
+    {
+    case Center:
+      x += ( colorWidth - textWidth ) / 2;
+      break;
+    case Right:
+      x += colorWidth + spacer;
+      break;
+    }
+    while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) )
+    {
+      int pos1 = i1;
+      int pos2 = lab - 1 - i2;
+      if ( filter && !( pos1 % filter ) )
+      {
+       p->drawText( x, (int)( Y + i1 * step + ascent + offset ), labels[i1] );
+       last1 = i1;
+      }
+      if ( filter && !( pos2 % filter ) )
+      {
+       p->drawText( x, (int)( Y + i2 * step + ascent + offset ), labels[i2] );
+       last2 = i2;
+      }
+      i1++;
+      i2--;
+    }
+    int pos = i1;
+    int i0 = -1;
+    while ( pos <= i2 && i0 == -1 )
+    {
+      if ( filter && !( pos % filter ) &&
+          qAbs( pos - last1 ) >= filter && qAbs( pos - last2 ) >= filter )
+       i0 = pos;
+      pos++;
+    }
+
+    if ( i0 != -1 )
+      p->drawText( x, (int)( Y + i0 * step + ascent + offset ), labels[i0] );
+  }
+}
+
+/*!
+  \brief Generate number presentation format.
+  \return format for number labels
 */
 QString QtxColorScale::getFormat() const
 {
-       QString aFormat = format();
-
-       if ( !testFlags( PreciseFormat ) || testFlags( Integer ) )
-               return aFormat;
-
-       if ( !myPrecise.isEmpty() )
-               return myPrecise;
-
-       if ( !aFormat.contains( QRegExp( "^(%[0-9]*.?[0-9]*[fegFEG])$" ) ) )
-               return aFormat;
-
-       int pos1 = aFormat.indexOf( '.' );
-       int pos2 = aFormat.indexOf( QRegExp( "[fegFEG]") );
-
-       QString aLocFormat;
-       int precision = 1;
-       if ( pos1 > 0 )
-       {
-               aLocFormat = aFormat.mid( 0, pos1 + 1 );
-               precision = aFormat.mid( pos1 + 1, pos2 - pos1 - 1 ).toInt();
-               if ( precision < 1 )
-                       precision = 1;
-       }
-       else
-               return aFormat;
+  QString aFormat = format();
   
-       QtxColorScale* that = (QtxColorScale*)this;
-
-       // calculate format, maximum precision limited
-       // to 7 digits after the decimal point.
-       while ( myPrecise.isEmpty() && precision < 7 )
-       {
-               QString aTmpFormat = aLocFormat;
-               aTmpFormat += QString( "%1" ).arg( precision );
-               aTmpFormat += aFormat.mid( pos2 );
-
-               QMap<QString, int> map;
-               bool isHasTwinz = false;
-
-               for ( int idx = 0; idx < intervalsNumber() && !isHasTwinz; idx++ )
-               {
-                       double val = getNumber( idx );
-                       QString tmpname = QString().sprintf( aTmpFormat.toLatin1(), val );
-                       isHasTwinz = map.contains( tmpname );
-                       map.insert( tmpname, 1 );
-               }
-
-               if ( !isHasTwinz )
-                       that->myPrecise = aTmpFormat;
-               precision++;
-       }
-
-       if ( !myPrecise.isEmpty() )
-               aFormat = myPrecise;
-
-       return aFormat;
+  if ( !testFlags( PreciseFormat ) || testFlags( Integer ) )
+    return aFormat;
+  
+  if ( !myPrecise.isEmpty() )
+    return myPrecise;
+  
+  if ( !aFormat.contains( QRegExp( "^(%[0-9]*.?[0-9]*[fegFEG])$" ) ) )
+    return aFormat;
+  
+  int pos1 = aFormat.indexOf( '.' );
+  int pos2 = aFormat.indexOf( QRegExp( "[fegFEG]") );
+  
+  QString aLocFormat;
+  int precision = 1;
+  if ( pos1 > 0 )
+  {
+    aLocFormat = aFormat.mid( 0, pos1 + 1 );
+    precision = aFormat.mid( pos1 + 1, pos2 - pos1 - 1 ).toInt();
+    if ( precision < 1 )
+      precision = 1;
+  }
+  else
+    return aFormat;
+  
+  QtxColorScale* that = (QtxColorScale*)this;
+  
+  // calculate format, maximum precision limited
+  // to 7 digits after the decimal point.
+  while ( myPrecise.isEmpty() && precision < 7 )
+  {
+    QString aTmpFormat = aLocFormat;
+    aTmpFormat += QString( "%1" ).arg( precision );
+    aTmpFormat += aFormat.mid( pos2 );
+    
+    QMap<QString, int> map;
+    bool isHasTwinz = false;
+    
+    for ( int idx = 0; idx < intervalsNumber() && !isHasTwinz; idx++ )
+    {
+      double val = getNumber( idx );
+      QString tmpname = QString().sprintf( aTmpFormat.toLatin1(), val );
+      isHasTwinz = map.contains( tmpname );
+      map.insert( tmpname, 1 );
+    }
+    
+    if ( !isHasTwinz )
+      that->myPrecise = aTmpFormat;
+    precision++;
+  }
+  
+  if ( !myPrecise.isEmpty() )
+    aFormat = myPrecise;
+  
+  return aFormat;
 }
 
 /*!
-  \return the number for specified interval.
+  \brief Get color scale value corresponding to the specified interval.
+  \param idx interval index
+  \return color scale value
 */
 double QtxColorScale::getNumber( const int idx ) const
 {
-       double val = 0;
-       if ( intervalsNumber() > 0 )
-               val = minimum() + idx * ( qAbs( maximum() - minimum() ) / intervalsNumber() );
-       return val;
+  double val = 0;
+  if ( intervalsNumber() > 0 )
+    val = minimum() + idx * ( qAbs( maximum() - minimum() ) / intervalsNumber() );
+  return val;
 }
 
 /*!
-  \return the label for specified interval according to the current label mode.
+  \brief Get color scale label text corresponding to the specified interval.
+  \param idx interval index
+  \return color scale label text
 */
 QString QtxColorScale::getLabel( const int idx ) const
 {
-       QString res;
-       if ( labelMode() == User )
-               res = label( idx );
-       else
-       {
-               double val = getNumber( idx );
-               res = QString().sprintf( getFormat().toLatin1(), testFlags( Integer ) ? (int)val : val );
-       }
-       return res;
+  QString res;
+  if ( labelMode() == User )
+    res = label( idx );
+  else
+  {
+    double val = getNumber( idx );
+    res = QString().sprintf( getFormat().toLatin1(), testFlags( Integer ) ? (int)val : val );
+  }
+  return res;
 }
 
 /*!
-  \return the color for specified interval according to the current color mode.
+  \brief Get color scale color corresponding to the specified interval.
+  \param idx interval index
+  \return color scale color
 */
 QColor QtxColorScale::getColor( const int idx ) const
 {
-       QColor res;
-       if ( colorMode() == User )
-               res = color( idx );
-       else
+  QColor res;
+  if ( colorMode() == User )
+    res = color( idx );
+  else
     res = Qtx::scaleColor( idx, 0, intervalsNumber() - 1 );
-       return res;
+  return res;
 }
 
 /*!
-  Update color scale if it required.
+  \brief Update color scale.
 */
 void QtxColorScale::updateScale()
 {
   update();
-       updateGeometry();
+  updateGeometry();
 }
 
 /*!
-  \return QSimpleRichText object for title. If title
-  not defined (empty string) then return null pointer.
-  Object should be deleted by caller function.
+  \brief Get text document (rich text) for the color scale title representation.
+
+  If title is not defined (empty string) then null pointer is returned.
+  The calling function is responsible for the returning object deleting.
+
+  \param flags color scale flags (not used)
+  \return text document or 0 if title is not set
 */
-QTextDocument* QtxColorScale::textDocument( const int flags ) const
+QTextDocument* QtxColorScale::textDocument( const int /*flags*/ ) const
 {
-       QTextDocument* doc = 0;
-
-       QString aTitle;
-       switch ( titlePosition() )
-       {
-       case Left:
-               aTitle = QString( "<p align=\"left\">%1</p>" );
-               break;
-       case Right:
-               aTitle = QString( "<p align=\"right\">%1</p>" );
-               break;
-       case Center:
-               aTitle = QString( "<p align=\"center\">%1</p>" );
-               break;
-       case None:
-       default:
-               break;
-       }
+  QTextDocument* doc = 0;
 
-       if ( !aTitle.isEmpty() && !title().isEmpty() )
-       {
+  QString aTitle;
+  switch ( titlePosition() )
+  {
+  case Left:
+    aTitle = QString( "<p align=\"left\">%1</p>" );
+    break;
+  case Right:
+    aTitle = QString( "<p align=\"right\">%1</p>" );
+    break;
+  case Center:
+    aTitle = QString( "<p align=\"center\">%1</p>" );
+    break;
+  case None:
+  default:
+    break;
+  }
+  
+  if ( !aTitle.isEmpty() && !title().isEmpty() )
+  {
     /*
-               if ( !myStyleSheet )
-               {
-                       QtxColorScale* that = (QtxColorScale*)this;
-                       that->myStyleSheet = new QStyleSheet( that );
-               }
-
-               if ( myStyleSheet )
-               {
-                       QStyleSheetItem* item = myStyleSheet->item( "p" );
-                       if ( item )
-                               item->setWhiteSpaceMode( flags & WrapTitle ? QStyleSheetItem::WhiteSpaceNormal :
-                                                                                                                    QStyleSheetItem::WhiteSpaceNoWrap );
-               }
-*/
-               aTitle = aTitle.arg( title() );
-               doc = new QTextDocument( aTitle );
-       }
-
-       return doc;
+    if ( !myStyleSheet )
+    {
+      QtxColorScale* that = (QtxColorScale*)this;
+      that->myStyleSheet = new QStyleSheet( that );
+    }
+      
+    if ( myStyleSheet )
+    {
+      QStyleSheetItem* item = myStyleSheet->item( "p" );
+      if ( item )
+      item->setWhiteSpaceMode( flags & WrapTitle ? QStyleSheetItem::WhiteSpaceNormal :
+      QStyleSheetItem::WhiteSpaceNoWrap );
+    }
+    */
+    aTitle = aTitle.arg( title() );
+    doc = new QTextDocument( aTitle );
+  }
+
+  return doc;
 }
index 364ac1e2e65f0d156bd94a4d1f7b939ec888d081..ae9e985f2a1f2e29958c31c8d8692ec4b2d120fe 100755 (executable)
@@ -24,8 +24,8 @@
 
 #include "Qtx.h"
 
-#include <QtGui/qframe.h>
-#include <QtCore/qlist.h>
+#include <QFrame>
+#include <QList>
 
 class QTextDocument;
 
@@ -33,20 +33,39 @@ class QTextDocument;
 #pragma warning( disable:4251 )
 #endif
 
-/*!
-  \class QtxColorScale
-  Color Scale widget.
-*/
 class QTX_EXPORT QtxColorScale : public QFrame
 {
   Q_OBJECT
 
 public:
-       typedef enum { Auto, User } Mode;
-       typedef enum { None, Left, Right, Center } Position;
-       typedef enum { NoDump, TitleDump, ScaleDump, FullDump } DumpMode;
-       typedef enum { AtBorder = 0x001, Reverse = 0x002, Integer = 0x004,
-                                        WrapTitle = 0x008, PreciseFormat = 0x010, Transparent = 0x020 } Flags;
+  //! Color scale color/label mode.
+  typedef enum { 
+    Auto,            //!< auto
+    User             //!< user defined
+  } Mode;
+  //! Color scale title, label position.
+  typedef enum { 
+    None,            //!< do not draw
+    Left,            //!< draw at the left
+    Right,           //!< draw at the right
+    Center           //!< draw at the center
+  } Position;
+  //! Dump mode.
+  typedef enum { 
+    NoDump,          //!< do not dump
+    TitleDump,       //!< dump title
+    ScaleDump,       //!< dump scale
+    FullDump         //!< dump all
+  } DumpMode;
+  //! Color scale flags (bitwise).
+  typedef enum { 
+    AtBorder      = 0x001, 
+    Reverse       = 0x002, 
+    Integer       = 0x004,
+    WrapTitle     = 0x008, 
+    PreciseFormat = 0x010, 
+    Transparent   = 0x020
+  } Flags;
 
 public:
   QtxColorScale( QWidget* = 0, Qt::WindowFlags = 0 );
@@ -114,34 +133,34 @@ private:
   double                getNumber( const int ) const;
   QTextDocument*        textDocument( const int ) const;
   void                  drawScale( QPainter*, const bool, const int, const int,
-                                                                                  const int, const int, const bool, const bool, const bool ) const;
+                                  const int, const int, const bool, const bool, const bool ) const;
   void                  drawScale( QPainter*, const QColor&, const bool,
-                                                                                  const int, const int, const int, const int,
-                                                                                  const bool, const bool, const bool ) const;
+                                  const int, const int, const int, const int,
+                                  const bool, const bool, const bool ) const;
   QSize                 calculateSize( const bool, const int,
-                                                                                            const bool, const bool, const bool ) const;
+                                      const bool, const bool, const bool ) const;
 
 private:
-  double                myMin;
-  double                myMax;
-  QString               myTitle;
-  QString               myFormat;
-  QString               myPrecise;
-  int                   myInterval;
-  int                   myDumpMode;
-  int                   myColorMode;
-  int                   myLabelMode;
-
-  QList<QColor>         myColors;
-  QList<QString>        myLabels;
-
-  int                   myFlags;
-  int                   myLabelPos;
-  int                   myTitlePos;
+  double                myMin;             //!< lower limit
+  double                myMax;             //!< upper limit
+  QString               myTitle;           //!< title
+  QString               myFormat;          //!< number presentation format
+  QString               myPrecise;         //!< double values precision format
+  int                   myInterval;        //!< number of color scale intervals
+  int                   myDumpMode;        //!< dump mode (QtxColorScale::DumpMode)
+  int                   myColorMode;       //!< color mode (QtxColorScale::Mode)
+  int                   myLabelMode;       //!< label mode (QtxColorScale::Mode)
+
+  QList<QColor>         myColors;          //!< list of colors
+  QList<QString>        myLabels;          //!< list of labels
+
+  int                   myFlags;           //!< color scale flags (QtxColorScale::Flags)
+  int                   myLabelPos;        //!< label position (QtxColorScale::Position)
+  int                   myTitlePos;        //!< title position (QtxColorScale::Position)
 };
 
 #ifdef WIN32
 #pragma warning( default:4251 )
 #endif
 
-#endif
+#endif  // QTXCOLORSCALE_H
index b7ba7292ac7db15fdd9c55bb9fd196e2f1700e04..eaffefbdf00dfb2f0a07feb8f85b91813e881ded 100755 (executable)
 
 #include "QtxComboBox.h"
 
-#include <QtCore/qlist.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qlineedit.h>
+#include <QLineEdit>
 
 /*!
-  Constructor
+  \class QtxComboBox
+  \brief Enhanced version of Qt combo box class.
+
+  In addition to the QComboBox class, QtxComboBox supports 
+  adding/removing the items with the associated unique identifiers.
+  It also provides a way to set "cleared" state to the combo box -
+  when no item is selected.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
 */
 QtxComboBox::QtxComboBox( QWidget* parent )
 : QComboBox( parent ),
-myCleared( false )
+  myCleared( false )
 {
-    connect( this, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
-    connect( this, SIGNAL( activated( const QString& ) ), this, SLOT( onActivated( const QString& ) ) );
+  connect( this, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
+  connect( this, SIGNAL( activated( const QString& ) ), this, SLOT( onActivated( const QString& ) ) );
 }
 
 /*!
-  Destructor
+  \brief Destructor.
+
+  Does nothing currently.
 */
 QtxComboBox::~QtxComboBox()
 {
 }
 
 /*!
-  \return true if combobox is cleared
+  \brief Check if the combo box is in the "cleared" state.
+  \return \c true if combobox is in the "cleared" state
 */
 bool QtxComboBox::isCleared() const
 {
@@ -52,8 +64,8 @@ bool QtxComboBox::isCleared() const
 }
 
 /*!
-  Sets cleared status
-  \param isClear - new status
+  \brief Set "cleared" state.
+  \param isClear new "cleared" state
 */
 void QtxComboBox::setCleared( const bool isClear )
 {
@@ -74,8 +86,11 @@ void QtxComboBox::setCleared( const bool isClear )
 }
 
 /*!
-  Sets currently selected item
-  \param idx - index of item
+  \brief Set current item.
+
+  Does nothing if the item index is out of range.
+
+  \param idx item index
 */
 void QtxComboBox::setCurrentIndex( int idx )
 {
@@ -87,7 +102,8 @@ void QtxComboBox::setCurrentIndex( int idx )
 }
 
 /*!
-  \return current selected id
+  \brief Get current item ID.
+  \return item id
 */
 int QtxComboBox::currentId() const
 {
@@ -95,7 +111,8 @@ int QtxComboBox::currentId() const
 }
 
 /*!
-  Sets current selected id
+  \brief Set current item by ID.
+  \param num item ID
 */
 void QtxComboBox::setCurrentId( int num )
 {
@@ -103,7 +120,18 @@ void QtxComboBox::setCurrentId( int num )
 }
 
 /*!
-  Custom paint event handler
+  \brief Set the identifier to specified item.
+  \param index - index of the item
+  \param id - identifier of the item
+*/
+void QtxComboBox::setId( const int index, const int id )
+{
+  setItemData( index, QVariant( id ), (Qt::ItemDataRole)IdRole );
+}
+
+/*!
+  \brief Customize paint event.
+  \param e paint event
 */
 void QtxComboBox::paintEvent( QPaintEvent* e )
 {
@@ -114,35 +142,40 @@ void QtxComboBox::paintEvent( QPaintEvent* e )
 }
 
 /*!
-  SLOT: called if some item is activated
-  \param idx - index of activated item
+  \brief Called when any item is activated by the user.
+  \param idx activated item index
 */
 void QtxComboBox::onActivated( int idx )
 {
   resetClear();
+
+  emit activatedId( id( idx ) );
 }
 
 /*!
-  SLOT: called if some item is activated
-*/void QtxComboBox::onActivated( const QString& )
+  \brief Called when any item is activated by the user.
+  \param txt activated item text (not used)
+*/
+void QtxComboBox::onActivated( const QString& /*txt*/ )
 {
-    resetClear();
+  resetClear();
 }
 
 /*!
-  Strips "cleared" state and updates
+  \brief Reset "cleared" state and update the combo box.
 */
 void QtxComboBox::resetClear()
 {
-    if ( !myCleared )
-        return;
-    
-    myCleared = false;
-    update();
+  if ( !myCleared )
+    return;
+  
+  myCleared = false;
+  update();
 }
 
 /*!
-  Draws combobox when it is cleared or isn't editable
+  \brief Draw combobox in the "cleared" state.
+  \param e paint event
 */
 void QtxComboBox::paintClear( QPaintEvent* e )
 {
@@ -165,26 +198,53 @@ void QtxComboBox::paintClear( QPaintEvent* e )
 }
 
 /*!
-  \return id by index
+  \brief Get item ID by the index.
+  \param idx item index
+  \return item ID or -1 if index is invalid.
 */
 int QtxComboBox::id( const int idx ) const
 {
   int id = -1;
-  if ( myIndexId.contains( idx ) )
-    id = myIndexId[idx];
+  QVariant v = itemData( idx, (Qt::ItemDataRole)IdRole );
+  if ( v.canConvert( QVariant::Int ) )
+    id = v.toInt();
   return id;
 }
 
 /*!
-  \return index by id
+  \brief Get item index by the ID.
+  \param id item ID
+  \return item index or -1 if ID is invalid.
 */
-int QtxComboBox::index( const int id ) const
+int QtxComboBox::index( const int ident ) const
 {
   int idx = -1;
-  for ( IndexIdMap::ConstIterator it = myIndexId.begin(); it != myIndexId.end() && idx == -1; ++it )
+  for ( int i = 0; i < (int)count() && idx == -1; i++ )
   {
-    if ( it.value() == id )
-      idx = it.key();
+    if ( id( i ) == ident )
+      idx = i;
   }
   return idx;
 }
+
+/*!
+  \brief Returns true if the item with index has ID.
+  \param idx item index
+*/
+bool QtxComboBox::hasId( const int idx ) const
+{
+  QVariant v = itemData( idx, (Qt::ItemDataRole)IdRole );
+  return v.canConvert( QVariant::Int );
+}
+
+/*!
+  \fn void QtxComboBox::activatedId( int id )
+  \brief Emitted when the item with identificator \a id is activated.
+  \param id item ID
+*/
+
+/*!
+  \fn void QtxComboBox::highlightedId( int id )
+  \brief Emitted when the item with identificator \a id is highlighted.
+  \param id item ID
+*/
index 79f40d924c492143ceefbff88cea85121fa1ee98..c821ffaed538bea3d041ace02a3d7303376391dc 100755 (executable)
@@ -24,8 +24,8 @@
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtGui/qcombobox.h>
+#include <QMap>
+#include <QComboBox>
 
 #ifdef WIN32
 #pragma warning( disable:4251 )
@@ -35,8 +35,6 @@ class QTX_EXPORT QtxComboBox : public QComboBox
 {
   Q_OBJECT
 
-  typedef QMap<int, int> IndexIdMap;
-
 public:
   QtxComboBox( QWidget* = 0 );
   virtual ~QtxComboBox();
@@ -49,11 +47,17 @@ public:
   int          currentId() const;
   void         setCurrentId( int );
 
-Q_SIGNALS:
+  int          id( const int ) const;
+  int          index( const int ) const;
+
+  bool         hasId( const int ) const;
+  void         setId( const int, const int );
+
+signals:
   void         activatedId( int );
   void         highlightedId( int );
 
-private Q_SLOTS:
+private slots:
   void         onActivated( int );
   void         onActivated( const QString& );
 
@@ -61,15 +65,14 @@ protected:
   virtual void paintEvent( QPaintEvent* );
 
 private:
-  int          id( const int ) const;
-  int          index( const int ) const;
-
   void         resetClear();
   void         paintClear( QPaintEvent* );
 
 private:
-  bool         myCleared;
-  IndexIdMap   myIndexId;
+  enum { IdRole = Qt::UserRole + 10 };
+
+private:
+  bool         myCleared;     //!< "cleared" state
 };
 
 #ifdef WIN32
index d11e8127e37d4c071681f99aac03e6b4978a1335..64e43c854e3ae461567a3b5919973d16bc453481 100755 (executable)
 
 #include "QtxDialog.h"
 
-#include <QtGui/qevent.h>
-#include <QtGui/qlabel.h>
-#include <QtGui/qframe.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qtabwidget.h>
-#include <QtGui/qpushbutton.h>
-#include <QtGui/qapplication.h>
+#include <QLabel>
+#include <QLayout>
+#include <QKeyEvent>
+#include <QFrame>
+#include <QTabWidget>
+#include <QPushButton>
+#include <QApplication>
 
 /*!
-       Class: QtxDialog::Area
-       Level: Internal
+  \class QtxDialog::Area
+  \internal
+  \brief Area containing dialog box buttons.
 */
+
 class QtxDialog::Area : public QFrame
 {
 public:
@@ -59,24 +61,27 @@ private:
   void                     updateBorder();
 
 private:
-  QtxDialog*               myDlg;
-  QLabel*                  myLine;
-  bool                     myBorder;
-  int                      myPolicy;
-  QList<QAbstractButton*>  myButtons;
-  Qt::Orientation          myOrientation;
+  QtxDialog*               myDlg;          //!< parent dialog box
+  QLabel*                  myLine;         //!< border widget 
+  bool                     myBorder;       //!< "has border" flag
+  int                      myPolicy;       //!< button layout type (QtxDialog::PlacePolicy)
+  QList<QAbstractButton*>  myButtons;      //!< buttons list
+  Qt::Orientation          myOrientation;  //!< buttons orientation (Qt::Orientation)
 };
 
 /*!
-  Contructor
+  \brief Constructor.
+  \param o buttons orientation
+  \param dlg dialog box owning this area
+  \param parent parent widget
 */
 QtxDialog::Area::Area( Qt::Orientation o, QtxDialog* dlg, QWidget* parent )
 : QFrame( parent ),
-myDlg( dlg ),
-myLine( 0 ),
-myBorder( false ),
-myPolicy( Position ),
-myOrientation( o )
+  myDlg( dlg ),
+  myLine( 0 ),
+  myBorder( false ),
+  myPolicy( Position ),
+  myOrientation( o )
 {
   if ( myOrientation == Qt::Horizontal )
     setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum ) );
@@ -87,15 +92,16 @@ myOrientation( o )
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxDialog::Area::~Area()
 {
 }
 
 /*!
-  Inserts button to area
-  \param b - button
+  \brief Insert button to the area.
+  \param b button to be added
+  \sa removeButton()
 */
 void QtxDialog::Area::insertButton( QAbstractButton* b )
 {
@@ -118,8 +124,9 @@ void QtxDialog::Area::insertButton( QAbstractButton* b )
 }
 
 /*!
-  Removes button from area
-  \param b - button
+  \brief Remove button from the area.
+  \param b button to be removed
+  \sa insertButton()
 */
 void QtxDialog::Area::removeButton( QAbstractButton* b )
 {
@@ -140,8 +147,9 @@ void QtxDialog::Area::removeButton( QAbstractButton* b )
 }
 
 /*!
-  \return true if area contains button
-  \param b - button
+  \brief Check if area owns the button specified.
+  \param b button to be checked
+  \return \c true if area contains button
 */
 bool QtxDialog::Area::contains( QAbstractButton* b ) const
 {
@@ -149,7 +157,9 @@ bool QtxDialog::Area::contains( QAbstractButton* b ) const
 }
 
 /*!
-  \return policy of button layouting.
+  \brief Get buttons layout policy.
+  \return policy of button layouting (Qtx::PlacePolicy)
+  \sa setPolicy()
 */
 int QtxDialog::Area::policy() const
 {
@@ -157,8 +167,8 @@ int QtxDialog::Area::policy() const
 }
 
 /*!
-  Changes policy of button layouting.
-  \param p new policy
+  \brief Set buttons layout policy.
+  \param p new policy
 */
 void QtxDialog::Area::setPolicy( const int p )
 {
@@ -170,7 +180,9 @@ void QtxDialog::Area::setPolicy( const int p )
 }
 
 /*!
-  \return true if border enabled
+  \brief Check of the border is enabled.
+  \return \c true if border is enabled
+  \sa setBorderEnabled(), setBorderWidget()
 */
 bool QtxDialog::Area::isBorderEnabled() const
 {
@@ -178,8 +190,8 @@ bool QtxDialog::Area::isBorderEnabled() const
 }
 
 /*!
-  Enables/disable separator between main frame and button frame
-  \param on new state
+  \brief Enable/disable border (separator between main frame and button frame)
+  \param on new state
 */
 void QtxDialog::Area::setBorderEnabled( const bool on )
 {
@@ -191,8 +203,8 @@ void QtxDialog::Area::setBorderEnabled( const bool on )
 }
 
 /*!
-  Sets label as separator between main frame and button frame
-  \param line - new separator
+  \brief Set border widget (separator between main frame and button frame).
+  \param line new separator widget
 */
 void QtxDialog::Area::setBorderWidget( QLabel* line )
 {
@@ -205,7 +217,8 @@ void QtxDialog::Area::setBorderWidget( QLabel* line )
 }
 
 /*!
-  \return const reference to list of buttons
+  \brief Get all area buttons.
+  \return const reference to the list of buttons
 */
 const QList<QAbstractButton*>& QtxDialog::Area::buttons() const
 {
@@ -213,7 +226,7 @@ const QList<QAbstractButton*>& QtxDialog::Area::buttons() const
 }
 
 /*!
-  Updates visibility of border
+  \brief Update border visibility.
 */
 void QtxDialog::Area::updateBorder()
 {
@@ -227,7 +240,7 @@ void QtxDialog::Area::updateBorder()
 }
 
 /*!
-  Installs buttons into layout
+  \brief Layout buttons in the area.
 */
 void QtxDialog::Area::layoutButtons()
 {
@@ -329,9 +342,11 @@ void QtxDialog::Area::layoutButtons()
 
 /*!
   \class QtxDialog::Border
-
-  Special label used as separator between main frame and button frame
+  \internal
+  \brief Special label used as border widget (separator
+         between main frame and button frame).
 */
+
 class QtxDialog::Border : public QLabel
 {
 public:
@@ -345,7 +360,8 @@ public:
 };
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param parent parent widget
 */
 QtxDialog::Border::Border( QWidget* parent )
 : QLabel( parent )
@@ -354,15 +370,15 @@ QtxDialog::Border::Border( QWidget* parent )
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxDialog::Border::~Border()
 {
 }
 
 /*!
-  Set line width of separator
-  \param lw new line width
+  \brief Set separator line width.
+  \param lw new line width
 */
 void QtxDialog::Border::setLineWidth( int lw )
 {
@@ -375,7 +391,8 @@ void QtxDialog::Border::setLineWidth( int lw )
 }
 
 /*!
-  \return the recommended size for the widget
+  \brief Get recommended size for the widget.
+  \return recommended size for the widget
 */
 QSize QtxDialog::Border::sizeHint() const
 {
@@ -393,7 +410,8 @@ QSize QtxDialog::Border::sizeHint() const
 }
 
 /*!
-  \return the recommended minimum size for the widget
+  \brief Get recommended minimum size for the widget.
+  \return recommended minimum size for the widget
 */
 QSize QtxDialog::Border::minimumSizeHint() const
 {
@@ -401,12 +419,22 @@ QSize QtxDialog::Border::minimumSizeHint() const
 }
 
 /*!
-  Constructor
+  \class QtxDialog
+  \brief Generic dialog box class.
+*/
+
+/*!
+  \brief Constructor.
+
   Construct a dialog with specified parent and name.
-  \param modal define modal status of dialog (default non modal dialog created).
-  \param allowResize - if it is true then dialog can be resize by user (default non resizable dialog created).
-  \param Button flags specified control buttons for dialog (default buttons is OK, Cancel and Help).
-  \param Widget flags used as in any widget.
+  By default non-modal, non-resizable with the OK, Cancel and Help buttons
+  dialog box is created.
+
+  \param parent parent widget
+  \param modal if \c true dialog box is modal
+  \param allowResize if \c true then dialog can be resized by user
+  \param f specified control buttons for dialog box (QtxDialog::ButtonFlags)
+  \param wf dialog box flags (Qt::WindowFlags)
 */
 QtxDialog::QtxDialog( QWidget* parent, bool modal, bool allowResize, const int f, Qt::WindowFlags wf )
 : QDialog( parent, (Qt::WindowFlags)( wf | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::Dialog |
@@ -419,10 +447,10 @@ QtxDialog::QtxDialog( QWidget* parent, bool modal, bool allowResize, const int f
               && !( wf & Qt::WindowContextHelpButtonHint )
 #endif
               ) ? Qt::WindowMaximizeButtonHint : 0 ) ) ),
-myInited( false ),
-mySender( 0 ),
-myAlignment( 0 ),
-myDialogFlags( Accept | SetFocus )
+  myInited( false ),
+  mySender( 0 ),
+  myAlignment( 0 ),
+  myDialogFlags( Accept | SetFocus )
 {
   setModal( modal );
 
@@ -534,19 +562,17 @@ myDialogFlags( Accept | SetFocus )
 }
 
 /*!
-       Name: ~QtxDialog [public]
-       Desc: Destructor
+  \brief Destructor.
 */
-
 QtxDialog::~QtxDialog()
 {
 }
 
 /*!
-       Name: setButtonFlags [public]
-       Desc: Allow to set specified control button(s) into dialog.
+  \brief Add specified control button(s) to the dialog box.
+  \param f ORed buttons flags (Qtx::ButtonFlags)
+  \sa clearButtonFlags(), testButtonFlags()
 */
-
 void QtxDialog::setButtonFlags( const int f )
 {
   int old = myButtonFlags;
@@ -556,10 +582,10 @@ void QtxDialog::setButtonFlags( const int f )
 }
 
 /*!
-       Name: clearButtonFlags [public]
-       Desc: Allow to unset specified control button(s) from dialog.
+  \brief Remove specified control button(s) from the dialog box.
+  \param f ORed buttons flags (Qtx::ButtonFlags)
+  \sa setButtonFlags(), testButtonFlags()
 */
-
 void QtxDialog::clearButtonFlags( const int f )
 {
   int old = myButtonFlags;
@@ -569,68 +595,64 @@ void QtxDialog::clearButtonFlags( const int f )
 }
 
 /*!
-       Name: testButtonFlags [public]
-       Desc: Return true if specified control button is used in dialog.
+  \brief Test specified buttons.
+  \return \c true if specified control buttons are used in the dialog box
+  \sa setButtonFlags(), clearButtonFlags()
 */
-
 bool QtxDialog::testButtonFlags( const int f ) const
 {
   return ( myButtonFlags & f ) == f;
 }
 
 /*!
-       Name: setDialogFlags [public]
-       Desc: Allow to set the dialog flags.
-
-                 Following flags can be used:
-                       Accept    - Allow to control dialog accepting. See also acceptData().
-                       Reject    - Allow to control dialog rejecting. See also rejectData().
-                       AlignOnce - Allow to align dialog only when it first time shown.
-                       SetFocus  - Allow to set focus on dialog when it shown. User can use
-                  setFocusProxy() and specify own initial focus widget.
+  \brief Set specified dialog box flags.
+  \param f dialog box flags (QtxDialog::DialogFlags)
+  \sa clearDialogFlags(), testDialogFlags(), acceptData(), rejectData()
 */
-
 void QtxDialog::setDialogFlags( const int f )
 {
   myDialogFlags = myDialogFlags | f;
 }
 
 /*!
-       Name: clearDialogFlags [public]
-       Desc: Allow to clear the dialog flags. See also setDialogFlags().
+  \brief Clear specified the dialog flags.
+  \param f dialog box flags (QtxDialog::DialogFlags)
+  \sa setDialogFlags(), testDialogFlags()
 */
-
 void QtxDialog::clearDialogFlags( const int f )
 {
   myDialogFlags = myDialogFlags & ~f;
 }
 
 /*!
-       Name: testDialogFlags [public]
-       Desc: Returns true if specified dialog flag is setted (see setDialogFlags()).
+  \brief Test specified dialog flags.
+  \return \c true if specified dialog box falgs are set
+  \sa setDialogFlags(), clearDialogFlags()
 */
-
 bool QtxDialog::testDialogFlags( const int f ) const
 {
   return ( myDialogFlags & f ) == f;
 }
 
 /*!
-       Name: mainFrame [public]
-       Desc: Returns main frame of dialog. Main frame should contains all
-          elements of dialog except control buttons.
-*/
+  \brief Get dialog box main frame widget.
 
+  Main frame is an internal widget which should contains all
+  elements of dialog box except control buttons.
+
+  \return main frame widget 
+*/
 QFrame* QtxDialog::mainFrame() const
 {
   return myMainFrame;
 }
 
 /*!
-       Name: buttonPosition [public]
-       Desc: Returns position of specified button.
+  \brief Get specified control button position
+  \param id control button ID (QtxDialog::ButtonFlags)
+  \return button's position (QtxDialog::ButtonPosition) or -1 if it is not set or invalid \a id is given
+  \sa setButtonPosition()
 */
-
 int QtxDialog::buttonPosition( const int id ) const
 {
   int pos = -1;
@@ -638,13 +660,11 @@ int QtxDialog::buttonPosition( const int id ) const
     pos = myPosition[id];
   return pos;
 }
-
 /*!
-       Name: setButtonPosition [public]
-       Desc: Sets the position for specified button(s). Following positions
-                 may be used: Left, Right, Center, Top, Bottom.
+  \brief Set the specified control button(s) position.
+  \param id control button(s) ID (QtxDialog::ButtonFlags)
+  \param pos button(s) position (QtxDialog::ButtonPosition)
 */
-
 void QtxDialog::setButtonPosition( const int pos, const int id )
 {
   ButtonMap map = buttons( id );
@@ -668,10 +688,11 @@ void QtxDialog::setButtonPosition( const int pos, const int id )
 }
 
 /*!
-       Name: setPlacePosition [public]
-       Desc: Sets button position for all buttons in given place.
+  \brief Set button position for all buttons in specified \a area.
+  \param pos button(s) position (QtxDialog::ButtonPosition)
+  \param area buttons area (QtxDialog::ButtonArea)
+  \sa setButtonPosition()
 */
-
 void QtxDialog::setPlacePosition( const int pos, const int area )
 {
   if ( !myArea.contains( area ) )
@@ -695,21 +716,10 @@ void QtxDialog::setPlacePosition( const int pos, const int area )
 }
 
 /*!
-       Name: placePolicy [public]
-       Desc: Returns policy of button layouting for specified place.
-
-                 Following place may be used:
-                       TopArea    - Horizontal area in the top side of dialog.
-                       BottomArea - Horizontal area in the bottom side of dialog.
-                       LeftArea   - Vertical area in the left side of dialog.
-                       RightArea  - Vertical area in the right side of dialog.
-
-                 Following policy may be used:
-                   Position - Buttons placed according their position.
-                       Expand   - Buttons fills all available space.
-                       Uniform  - Buttons uniformly placed in area.
+  \brief Get buttons layouting policy for the specified \a area.
+  \param area buttons area (QtxDialog::ButtonArea)
+  \sa setPlacePolicy()
 */
-
 int QtxDialog::placePolicy( const int area ) const
 {
   int res = -1;
@@ -719,11 +729,11 @@ int QtxDialog::placePolicy( const int area ) const
 }
 
 /*!
-       Name: setPlacePolicy [public]
-       Desc: Sets the policy of button layouting for specified place.
-                 See also placePolicy().
+  \brief set buttons layouting policy for the specified \a area.
+  \param policy buttons layouting policy (QtxDialog::PlacePolicy)
+  \param area buttons area (QtxDialog::ButtonArea)
+  \sa placePolicy()
 */
-
 void QtxDialog::setPlacePolicy( const int policy, const int area )
 {
   if ( area < 0 )
@@ -736,17 +746,17 @@ void QtxDialog::setPlacePolicy( const int policy, const int area )
 }
 
 /*!
-       Name: setButtonPlace [public]
-       Desc: Move given button(s) into specified place.
+  \brief Move specified button(s) into specified area.
+  \param area buttons area (QtxDialog::ButtonArea)
+  \param id control button(s) ID (QtxDialog::ButtonFlags)
 */
-
-void QtxDialog::setButtonPlace( const int area, const int ids )
+void QtxDialog::setButtonPlace( const int area, const int id )
 {
   if ( !myArea.contains( area ) )
     return;
 
   Area* anArea = myArea[area];
-  ButtonMap map = buttons( ids );
+  ButtonMap map = buttons( id );
   QMap<Area*, int> areaMap;
   for ( AreaMap::ConstIterator aIt = myArea.begin(); aIt != myArea.end(); ++aIt )
     areaMap.insert( aIt.value(), 0 );
@@ -764,10 +774,11 @@ void QtxDialog::setButtonPlace( const int area, const int ids )
 }
 
 /*!
-       Name: isBorderEnabled [public]
-       Desc: Returns true if border is shown for specified button area.
+  \brief Check if border is enabled.
+  \param area buttons area (QtxDialog::ButtonArea)
+  \return \c true if border is enabled for specified button area.
+  \sa setBorderEnabled()
 */
-
 bool QtxDialog::isBorderEnabled( const int area ) const
 {
   bool res = false;
@@ -777,11 +788,14 @@ bool QtxDialog::isBorderEnabled( const int area ) const
 }
 
 /*!
-       Name: setBorderEnabled [public]
-       Desc: Show/hide border for specified button area. Border are
-             line which separate main frame and control buttons.
-*/
+  \brief Show/hide border for the specified button area.
 
+  Border is a line which separate main frame and control buttons.
+
+  \param area buttons area (QtxDialog::ButtonArea)
+  \param on enable border flag
+  \sa isBorderEnabled()
+*/
 void QtxDialog::setBorderEnabled( const bool on, const int area )
 {
   if ( !myArea.contains( area ) )
@@ -800,13 +814,14 @@ void QtxDialog::setBorderEnabled( const bool on, const int area )
 }
 
 /*!
-       Name: isButtonEnabled [public]
-       Desc: Returns true if all specified button(s) is enabled.
+  \brief Get "enabled" status of the specified button(s).
+  \param id control button(s) ID (QtxDialog::ButtonFlags)
+  \return \c true if all specified buttons are enabled.
+  \sa setButtonEnabled()
 */
-
-bool QtxDialog::isButtonEnabled( const int f ) const
+bool QtxDialog::isButtonEnabled( const int id ) const
 {
-  ButtonMap map = buttons( f );
+  ButtonMap map = buttons( id );
   bool result = !map.isEmpty();
   for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
     result = result && it.value()->isEnabled();
@@ -814,22 +829,24 @@ bool QtxDialog::isButtonEnabled( const int f ) const
 }
 
 /*!
-       Name: setButtonEnabled [public]
-       Desc: Enable/disable specified button(s).
+  \brief Enable/disable specified button(s).
+  \param on enable button(s) flag
+  \param id control button(s) ID (QtxDialog::ButtonFlags)
+  \sa isButtonEnabled()
 */
-
-void QtxDialog::setButtonEnabled( const bool on, const int ids )
+void QtxDialog::setButtonEnabled( const bool on, const int id )
 {
-  ButtonMap map = buttons( ids );
+  ButtonMap map = buttons( id );
   for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
     it.value()->setEnabled( on );
 }
 
 /*!
-       Name: hasButtonFocus [public]
-       Desc: Retruns true if specified button has keyboard focus.
+  \brief Check if specified button has keyboard focus.
+  \param id control button ID (QtxDialog::ButtonFlags)
+  \return \c true if specified button has keyboard focus
+  \sa setButtonFocus()
 */
-
 bool QtxDialog::hasButtonFocus( const int id ) const
 {
   bool res = false;
@@ -840,10 +857,10 @@ bool QtxDialog::hasButtonFocus( const int id ) const
 }
 
 /*!
-       Name: setButtonFocus [public]
-       Desc: Sets the keyboard focus on specified button.
+  \brief Sets the keyboard focus to the specified button.
+  \param id control button ID (QtxDialog::ButtonFlags)
+  \sa hasButtonFocus()
 */
-
 void QtxDialog::setButtonFocus( const int id )
 {
   QAbstractButton* pb = button( id );
@@ -852,10 +869,11 @@ void QtxDialog::setButtonFocus( const int id )
 }
 
 /*!
-       Name: buttonText [public]
-       Desc: Return text of specified button.
+  \brief Get specified button's text.
+  \param id control button ID (QtxDialog::ButtonFlags)
+  \return button's text
+  \sa setButtonText()
 */
-
 QString QtxDialog::buttonText( const int id )
 {
   QString retval;
@@ -866,10 +884,11 @@ QString QtxDialog::buttonText( const int id )
 }
 
 /*!
-       Name: setButtonText [public]
-       Desc: Sets text to specified button.
+  \brief Set specified button's text.
+  \param id control button ID (QtxDialog::ButtonFlags)
+  \param text button's text
+  \sa buttonText()
 */
-
 void QtxDialog::setButtonText( const int id, const QString& text )
 {
   QAbstractButton* but = button( id );
@@ -881,28 +900,19 @@ void QtxDialog::setButtonText( const int id, const QString& text )
 }
 
 /*!
-       Name: setAlignment [public]
-       Desc: Sets alignment policy. Returns the previous alignment.
-                 Use the function before the first show of the dialog.
-                 If dialog flag AlignOnce is setted then align will performed
-                 only one time otherwise dialog will be aligned every time
-                 when it shown. Dialog will be aligned relative to it parent.
+  \brief Sets alignment policy.
 
-                 Following align flags may be used:
-                       Qtx::AlignAuto      - Align to center of desktop (default).
-                       Qtx::AlignLeft      - Align left side of dialog to left side of parent.
-                       Qtx::AlignRight     - Align right side of dialog to right side of parent.
-                       Qtx::AlignTop       - Align top side of dialog to top side of parent.
-                       Qtx::AlignBottom    - Align bottom side of dialog to bottom side of parent.
-                       Qtx::AlignHCenter   - Align dialog to center of parent in horizontal dimension.
-                       Qtx::AlignVCenter   - Align dialog to center of parent in vertical dimension.
-                       Qtx::AlignCenter    - Align dialog to center of parent in both dimensions.
-                       Qtx::AlignOutLeft   - Align right side of dialog to left side of parent.
-                       Qtx::AlignOutRight  - Align left side of dialog to right side of parent.
-                       Qtx::AlignOutTop    - Align bottom side of dialog to top side of parent.
-                       Qtx::AlignOutBottom - Align top side of dialog to bottom side of parent.
+  Use the function before the the dialog is first time shown.
+  If dialog flag AlignOnce is set then alignment is performed
+  only once, otherwise the dialog is aligned each time when it
+  is shown. 
+  Dialog box is aligned relatively to its parent.
+  By default, dialog box is aligned to the center of the parent 
+  widget (usually desktop or another dialog box).
+  
+  \param align alignment flag(s) (Qtx::AlignmentFlags)
+  \return previous alignment policy
 */
-
 uint QtxDialog::setAlignment( uint align )
 {
   uint oldAlign = myAlignment;
@@ -911,10 +921,8 @@ uint QtxDialog::setAlignment( uint align )
 }
 
 /*!
-       Name: update [virtual public slot]
-       Desc: Updates dialog, show selected buttons and hide unselected.
+  \brief Update dialog box.
 */
-
 void QtxDialog::update()
 {
   for ( ButtonMap::Iterator it = myButton.begin(); it != myButton.end(); ++it )
@@ -930,12 +938,16 @@ void QtxDialog::update()
 }
 
 /*!
-       Name: show [virtual public]
-       Desc: Show dialog, set keyboard focus on dialog.
+  \brief Show/hide dialog box, set keyboard focus to the dialog.
+  
+  Re-implemented from Qt.
+  
+  \param on show/hide flag
 */
-
 void QtxDialog::setVisible( bool on )
 {
+  resize( sizeHint() );
+
   QDialog::setVisible( on );
 
   if ( on )
@@ -949,10 +961,11 @@ void QtxDialog::setVisible( bool on )
 }
 
 /*!
-       Name: userButton [public]
-       Desc: Return user dialog button using specified identificator.
+  \brief Get user button by the specified \a id.
+  \param id user button ID
+  \return user button or 0 if it is not found
+  \sa insertButton(), removeButton(), userButtonIds()
 */
-
 QAbstractButton* QtxDialog::userButton( const int id ) const
 {
   QAbstractButton* b = 0;
@@ -962,10 +975,10 @@ QAbstractButton* QtxDialog::userButton( const int id ) const
 }
 
 /*!
-       Name: userButtonIds [public]
-       Desc: Return list of user dialog button identificators.
+  \brief Get all user button IDs.
+  \return list of user buttons identificators
+  \sa insertButton(), removeButton(), userButton()
 */
-
 QIntList QtxDialog::userButtonIds() const
 {
   QIntList retlist;
@@ -976,11 +989,17 @@ QIntList QtxDialog::userButtonIds() const
 }
 
 /*!
-       Name: insertButton [public]
-       Desc: Add new user dialog button. Function return identificator of
-                 newly added button in successfull case otherwise -1 will be returned.
-*/
+  \brief Add user button to the dialog box.
 
+  The button is inserted to the specified dialog box area.
+  if the button is added successfully, the unique identificator of 
+  the added button is returned, otherwise -1 is returned.
+
+  \param text text of the added button
+  \param area buttons area (QtxDialog::ButtonArea)
+  \return button ID
+  \sa removeButton(), userButton(), userButtonIds()
+*/
 int QtxDialog::insertButton( const QString& text, const int area )
 {
   if ( !myArea.contains( area ) )
@@ -1011,11 +1030,13 @@ int QtxDialog::insertButton( const QString& text, const int area )
 }
 
 /*!
-       Name: removeButton [public]
-       Desc: Remove user dialog button with specified identificator. If
-                 identificator equal -1 then method will remove all user dialog buttons.
-*/
+  \brief Remove user button.
+
+  If \c id is -1, all user buttons are removed.
 
+  \param id user button ID
+  \sa insertButton(), userButton(), userButtonIds()
+*/
 void QtxDialog::removeButton( const int id )
 {
   if ( id >= 0 )
@@ -1047,18 +1068,31 @@ void QtxDialog::removeButton( const int id )
 }
 
 /*!
-       Name: setUnits [static public]
-       Desc: Sets specified measure units in given label. Measure units close
-                 in braces. If measure units not exist then they will be added.
-                 For example:
-                       1. Label contains text 'Radius'.
-                          setUnits( aLabel, "mm" )    => aLabel contains 'Radius (mm)'
-               setUnits( aLabel, "cm" )    => aLabel contains 'Radius (cm)'
-            2. Label "aLabel" contains text 'Radius ():'.
-               setUnits( aLabel, "mm" )    => aLabel contains 'Radius (mm):'
-               setUnits( aLabel, "cm" )    => aLabel contains 'Radius (cm):'
-*/
+  \brief Set measure units to the specified label.
 
+  In the dialog box label the measure units are closed in braces.
+  If measure units do not exist they will be added.
+
+  For example:
+  \code
+  // create label "Radius"
+  QLabel* aLabel = new QLabel( "Radius", mainFrame() );
+  // set measure units to "mm"
+  setUnits( aLabel, "mm" )    // => aLabel contains 'Radius (mm)'
+  // set measure units to "cm"
+  setUnits( aLabel, "cm" )    // => aLabel contains 'Radius (cm)'
+
+  // create label "Radius" with initially not set measure units
+  QLabel* aLabel = new QLabel( "Radius ():", mainFrame() );
+  // set measure units to "mm"
+  setUnits( aLabel, "mm" )    // => aLabel contains 'Radius (mm):'
+  // set measure units to "cm"
+  setUnits( aLabel, "cm" )    // => aLabel contains 'Radius (cm):'
+  \endcode
+
+  \param aLabel label widget
+  \param aUnits measure units
+*/
 void QtxDialog::setUnits( QLabel* aLabel, const QString& aUnits )
 {
   QString label = aLabel->text();
@@ -1095,32 +1129,49 @@ void QtxDialog::setUnits( QLabel* aLabel, const QString& aUnits )
 }
 
 /*!
-       Name: acceptData [virtual protected]
-       Desc: If returns true dialog will be accepted and closed. This method
-             called if dialog flag Accept is setted.
-*/
+  \brief Check if data entered by the user is valid.
+
+  This method can be re-implemented in the successor class if it
+  requires to check user input consistency.
+  Default implementation returns \c true.
 
+  This method is called if dialog flag QtxDialog::Accept is set.
+  If this method returns \c true, then dialog will be accepted and closed.
+
+  \return \c true if user input is valid
+  \sa accept()
+*/
 bool QtxDialog::acceptData() const
 {
   return true;
 }
 
 /*!
-       Name: rejectData [virtual protected]
-       Desc: If returns true dialog will be rejected and closed. This method
-             called if dialog flag Reject is setted.
-*/
+  \brief Check if dialog box can be cancelled.
+
+  This method can be re-implemented in the successor class if it
+  requires to check possibility to cancel dialog box safely.
+  Default implementation returns \c true.
+
+  This method is called if dialog flag QtxDialog::Reject is set.
+  If this method returns \c true, then dialog will be rejected and closed.
 
+  \return \c true if dialog box can be cancelled
+  \sa reject()
+*/
 bool QtxDialog::rejectData() const
 {
   return true;
 }
 
 /*!
-       Name: createButton [virtual protected]
-       Desc: Create new user button. Invoked from method "insertButton".
-*/
+  \brief Create new user button.
 
+  This method is invoked from method insertButton().
+
+  \param parent parent widget
+  \return new user button
+*/
 QAbstractButton* QtxDialog::createButton( QWidget* parent )
 {
   QPushButton* pb = new QPushButton( parent );
@@ -1129,11 +1180,10 @@ QAbstractButton* QtxDialog::createButton( QWidget* parent )
 }
 
 /*!
-       Name: button [protected]
-       Desc: Return pointer on control button specified by identifier.
-                 If identifier is wrong then null pointer will returned.
+  \brief Get button by the specified ID.
+  \param f control button ID (QtxDialog::ButtonFlags)
+  \return button or 0 if \a id is invalid
 */
-
 QAbstractButton* QtxDialog::button( const int f ) const
 {
   QAbstractButton* retval = 0;
@@ -1143,10 +1193,10 @@ QAbstractButton* QtxDialog::button( const int f ) const
 }
 
 /*!
-       Name: buttons [protected]
-       Desc: Return map with control dialog buttons accordance to given button flags.
+  \brief Get buttons by the specified IDs.
+  \param f control button(s) ID(s) (QtxDialog::ButtonFlags)
+  \return button map
 */
-
 QtxDialog::ButtonMap QtxDialog::buttons( const int f ) const
 {
   ButtonMap retmap;
@@ -1165,10 +1215,10 @@ QtxDialog::ButtonMap QtxDialog::buttons( const int f ) const
 }
 
 /*!
-       Name: buttonId [protected]
-       Desc: Return identifier of specified button.
+  \brief Get specified button's identifier.
+  \param b button
+  \return button ID
 */
-
 int QtxDialog::buttonId( const QAbstractButton* b ) const
 {
   int id = -1;
@@ -1179,21 +1229,23 @@ int QtxDialog::buttonId( const QAbstractButton* b ) const
 }
 
 /*!
-       Name: buttonPosition
-       Desc: Returns position of specified button. [protected]
+  \brief Get position of specified button.
+  \param b button
+  \return button position (QtxDialog::ButtonPosition)
 */
-
 int QtxDialog::buttonPosition( QAbstractButton* b ) const
 {
   return buttonPosition( buttonId( b ) );
 }
 
 /*!
-       Name: showEvent [virtual protected]
-       Desc: Aligns this dialog according the parent widget and alignment
-             policy before the show.
-*/
+  \brief Align this dialog according to the parent widget and alignment
+         policy before the dialog box is shown.
+
+  Re-implemented from Qt.
 
+  \param e show event
+*/
 void QtxDialog::showEvent( QShowEvent* e )
 {
   if ( !testDialogFlags( AlignOnce ) || !myInited )
@@ -1202,10 +1254,12 @@ void QtxDialog::showEvent( QShowEvent* e )
 }
 
 /*!
-       Name: hideEvent [virtual protected]
-       Desc: Process all existing events when dialog is closed.
-*/
+  \brief Process all existing events when dialog box is hidden.
 
+  Re-implemented from Qt.
+
+  \param e hide event
+*/
 void QtxDialog::hideEvent( QHideEvent* e )
 {
   QApplication::instance()->processEvents();
@@ -1213,10 +1267,12 @@ void QtxDialog::hideEvent( QHideEvent* e )
 }
 
 /*!
-       Name: childEvent [virtual protected]
-       Desc: Setting up layout when size grip is added.
-*/
+  \brief Update dialog box layout when the size grip is added.
+
+  Re-implemented from Qt.
 
+  \param e child event
+*/
 void QtxDialog::childEvent( QChildEvent* e )
 {
   QDialog::childEvent( e );
@@ -1228,13 +1284,18 @@ void QtxDialog::childEvent( QChildEvent* e )
 }
 
 /*!
-       Name: keyPressEvent [virtual protected]
-       Desc: Calls reject() if key Escape is pressed.
-             Calls accept() if key "Ctrl+Enter" is pressed.
-                 Process key "F1" and emit signal dlgHelp().
-                 Transfer key "Ctrl+(Shift+)Tab" press event to Tab Widget.
-*/
+  \brief Process key pressing event.
 
+  Re-implemented from Qt.
+
+  Call reject() if "Escape" key is pressed.
+  Call accept() if "Ctrl+Enter" key-sequence is pressed.
+  Process "F1" key and emit signal dlgHelp().
+  Transfer "Ctrl+(Shift+)Tab" key-sequence press event 
+  to the child Tab widget (if there is any).
+
+  \param e key press event
+*/
 void QtxDialog::keyPressEvent( QKeyEvent* e )
 {
   QDialog::keyPressEvent( e );
@@ -1269,22 +1330,37 @@ void QtxDialog::keyPressEvent( QKeyEvent* e )
 }
 
 /*!
-       Name: closeEvent [virtual protected]
-       Desc: Reject the dialog.
+  \brief Called when user closes dialog box.
+  
+  Call reject() method.
+  
+  \param e close event (not used)
 */
-
-void QtxDialog::closeEvent( QCloseEvent* )
+void QtxDialog::closeEvent( QCloseEvent* /*e*/ )
 {
   reject();
 }
 
 /*!
-       Name: accept [virtual protected slot]
-       Desc: Invoke function acceptData() if it needed and if acceptData() return
-                 false does nothing. Otherwise hides the dialog and sets the result code
-                 to Accepted. Emit signal according to the pressed control button.
-*/
+  \brief Accept the dialog box.
+
+  This method is used when any accept button is pressed (usually
+  "OK", "Yes", etc).
 
+  If dialog flag QtxDialog::Accept is set, this function invokes 
+  acceptData() method, which should in this case return \c true to
+  allow further processing. 
+
+  If acceptData() returns \c false, this function just returns.
+
+  If acceptData() returns \c true, the Accepted result is set
+  and signal according to the pressed control button is emitted.
+  Then the default implementation of accept() method is called
+  (which hides the dialog box and, depending on the dialog box flags,
+  can close and destroy it).
+  \sa acceptData()
+*/
 void QtxDialog::accept()
 {
   if ( !mySender )
@@ -1310,14 +1386,25 @@ void QtxDialog::accept()
 }
 
 /*!
-       Name: reject [virtual protected slot]
-       Desc: Invoke function rejectData() if it needed and if rejectData() return
-                 false does nothing. Otherwise hides the dialog and sets the result code
-                 to Rejected. Emit signal according to the pressed control button. (If
-                 dialog was closed by key Escape or by close event emit signal dlgCancel(),
-                 or dlgClose(), or dlgNo().
-*/
+  \brief Reject the dialog box.
 
+  This method is used when any reject button is pressed (usually
+  "Close", "Cancel", "No", etc).
+
+  If dialog flag QtxDialog::Reject is set, this function invokes 
+  rejectData() method, which should in this case return \c true to
+  allow further processing. 
+
+  If rejectData() returns \c false, this function just returns.
+
+  If rejectData() returns \c true, the Rejected result is set
+  and signal according to the pressed control button is emitted.
+  Then the default implementation of reject() method is called
+  (which hides the dialog box and, depending on the dialog box flags,
+  can close and destroy it).
+  \sa rejectData()
+*/
 void QtxDialog::reject()
 {
   if ( testDialogFlags( Reject ) && !rejectData() )
@@ -1343,10 +1430,8 @@ void QtxDialog::reject()
 }
 
 /*!
-       Name: reject [private]
-       Desc: Emit signal appropriate to control button.
+  \brief Emit signal correspondingly to the control button.
 */
-
 void QtxDialog::emitSignal()
 {
   QApplication::instance()->processEvents();
@@ -1376,10 +1461,11 @@ void QtxDialog::emitSignal()
 }
 
 /*!
-       Name: onAccept [private slot]
-       Desc: Process signals "clicked()" from control buttons "OK", "Yes". Invoke accept().
-*/
+  \brief This slot is called when user presses on of the buttons
+         "OK", "Yes", etc.
 
+  Call accept() method.
+*/
 void QtxDialog::onAccept()
 {
   const QObject* obj = sender();
@@ -1388,9 +1474,10 @@ void QtxDialog::onAccept()
 }
 
 /*!
-       Name: onReject [private slot]
-       Desc: Process signals "clicked()" from control buttons "Cancel", "No", "Close".
-                 Invoke reject().
+  \brief This slot is called when user presses on of the buttons
+         "Cancel", "No", "Close".
+
+  Call reject() method.
 */
 
 void QtxDialog::onReject()
@@ -1401,11 +1488,12 @@ void QtxDialog::onReject()
 }
 
 /*!
-       Name: onButton [private slot]
-       Desc: Receive signal "clicked()" from user buttons and emit signal
-                 "dlgButton( int )" with identificator of clicked user button.
+  \brief Process user button click event.
+  
+  This method is called when user presses one of custom user buttons.
+  Emits signal dlgButton(int) with identificator of the clicked user
+  button passed as parameter.
 */
-
 void QtxDialog::onButton()
 {
   int id = buttonId( (QAbstractButton*)sender() );
@@ -1414,10 +1502,9 @@ void QtxDialog::onButton()
 }
 
 /*!
-       Name: onDestroyed [private slot]
-       Desc: Remove user button if it was destroyed.
+  \brief Watch for the user button destroying.
+  \param obj button being destroyed
 */
-
 void QtxDialog::onDestroyed( QObject* obj )
 {
   QAbstractButton* b = (QAbstractButton*)obj;
@@ -1432,10 +1519,8 @@ void QtxDialog::onDestroyed( QObject* obj )
 }
 
 /*!
-       Name: onSizeGripDestroyed [private slot]
-       Desc: Setting up layout when size grip is destroyed.
+  \brief Update dialog box layout when the size grip is destroyed.
 */
-
 void QtxDialog::onSizeGripDestroyed()
 {
   if ( layout() )
@@ -1443,10 +1528,8 @@ void QtxDialog::onSizeGripDestroyed()
 }
 
 /*!
-       Name: adjustButtons [private]
-       Desc: Setting the equal with for all buttons.
+  \brief Adjust buttons (set equal size for all buttons).
 */
-
 void QtxDialog::adjustButtons()
 {
   int minWidth = 0;
@@ -1466,3 +1549,42 @@ void QtxDialog::adjustButtons()
        (*bItr)->setMinimumWidth( minWidth );
   }
 }
+
+/*!
+  \fn void QtxDialog::dlgButton( int id )
+  \brief Emitted when the user button is clicked.
+  \param id user button identificator
+*/
+/*!
+  \fn void QtxDialog::dlgParamChanged()
+  \brief This signal can be used in successor classes to signalize about
+         some dialog parameter changing.
+*/
+/*!
+  \fn void QtxDialog::dlgHelp()
+  \brief Emitted when the "Help" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgApply()
+  \brief Emitted when the "Apply" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgOk()
+  \brief Emitted when the "OK" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgNo()
+  \brief Emitted when the "No" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgYes()
+  \brief Emitted when the "Yes" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgClose()
+  \brief Emitted when the "Close" button is clicked.
+*/
+/*!
+  \fn void QtxDialog::dlgCancel()
+  \brief Emitted when the "Cancel" button is clicked.
+*/
index 9ab34e770666bc06a9435ffe36b0e15ac0eaa921..86006f54753c0796979580d70471dbe036a60fbf 100755 (executable)
@@ -1,22 +1,22 @@
 // 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
 //
-// File:      QtxDialog.hxx
+// File:      QtxDialog.h
 // Author:    Sergey TELKOV
 
 #ifndef QTXDIALOG_H
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtCore/qlist.h>
-
-#include <QtGui/qdialog.h>
+#include <QDialog>
+#include <QMap>
 
 class QFrame;
 class QLabel;
@@ -45,140 +43,157 @@ class QTX_EXPORT QtxDialog : public QDialog
   class Border;
 
 public:
-    typedef enum { Position, Expand, Uniform } PlacePolicy;
-    typedef enum { TopArea, BottomArea, LeftArea, RightArea } ButtonArea;
-    typedef enum { Left, Right, Center, Top = Left, Bottom = Right } ButtonPosition;
-
-    typedef enum { None      = 0x00000000,
-                   OK        = 0x00000001,
-                   Apply     = 0x00000002,
-                   Cancel    = 0x00000004,
-                   Yes       = 0x00000008,
-                   No        = 0x00000010,
-                   Close     = 0x00000020,
-                   Help      = 0x00000040,
-                   OKCancel  = OK  | Cancel,
-                   YesNo     = Yes | No,
-                   Standard  = OK  | Cancel | Help,
-                   All       = Standard | YesNo | Apply | Close } ButtonFlags;
-
-    typedef enum { Accept    = 0x000001,
-                  Reject    = 0x000002,
-                  AlignOnce = 0x000004,
-                   SetFocus  = 0x000008 } DialogFlags;
-
+  //! Buttons alignment type
+  typedef enum { Position,          //!< buttons are placed according their position
+                Expand,            //!< buttons occupy all available space
+                Uniform            //!< buttons are uniformly placed in the area
+  } PlacePolicy;
+  //! Buttons area
+  typedef enum { TopArea,           //!< horizontal area at the top side of the dialog box
+                BottomArea,        //!< horizontal area at the bottom side of the dialog box
+                LeftArea,          //!< vertical area at the left side of the dialog box
+                RightArea          //!< vertical area at the right side of the dialog box
+  } ButtonArea;
+  //! Button position
+  typedef enum { Left,              //!< set button left-most
+                Right,             //!< set button right-most
+                Center,            //!< place button in the center
+                Top = Left,        //!< set button top-most
+                Bottom = Right     //!< set button bottom-most
+  } ButtonPosition;
+  //! Button ID flags
+  typedef enum { None      = 0x00000000,                      //!< no button used
+                OK        = 0x00000001,                      //!< OK button
+                Apply     = 0x00000002,                      //!< Apply button
+                Cancel    = 0x00000004,                      //!< Cancel button
+                Yes       = 0x00000008,                      //!< Yes button
+                No        = 0x00000010,                      //!< No button
+                Close     = 0x00000020,                      //!< Close button
+                Help      = 0x00000040,                      //!< Help button
+                OKCancel  = OK  | Cancel,                    //!< OK & Cancel button
+                YesNo     = Yes | No,                        //!< Yes & No buttons
+                Standard  = OK  | Cancel | Help,             //!< OK, Cancel & Help buttons
+                All       = Standard | YesNo | Apply | Close //!< all buttons
+  } ButtonFlags;
+  //! Dialog box flags
+  typedef enum { Accept    = 0x000001, //!< allow dialog box accepting control
+                Reject    = 0x000002, //!< allow dialog box rejecting control
+                AlignOnce = 0x000004, //!< align dialog box only when it is first time shown
+                SetFocus  = 0x000008  //!< allow to set focus on dialog box when it is shown (user can use setFocusProxy() and specify own initial focus widget)
+  } DialogFlags;
+  
 public:
-    QtxDialog( QWidget* = 0, bool = false, bool = false, const int = Standard, Qt::WindowFlags = 0 );
-    virtual ~QtxDialog();
-
-    void             setDialogFlags( const int );
-    void             clearDialogFlags( const int );
-    bool             testDialogFlags( const int ) const;
-
-    void             setButtonFlags( const int );
-    void             clearButtonFlags( const int );
-    bool             testButtonFlags( const int ) const;
-
-    int              buttonPosition( const int ) const;
-    void             setButtonPosition( const int, const int = -1 );
-    void             setPlacePosition( const int, const int );
-
-    int              placePolicy( const int ) const;
-    void             setPlacePolicy( const int, const int );
-    void             setButtonPlace( const int, const int );
-
-    QString          buttonText( const int );
-    void             setButtonText( const int, const QString& text );
-
-    void             setButtonFocus( const int );
-    bool             hasButtonFocus( const int ) const;
-
-    bool             isButtonEnabled( const int ) const;
-    void             setButtonEnabled( const bool, const int );
-
-    bool             isBorderEnabled( const int ) const;
-    void             setBorderEnabled( const bool, const int );
-
-    void             removeButton( const int );
-    int              insertButton( const QString&, const int = BottomArea );
-
-    QIntList         userButtonIds() const;
-    QAbstractButton* userButton( const int ) const;
-
-    uint             setAlignment( uint align );
-    static  void     setUnits( QLabel*, const QString& );
-
-Q_SIGNALS:
-    void             dlgButton( int );
-    void             dlgParamChanged();
-
-    void             dlgHelp();
-    void             dlgApply();
-
-    void             dlgOk();
-    void             dlgNo();
-    void             dlgYes();
-    void             dlgClose();
-    void             dlgCancel();
-
-public Q_SLOTS:
-    void             update();
-    virtual void     setVisible( bool );
-
-protected Q_SLOTS:
-    virtual void     accept();
-    virtual void     reject();
-
-private Q_SLOTS:
-    void             onAccept();
-    void             onReject();
-    void             onButton();
-    void             onSizeGripDestroyed();
-    void             onDestroyed( QObject* );
+  QtxDialog( QWidget* = 0, bool = false, bool = false, const int = Standard, Qt::WindowFlags = 0 );
+  virtual ~QtxDialog();
+  
+  void             setDialogFlags( const int );
+  void             clearDialogFlags( const int );
+  bool             testDialogFlags( const int ) const;
+  
+  void             setButtonFlags( const int );
+  void             clearButtonFlags( const int );
+  bool             testButtonFlags( const int ) const;
+  
+  int              buttonPosition( const int ) const;
+  void             setButtonPosition( const int, const int = -1 );
+  void             setPlacePosition( const int, const int );
+  
+  int              placePolicy( const int ) const;
+  void             setPlacePolicy( const int, const int );
+  void             setButtonPlace( const int, const int );
+  
+  QString          buttonText( const int );
+  void             setButtonText( const int, const QString& text );
+  
+  void             setButtonFocus( const int );
+  bool             hasButtonFocus( const int ) const;
+  
+  bool             isButtonEnabled( const int ) const;
+  void             setButtonEnabled( const bool, const int );
+  
+  bool             isBorderEnabled( const int ) const;
+  void             setBorderEnabled( const bool, const int );
+  
+  void             removeButton( const int );
+  int              insertButton( const QString&, const int = BottomArea );
+  
+  QIntList         userButtonIds() const;
+  QAbstractButton* userButton( const int ) const;
+  
+  uint             setAlignment( uint align );
+  static  void     setUnits( QLabel*, const QString& );
+  
+signals:
+  void             dlgButton( int );
+  void             dlgParamChanged();
+  
+  void             dlgHelp();
+  void             dlgApply();
+  
+  void             dlgOk();
+  void             dlgNo();
+  void             dlgYes();
+  void             dlgClose();
+  void             dlgCancel();
+  
+public slots:
+  void             update();
+  virtual void     setVisible( bool );
+
+protected slots:
+  virtual void     accept();
+  virtual void     reject();
+
+private slots:
+  void             onAccept();
+  void             onReject();
+  void             onButton();
+  void             onSizeGripDestroyed();
+  void             onDestroyed( QObject* );
 
 protected:
-    typedef QMap<int, QAbstractButton*> ButtonMap;
+  typedef QMap<int, QAbstractButton*> ButtonMap;   //!< button map
 
 protected:
-    QFrame*          mainFrame() const;
-
-    virtual bool     acceptData() const;
-    virtual bool     rejectData() const;
-
-    virtual QAbstractButton* createButton( QWidget* );
-
-    QAbstractButton* button( const int ) const;
-    ButtonMap        buttons( const int = All ) const;
-    int              buttonId( const QAbstractButton* ) const;
-    int              buttonPosition( QAbstractButton* ) const;
-
-    virtual void     showEvent( QShowEvent* );
-    virtual void     hideEvent( QHideEvent* );
-    virtual void     closeEvent( QCloseEvent* );
-    virtual void     childEvent( QChildEvent* );
-    virtual void     keyPressEvent( QKeyEvent* );
-
+  QFrame*          mainFrame() const;
+  
+  virtual bool     acceptData() const;
+  virtual bool     rejectData() const;
+  
+  virtual QAbstractButton* createButton( QWidget* );
+  
+  QAbstractButton* button( const int ) const;
+  ButtonMap        buttons( const int = All ) const;
+  int              buttonId( const QAbstractButton* ) const;
+  int              buttonPosition( QAbstractButton* ) const;
+  
+  virtual void     showEvent( QShowEvent* );
+  virtual void     hideEvent( QHideEvent* );
+  virtual void     closeEvent( QCloseEvent* );
+  virtual void     childEvent( QChildEvent* );
+  virtual void     keyPressEvent( QKeyEvent* );
+  
 private:
-    void             adjustButtons();
-    void             emitSignal();
-
+  void             adjustButtons();
+  void             emitSignal();
+  
 private:
-    typedef QMap<int, Area*> AreaMap;
-    typedef QMap<int, int>   PositionMap;
-
-    friend class Area;
+  typedef QMap<int, Area*> AreaMap;        //!< button area map
+  typedef QMap<int, int>   PositionMap;    //!< button position map
+  
+  friend class Area;
 
 private:
-    AreaMap          myArea;
-    ButtonMap        myButton;
-    PositionMap      myPosition;
-
-    bool             myInited;
-    const QObject*   mySender;
-    uint             myAlignment;
-    QFrame*          myMainFrame;
-    int              myButtonFlags;
-    int              myDialogFlags;
+  AreaMap          myArea;                 //!< buttons areas map
+  ButtonMap        myButton;               //!< buttons map
+  PositionMap      myPosition;             //!< buttons position map
+  
+  bool             myInited;               //!< dialog's "initialized" flag
+  const QObject*   mySender;               //!< signal sender
+  uint             myAlignment;            //!< dialog box alignment type
+  QFrame*          myMainFrame;            //!< main frame
+  int              myButtonFlags;          //!< button flags
+  int              myDialogFlags;          //!< dialog flags
 };
 
 #ifdef WIN32
index 49b22b89c1005e22b0dd8cd454ce34afd3c3e53f..8f40092d3c2e136586aa4b834cad6184cd2eb40f 100755 (executable)
 
 #include "QtxDockAction.h"
 
-#include <QtGui/qmenu.h>
-#include <QtGui/qtoolbar.h>
-#include <QtGui/qdockwidget.h>
-#include <QtGui/qmainwindow.h>
+#include <QMenu>
+#include <QToolBar>
+#include <QDockWidget>
+#include <QMainWindow>
 
 /*!
-       Name: QtxDockAction [public]
-       Desc: Constructs an Dock action with given main window and name.
+  \class QtxDockAction
+  \brief Dockable windows & toolbars list action.
+
+  Implements the action which provides the popup menu with the list
+  of toolbars and/or dockable windows list owned by the main window.
+  This action can be used, for example, in the menu "Windows".
 */
 
+/*!
+  \brief Constructor.
+  \param mw parent main window
+*/
 QtxDockAction::QtxDockAction( QMainWindow* mw )
 : QtxAction( "Windows and Toolbars", "Windows and Toolbars", 0, mw ),
-myMain( mw ),
-myType( Both )
+  myType( Both ),
+  myMain( mw )
 {
   initialize();
 }
 
 /*!
-       Name: QtxDockAction [public]
-       Desc: This constructor creates an action with the following properties: the
-                   description text, the menu text and. It is a child of given main window
-        and named specified name.
+  \brief Constructor.
+  \param text description (tooltip) text
+  \param menuText menu text
+  \param mw parent main window
 */
-
 QtxDockAction::QtxDockAction( const QString& text, const QString& menuText, QMainWindow* mw )
 : QtxAction( text, menuText, 0, mw ),
-myMain( mw ),
-myType( Both )
+  myType( Both ),
+  myMain( mw )
 {
   initialize();
 }
 
 /*!
-       Name: QtxDockAction [public]
-       Desc: This constructor creates an action with the following properties: the
-                   description text, the menu text, the icon or iconset icon and keyboard
-        accelerator. It is a child of given main window and named specified name.
+  \brief Constructor.
+  \param text description (tooltip) text
+  \param icon action icon
+  \param menuText menu text
+  \param mw parent main window
 */
-
 QtxDockAction::QtxDockAction( const QString& text, const QIcon& icon, const QString& menuText, QMainWindow* mw )
 : QtxAction( text, icon, menuText, 0, mw ),
-myMain( mw ),
-myType( Both )
+  myType( Both ),
+  myMain( mw )
 {
   initialize();
 }
 
 /*!
-       Name: ~QtxDockAction [public]
-       Desc: Removes all added popup items.
+  \brief Desctructor
+  
+  Does nothing currently.
 */
-
 QtxDockAction::~QtxDockAction()
 {
 }
 
 /*!
-       Name: mainWindow [public]
-       Desc: Returns the main window which contains managed dock windows.
+  \brief Get parent main window.
+  \return main window pointer.
 */
-
 QMainWindow* QtxDockAction::mainWindow() const
 {
   return myMain;
 }
 
+/*!
+  \brief Get dock action type.
+  \return dock type (QtxDockAction::DockType)
+*/
 int QtxDockAction::dockType() const
 {
   return myType;
 }
 
+/*!
+  \brief Set dock action type.
+  \param type dock type (QtxDockAction::DockType)
+*/
 void QtxDockAction::setDockType( const int type )
 {
   myType = type;
 }
 
 /*!
-       Name: onAboutToShow [private slots]
-       Desc: Prepare sub popup with dock windows list when parent popup is shown.
+  \brief Prepare popup menu with dock windows list when 
+         parent popup menu is shown.
 */
-
 void QtxDockAction::onAboutToShow()
 {
   updateMenu();
@@ -110,10 +123,9 @@ void QtxDockAction::onAboutToShow()
 }
 
 /*!
-       Name: toolBars [private]
-       Desc: Returns all toolbars of the main window.
+  \brief Get all toolbars owned by parent main window.
+  \param lst returned list of all toolbars owned by main window
 */
-
 void QtxDockAction::toolBars( QList<QToolBar*>& lst ) const
 {
   lst.clear();
@@ -132,10 +144,9 @@ void QtxDockAction::toolBars( QList<QToolBar*>& lst ) const
 }
 
 /*!
-       Name: dockWidgets [private]
-       Desc: Returns all dock widgets of the main window.
+  \brief Get all dockable windows owned by parent main window.
+  \param lst returned list of all dockable windows owned by main window
 */
-
 void QtxDockAction::dockWidgets( QList<QDockWidget*>& lst ) const
 {
   lst.clear();
@@ -153,10 +164,6 @@ void QtxDockAction::dockWidgets( QList<QDockWidget*>& lst ) const
   }
 }
 
-/*!
-       Name: updateInfo [private]
-       Desc: Updates icon and caption info of dock window in the corresponded action.
-*/
 /*
 void QtxDockAction::updateInfo( QDockWindow* dw )
 {
@@ -178,12 +185,28 @@ void QtxDockAction::updateInfo( QDockWindow* dw )
 }
 */
 
+/*!
+  \brief Customize action adding to the widget operation.
+  
+  Called when the action is added to the widget.
+  Reimplemented from QtxAction class.
+
+  \param w widget this action is added to (menu or toolbar)
+*/
 void QtxDockAction::addedTo( QWidget* w )
 {
   if ( w->inherits( "QMenu" ) )
     connect( w, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
 }
 
+/*!
+  \brief Customize action removing from the widget operation.
+  
+  Called when the action is removed from the widget.
+  Reimplemented from QtxAction class.
+
+  \param w widget this action is removed from to (menu or toolbar)
+*/
 void QtxDockAction::removedFrom( QWidget* w )
 {
   if ( w->inherits( "QMenu" ) )
@@ -191,17 +214,15 @@ void QtxDockAction::removedFrom( QWidget* w )
 }
 
 /*!
-       Name: initialize [private]
-       Desc: Initialisation of the object.
+  \brief Initialize the action.
 */
-
 void QtxDockAction::initialize()
 {
   setMenu( new QMenu( 0 ) );
 }
 
 /*!
-  Updates menu of action
+  \brief Update action child popup menu.
 */
 void QtxDockAction::updateMenu()
 {
index 8fd83e6fb4330b219b07662878fe118cf13dec8f..293e3351d669aefe9eb957a83d2b3cececec8df5 100755 (executable)
 // File:      QtxDockAction.h
 // Author:    Sergey TELKOV
 
-#ifndef QTX_DOCKACTION_H
-#define QTX_DOCKACTION_H
+#ifndef QTXDOCKACTION_H
+#define QTXDOCKACTION_H
 
 #include "QtxAction.h"
 
-#include <QtCore/qlist.h>
+#include <QList>
 
 class QIcon;
 class QString;
@@ -41,7 +41,11 @@ class QTX_EXPORT QtxDockAction : public QtxAction
   Q_OBJECT
 
 public:
-  enum { ToolBar, DockWidget, Both };
+  //! Dock windows type.
+  enum { ToolBar,      //!< list toolbars only
+        DockWidget,   //!< list dockable windows only
+        Both          //!< list toolbars and dockable windows
+  } DockType;
 
 public:
   QtxDockAction( QMainWindow* );
@@ -54,7 +58,7 @@ public:
 
   QMainWindow* mainWindow() const;
 
-private Q_SLOTS:
+private slots:
   void         onAboutToShow();
 
 protected:
@@ -69,12 +73,12 @@ private:
   void         dockWidgets( QList<QDockWidget*>& ) const;
 
 private:
-  int          myType;
-  QMainWindow* myMain;
+  int          myType;   //!< dock action type
+  QMainWindow* myMain;   //!< parent main window
 };
 
 #ifdef WIN32
 #pragma warning( default:4251 )
 #endif
 
-#endif
+#endif // QTXDOCKACTION_H
index 7b16f42471580d826c4d5a24751753e159dd6d2a..fd6f003714d12dcb0fb779ee6814236f0ba8ddcf 100644 (file)
 #include <QApplication>
 
 /*!
-  \class QtxDockWidget::Watcher [Internal]
-  Internal object with event filter.
+  \class QtxDockWidget::Watcher
+  \internal
+  \brief Internal class which goal is to watch parent dockable widget state changing.
 */
+
 class QtxDockWidget::Watcher : public QObject
 {
 public:
   Watcher( QtxDockWidget* );
 
   void           shown( QtxDockWidget* );
-  void           hided( QtxDockWidget* );
+  void           hidden( QtxDockWidget* );
 
   virtual bool   eventFilter( QObject*, QEvent* );
 
@@ -62,12 +64,13 @@ private:
 };
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param cont dockable widget to be watched
 */
 QtxDockWidget::Watcher::Watcher( QtxDockWidget* cont )
 : QObject( cont ), myCont( cont ),
-myState( true ),
-myEmpty( false )
+  myState( true ),
+  myEmpty( false )
 {
   myCont->installEventFilter( this );
   myVisible = myCont->isVisibleTo( myCont->parentWidget() );
@@ -76,7 +79,10 @@ myEmpty( false )
 }
 
 /*!
-  Custom event filter
+  \brief Custom event filter.
+  \param o event receiver object
+  \param e event sent to object
+  \return \c true if further event processing should be stopped
 */
 bool QtxDockWidget::Watcher::eventFilter( QObject* o, QEvent* e )
 {
@@ -111,7 +117,8 @@ bool QtxDockWidget::Watcher::eventFilter( QObject* o, QEvent* e )
 }
 
 /*!
-  Sets internal status to shown
+  \brief Set internal status to "shown"
+  \param dw dockable widget
 */
 void QtxDockWidget::Watcher::shown( QtxDockWidget* dw )
 {
@@ -122,9 +129,10 @@ void QtxDockWidget::Watcher::shown( QtxDockWidget* dw )
 }
 
 /*!
-  Sets internal status to hidden
+  \brief Set internal status to "hidden"
+  \param dw dockable widget
 */
-void QtxDockWidget::Watcher::hided( QtxDockWidget* dw )
+void QtxDockWidget::Watcher::hidden( QtxDockWidget* dw )
 {
   if ( dw != myCont )
     return;
@@ -133,7 +141,7 @@ void QtxDockWidget::Watcher::hided( QtxDockWidget* dw )
 }
 
 /*!
-  Shows corresponding dock window
+  \brief Show the dock window being watched
 */
 void QtxDockWidget::Watcher::showContainer()
 {
@@ -147,7 +155,7 @@ void QtxDockWidget::Watcher::showContainer()
 }
 
 /*!
-  Hides corresponding dock window
+  \brief Hide the dock window being watched
 */
 void QtxDockWidget::Watcher::hideContainer()
 {
@@ -161,9 +169,10 @@ void QtxDockWidget::Watcher::hideContainer()
 }
 
 /*!
-  Event filter of custom events
+  \brief Proces custom events.
+  \param e custom event (not used)
 */
-void QtxDockWidget::Watcher::customEvent( QEvent* )
+void QtxDockWidget::Watcher::customEvent( QEvent* /*e*/ )
 {
   updateIcon();
   updateCaption();
@@ -171,7 +180,8 @@ void QtxDockWidget::Watcher::customEvent( QEvent* )
 }
 
 /*!
-  Installs this object as event filter to all widgets inside corresponding main window
+  \brief Install this object as event filter to all children widgets
+         of the dockable widget being watched.
 */
 void QtxDockWidget::Watcher::installFilters()
 {
@@ -190,7 +200,8 @@ void QtxDockWidget::Watcher::installFilters()
 }
 
 /*!
-  Updates visibility of all widgets inside corresponding main window
+  \brief Update visibility state of all children widgets of the dockable widget
+         being watched.
 */
 void QtxDockWidget::Watcher::updateVisibility()
 {
@@ -223,7 +234,7 @@ void QtxDockWidget::Watcher::updateVisibility()
 }
 
 /*!
-  Updates icon of corresponding main window
+  \brief Update the icon of dockable window being watched
 */
 void QtxDockWidget::Watcher::updateIcon()
 {
@@ -234,7 +245,7 @@ void QtxDockWidget::Watcher::updateIcon()
 }
 
 /*!
-  Updates caption of corresponding main window
+  \brief Update the title of dockable window being watched
 */
 void QtxDockWidget::Watcher::updateCaption()
 {
@@ -243,7 +254,15 @@ void QtxDockWidget::Watcher::updateCaption()
 }
 
 /*!
-  Constructor
+  \class QtxDockWidget
+  \brief Enhanced dockable widget class.
+*/
+
+/*!
+  \brief Constructor.
+  \param title dockable widget title
+  \param parent parent widget
+  \param f widget flags
 */
 QtxDockWidget::QtxDockWidget( const QString& title, QWidget* parent, Qt::WindowFlags f )
 : QDockWidget( title, parent, f ),
@@ -254,7 +273,11 @@ QtxDockWidget::QtxDockWidget( const QString& title, QWidget* parent, Qt::WindowF
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \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
 */
 QtxDockWidget::QtxDockWidget( const bool watch, QWidget* parent, Qt::WindowFlags f )
 : QDockWidget( parent, f ),
@@ -268,7 +291,9 @@ QtxDockWidget::QtxDockWidget( const bool watch, QWidget* parent, Qt::WindowFlags
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param parent parent widget
+  \param f widget flags
 */
 QtxDockWidget::QtxDockWidget( QWidget* parent, Qt::WindowFlags f )
 : QDockWidget( parent, f ),
@@ -277,14 +302,15 @@ myWatcher( 0 )
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxDockWidget::~QtxDockWidget()
 {
 }
 
 /*!
-  \return the recommended size for the widget
+  \brief Get the recommended size for the widget.
+  \return recommended dockable widget size
 */
 QSize QtxDockWidget::sizeHint() const
 {
@@ -302,7 +328,8 @@ QSize QtxDockWidget::sizeHint() const
 }
 
 /*!
-  \return the recommended minimum size for the widget
+  \brief Get the recommended minimum size for the widget.
+  \return recommended dockable widget minimum size
 */
 QSize QtxDockWidget::minimumSizeHint() const
 {
@@ -325,7 +352,8 @@ QSize QtxDockWidget::minimumSizeHint() const
 }
 
 /*!
-  Shows/hides the window
+  \brief Show/hide the dockable window.
+  \param on new visibility state
 */
 void QtxDockWidget::setVisible( bool on )
 {
@@ -334,7 +362,7 @@ void QtxDockWidget::setVisible( bool on )
     if ( on )
       myWatcher->shown( this );
     else
-      myWatcher->hided( this );
+      myWatcher->hidden( this );
   }
 
   updateGeometry();
@@ -344,12 +372,20 @@ void QtxDockWidget::setVisible( bool on )
   QDockWidget::setVisible( on );
 }
 
+/*!
+  \brief Process resize event
+  \param e event
+*/
 void QtxDockWidget::resizeEvent( QResizeEvent* e )
 {
   QDockWidget::resizeEvent( e );
   updateState();
 }
 
+/*!
+  \brief Get dockable window orientation.
+  \return orientation type
+*/
 Qt::Orientation QtxDockWidget::orientation() const
 {
   QMainWindow* mw = 0;
@@ -383,6 +419,9 @@ Qt::Orientation QtxDockWidget::orientation() const
   return res;
 }
 
+/*!
+  \brief Update dockable window state.
+*/
 void QtxDockWidget::updateState()
 {
   Qt::Orientation o = orientation();
@@ -393,3 +432,9 @@ void QtxDockWidget::updateState()
 
   emit orientationChanged( myOrientation );
 }
+
+/*!
+  \fn QtxDockWidget::orientationChanged(Qt::Orientation o)
+  \brief Emitted when the dockable window orientation is changed.
+  \param o new window orientation
+*/
index 3554f05f73f59ceb4276cd1036e797f4ba71c655..f94756ebf5f7e4401b68bf4a70391b0fa2afd41a 100644 (file)
@@ -19,6 +19,9 @@
 // File:      QtxDockWidget.h
 // Author:    Sergey TELKOV
 
+#ifndef QTXDOCKWIDGET_H
+#define QTXDOCKWIDGET_H
+
 #include "Qtx.h"
 
 #include <QDockWidget>
@@ -40,10 +43,10 @@ public:
 
   Qt::Orientation orientation() const;
 
-Q_SIGNALS:
+signals:
   void            orientationChanged( Qt::Orientation );
 
-public Q_SLOTS:
+public slots:
   virtual void    setVisible( bool );
 
 protected:
@@ -53,6 +56,8 @@ private:
   void            updateState();
 
 private:
-  Watcher*        myWatcher;
-  Qt::Orientation myOrientation;
+  Watcher*        myWatcher;       //!< watcher object
+  Qt::Orientation myOrientation;   //!< dockable window orientation
 };
+
+#endif // QTXDOCKWIDGET_H
diff --git a/src/Qtx/QtxDoubleSpinBox.cxx b/src/Qtx/QtxDoubleSpinBox.cxx
new file mode 100644 (file)
index 0000000..c79e581
--- /dev/null
@@ -0,0 +1,152 @@
+// 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
+//
+// File:      QtxDoubleSpinBox.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxDoubleSpinBox.h"
+
+#include <QLineEdit>
+
+/*!
+  \class QtxDoubleSpinBox
+  \brief Enhanced version of the Qt's double spin box.
+
+  The QtxDoubleSpinBox class represents the widget for entering the
+  floating point values. In addition to the functionality provided by
+  QDoubleSpinBox, this class supports "cleared" state - this is the
+  state corresponding to "None" (or empty) entered value.
+
+  To set "cleared" state use setCleared() method. To check if the spin
+  box stores "cleared" state, use isCleared() method.
+  For example:
+  \code
+  if (myDblSpinBox->isCleared()) {
+    ... // process "None" state
+  }
+  else {
+    double value = myDblSpinBox->value();
+    ... // process entered value
+  }
+  \endcode
+*/
+
+/*!
+  \brief Constructor.
+
+  Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
+  a step value of 1.0 and a precision of 2 decimal places. 
+  The value is initially set to 0.00.
+
+  \param parent parent object
+*/
+QtxDoubleSpinBox::QtxDoubleSpinBox( QWidget* parent )
+: QDoubleSpinBox( parent ),
+  myCleared( false )
+{
+  connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), 
+          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, QWidget* parent )
+: QDoubleSpinBox( parent ),
+  myCleared( false )
+{
+  setMinimum( min );
+  setMaximum( max );
+  setSingleStep( step );
+
+  connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), 
+          this, SLOT( onTextChanged( const QString& ) ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxDoubleSpinBox::~QtxDoubleSpinBox()
+{
+}
+
+/*!
+  \brief Check if spin box is in the "cleared" state.
+  \return \c true if spin box is cleared
+*/
+bool QtxDoubleSpinBox::isCleared() const
+{
+  return myCleared;
+}
+
+/*!
+  \brief Change "cleared" status of the spin box.
+  \param on new "cleared" status
+*/
+void QtxDoubleSpinBox::setCleared( const bool on )
+{
+  if ( myCleared == on )
+    return;
+  
+  myCleared = on;
+  setSpecialValueText( specialValueText() );
+}
+
+/*!
+  \brief Convert value to the text.
+  \param val value being converted
+  \return string containing the converted value
+*/
+QString QtxDoubleSpinBox::textFromValue( double val ) const
+{
+  return myCleared ? QString() : QDoubleSpinBox::textFromValue( val );
+}
+
+/*!
+  \brief Perform \a steps increment/decrement steps.
+  
+  The \a steps value can be any integer number. If it is > 0,
+  the value incrementing is done, otherwise value is decremented
+  \a steps times.  
+
+  \param steps number of increment/decrement steps
+*/
+void QtxDoubleSpinBox::stepBy( int steps )
+{
+  myCleared = false;
+
+  QDoubleSpinBox::stepBy( steps );
+}
+
+/*!
+  \brief Called when user enters the text in the spin box.
+  \param txt current spin box text (not used)
+*/
+void QtxDoubleSpinBox::onTextChanged( const QString& /*txt*/ )
+{
+  myCleared = false;
+}
diff --git a/src/Qtx/QtxDoubleSpinBox.h b/src/Qtx/QtxDoubleSpinBox.h
new file mode 100644 (file)
index 0000000..45ef543
--- /dev/null
@@ -0,0 +1,53 @@
+// 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
+//
+// File:      QtxDoubleSpinBox.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXDOUBLESPINBOX_H
+#define QTXDOUBLESPINBOX_H
+
+#include "Qtx.h"
+
+#include <QDoubleSpinBox>
+
+class QTX_EXPORT QtxDoubleSpinBox : public QDoubleSpinBox
+{
+  Q_OBJECT
+
+public:
+  QtxDoubleSpinBox( QWidget* = 0 );
+  QtxDoubleSpinBox( double, double, double = 1, QWidget* = 0 );
+  virtual ~QtxDoubleSpinBox();
+
+  bool            isCleared() const;
+  virtual void    setCleared( const bool );
+
+  virtual void    stepBy( int );
+
+private slots:
+  virtual void    onTextChanged( const QString& );
+
+protected:
+  virtual QString textFromValue( double ) const;
+
+private:
+  bool            myCleared;
+};
+
+#endif
diff --git a/src/Qtx/QtxEvalExpr.cxx b/src/Qtx/QtxEvalExpr.cxx
new file mode 100644 (file)
index 0000000..75bcb7c
--- /dev/null
@@ -0,0 +1,2435 @@
+// 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
+//
+// File:      QtxEvalExpr.cxx
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
+
+#include "QtxEvalExpr.h"
+
+#include <QStack>
+
+#include <math.h>
+
+/*!
+  \class QtxEvalExpr
+  \brief String expression evaluator.
+*/
+
+/*!
+  \brief Constructor.
+
+  The evaluator is initalized by standard operations. Use another constructor with parameter
+  \a stdSets = \c false to avoid initialization of evaluator with standard operations.
+
+  \param expr expression to be evaluated
+*/
+QtxEvalExpr::QtxEvalExpr( const QString& expr )
+{
+  intialize( true, expr );
+}
+
+/*!
+  \brief Constructor.
+  \param stdSets if \c true, the evaluator is initalized by standard operations
+  \param expr expression to be evaluated
+*/
+QtxEvalExpr::QtxEvalExpr( const bool stdSets, const QString& expr )
+{
+  intialize( stdSets, expr );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalExpr::~QtxEvalExpr()
+{
+  delete myParser;
+}
+
+/*!
+  \brief Initialize the evaluator.
+  \param stdSets if \c true, the evaluator is initalized by standard operations
+  \param expr expression to be evaluated
+*/
+void QtxEvalExpr::intialize( const bool stdSets, const QString& expr )
+{
+  myParser = new QtxEvalParser();
+  if ( stdSets )
+  {
+    myParser->setAutoDeleteOperationSets( true );
+    myParser->insertOperationSet( new QtxEvalSetArithmetic() );
+    myParser->insertOperationSet( new QtxEvalSetLogic() );
+    myParser->insertOperationSet( new QtxEvalSetString() );
+    myParser->insertOperationSet( new QtxEvalSetMath() );
+    myParser->insertOperationSet( new QtxEvalSetSets() );
+    myParser->insertOperationSet( new QtxEvalSetConst() );
+  }
+  setExpression( expr );
+}
+
+/*!
+  \brief Evaluate the expression.
+  \param expr expression to be evaluated
+  \return result of the evaluation
+*/
+QVariant QtxEvalExpr::calculate( const QString& expr )
+{
+  if ( !expr.isEmpty() )
+    setExpression( expr );
+  return myParser->calculate();
+}
+
+/*!
+  \brief Get the expression.
+  \return expression string
+*/
+QString QtxEvalExpr::expression() const
+{
+  return myExpr;
+}
+
+/*!
+  \brief Set the expression.
+  \param expr expression string
+*/
+void QtxEvalExpr::setExpression( const QString& expr )
+{
+  if ( expr == expression() )
+    return;
+
+  myExpr = expr;
+  myParser->setExpression( myExpr );
+}
+
+/*!
+  \brief Get the code of latest parsing error.
+  \return the code of the last error
+*/
+QtxEvalExpr::Error QtxEvalExpr::error() const
+{
+  return myParser->error();
+}
+
+/*!
+  \brief Get the expression parser.
+  \return expression parser
+*/
+QtxEvalParser* QtxEvalExpr::parser() const
+{
+  return myParser;
+}
+
+/*!
+  \brief Get current set of operations.
+  \return operations set
+  \sa insertOperationSet(), removeOperationSet(), operationSet()
+*/
+QList<QtxEvalSet*> QtxEvalExpr::operationSets() const
+{
+  return myParser->operationSets();
+}
+
+/*!
+  \brief Install the operation.
+  \param operation to be added
+  \param idx index in the list at which the operation shoud be inserted
+  \sa operationSets(), removeOperationSet(), operationSet()
+*/
+void QtxEvalExpr::insertOperationSet( QtxEvalSet* set, const int idx )
+{
+  myParser->insertOperationSet( set, idx );
+}
+
+/*!
+  \brief Remove the operation.
+  \param operation to be removed
+  \sa operationSets(), insertOperationSet(), operationSet()
+*/
+void QtxEvalExpr::removeOperationSet( QtxEvalSet* set )
+{
+  myParser->removeOperationSet( set );
+}
+
+/*!
+  \brief Get the operation by name.
+  \param name operation name
+  \return operation of 0 if not found
+  \sa operationSets(), insertOperationSet(), removeOperationSet()
+*/
+QtxEvalSet* QtxEvalExpr::operationSet( const QString& name ) const
+{
+  return myParser->operationSet( name );
+}
+
+/*!
+  \brief Get the 'auto-delete operations' flag value.
+  \return \c true if all operations shoud be automatically deleted when the evaluator is destroyed
+  \sa setAutoDeleteOperationSets()
+*/
+bool QtxEvalExpr::autoDeleteOperationSets() const
+{
+  return myParser->autoDeleteOperationSets();
+}
+
+/*!
+  \brief Set the 'auto-delete operations' flag value.
+  \param on if \c true, all operations shoud be automatically deleted when the evaluator is destroyed
+  \sa autoDeleteOperationSets()
+*/
+void QtxEvalExpr::setAutoDeleteOperationSets( const bool on )
+{
+  myParser->setAutoDeleteOperationSets( on );
+}
+
+/*!
+  \class QtxEvalParser
+  \brief Expression parser.
+
+  This class provides the functionality to calculate value of the expression using defined set of operations.
+  Standard operations (arithmetics, logic, strings, etc) are implemented in the corresponding successors of the
+  QtxEvalSet class: QtxEvalSetArithmetic, QtxEvalSetLogic, QtxEvalSetMath, QtxEvalSetString, ...
+
+  The parser allows using parameters with help of methods has(), set(), remove(), value(). It uses
+  postfix representation of expressions and uses class QtxEvalSet in order to make certain operation.
+
+  Every instance of parser contains only one postfix - thus, if the expression is changed, the postfix
+  must be rebuilt. In order to increase performance of frequent calculations for many of expressions it is 
+  recommended to use different instances of the parser for each expression.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalParser::QtxEvalParser()
+: myAutoDel( false )
+{
+  setError( QtxEvalExpr::OK );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalParser::~QtxEvalParser()
+{
+  if ( autoDeleteOperationSets() )
+    qDeleteAll( mySets );
+}
+
+/*!
+  \brief Get current operations set.
+  \return current operations set
+*/
+QList<QtxEvalSet*> QtxEvalParser::operationSets() const
+{
+  return mySets;
+}
+
+/*!
+  \brief Get the operations set by \a name.
+  \param name the name of the operation set
+  \return operation set or 0 if not found
+*/
+QtxEvalSet* QtxEvalParser::operationSet( const QString& name ) const
+{
+  QtxEvalSet* set = 0;
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && !set; ++it )
+  {
+    if ( (*it)->name() == name )
+      set = *it;
+  }
+  return set;
+}
+
+/*!
+  \brief Install the operations set.
+  \param operations set to be added
+  \param idx index in the list at which the operations set shoud be inserted
+  \sa operationSets(), removeOperationSet(), operationSet()
+*/
+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 );
+  mySets.insert( index, set );
+}
+
+/*!
+  \brief Remove the operations set.
+  \param operations set to be removed
+  \sa operationSets(), insertOperationSet(), operationSet()
+*/
+void QtxEvalParser::removeOperationSet( QtxEvalSet* set )
+{
+  mySets.removeAll( set );
+}
+
+/*!
+  \brief Get the 'auto-delete operations' flag value.
+  \return \c true if all operations shoud be automatically deleted when the parser is destroyed
+  \sa setAutoDeleteOperationSets()
+*/
+bool QtxEvalParser::autoDeleteOperationSets() const
+{
+  return myAutoDel;
+}
+
+/*!
+  \brief Set the 'auto-delete operations' flag value.
+  \param on if \c true, all operations shoud be automatically deleted when the parser is destroyed
+  \sa autoDeleteOperationSets()
+*/
+void QtxEvalParser::setAutoDeleteOperationSets( const bool on )
+{
+  myAutoDel = on;
+}
+
+/*!
+  \brief Search elements of the list as substrings starting from \a offset.
+  \param list list of substrings
+  \param str string in which the searching is performed
+  \param offset starting index for search
+  \param matchLen returning matching length of any substring
+  \param listind returning index of the found substring in the \a list
+  \return position of first found substring inside the \a str or -1 if no matches is found
+*/
+int QtxEvalParser::search( const QStringList& list, const QString& str,
+                           int offset, int& matchLen, int& listind )
+{
+  int min = -1;
+  QStringList::const_iterator anIt = list.begin(), aLast = list.end();
+  for ( int ind = 0; anIt != aLast; anIt++, ind++ )
+  {
+    int pos = str.indexOf( *anIt, offset );
+    if ( pos >= 0 && ( min < 0 || min > pos ||
+                       ( min == pos && matchLen < (int)(*anIt).length() ) ) )
+    {
+      min = pos;
+      listind = ind;
+      matchLen = (*anIt).length();
+    }
+  }
+  if ( min < 0 )
+    matchLen = 0;
+  return min;
+}
+
+/*!
+  \brief Get the substring field from the string \a str.
+  \param str source string
+  \param pos start position of the substring
+  \param len length of the substring
+  \return substring (leading and trailing spaces are truncated)
+*/
+QString QtxEvalParser::note( const QString& str, int pos, int len )
+{
+    return str.mid( pos, len ).trimmed();
+}
+
+/*!
+  \brief Prepare to the parsing.
+
+  Performs the first step of the parsing:
+  - find tokens
+  - determine tokens types
+  - create unsorted pseudo-postfix (with brackets)
+
+  \param expr string expression
+  \param post postfix to be created
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::prepare( const QString& expr, Postfix& post )
+{
+  int pos = 0;
+  int len = expr.length();
+  QStack<int> aBracketStack;
+  QStringList anOpers, anOpenBr, aCloseBr;
+  if ( !checkOperations() )
+    return false;
+
+  bracketsList( anOpenBr, true );
+  bracketsList( aCloseBr, false );
+  operationList( anOpers );
+
+  while ( pos < len && error() == QtxEvalExpr::OK )
+  {
+    PostfixItem item;
+    while ( expr[pos].isSpace() && pos < len )
+      pos++;
+    if ( pos >= len )
+      break;
+
+    int mBrLen = 0, mLen = 0, br_ind = -1, op_ind = -1;
+    int oPos = search( anOpenBr, expr, pos, mBrLen, br_ind );
+    int cPos = oPos == pos ? -1 : search( aCloseBr, expr, pos, mBrLen, br_ind );
+    int opPos = search( anOpers, expr, pos, mLen, op_ind );
+
+    if ( expr[pos] == QChar( '\'' ) )
+    {
+      int vpos = pos + 1;
+      while ( vpos < (int)expr.length() && expr[vpos] != QChar( '\'' ) )
+        vpos++;
+
+      mLen = vpos - pos + 1;
+
+      int res = createValue( note( expr, pos, mLen ), item.myValue );
+      item.myType = res ? Value : Param;
+      post.append( item );
+      pos = vpos + 1;
+      continue;
+    }
+
+    if ( oPos == pos )
+    {
+      aBracketStack.push( br_ind );
+      item.myValue = note( expr, pos, mBrLen );
+      item.myType = Open;
+      post.append( item );
+    }
+    else if ( cPos == pos )
+    {
+      if ( aBracketStack.count() == 0 )
+      {
+        setError( QtxEvalExpr::ExcessClose );
+        break;
+      }
+      if ( br_ind != aBracketStack.top() )
+      {
+        setError( QtxEvalExpr::BracketsNotMatch );
+        break;
+      }
+      else
+      {
+        aBracketStack.pop();
+        item.myValue = note( expr, pos, mBrLen );
+        item.myType = Close;
+        post.append( item );
+      }
+    }
+    else
+      mBrLen = 0;
+
+    if ( opPos == pos )
+    {
+      mBrLen = 0;
+      item.myValue = note( expr, pos, mLen );
+      item.myType = Binary;
+
+      if ( oPos == pos )
+        post.insert( post.count() - 1, item );
+      else
+        post.append( item );
+    }
+    else
+    {
+      mLen = 0;
+      if ( oPos != pos && cPos != pos )
+      {
+             int i; 
+        for ( i = pos + 1; i < (int)expr.length(); i++ )
+        {
+          if ( expr[i].isSpace() )
+            break;
+        }
+
+        int vpos = i;
+        if ( oPos >= 0 && oPos < vpos )
+          vpos = oPos;
+        if ( cPos >= 0 && cPos < vpos )
+          vpos = cPos;
+        if ( opPos >= 0 && opPos < vpos )
+          vpos = opPos;
+
+        while( vpos < (int)expr.length() && 
+               ( expr[vpos].isLetter() || expr[vpos].isDigit() || expr[vpos]=='_' ) )
+          vpos++;
+
+        mLen = vpos - pos;
+        bool res = createValue( note( expr, pos, mLen ), item.myValue );
+        item.myType = res ? Value : Param;
+        post.append( item );
+      }
+    }
+
+    pos += mBrLen + mLen;
+  }
+
+  //Bracket checking
+  int brValue = 0;
+  for ( Postfix::iterator anIt = post.begin(); anIt != post.end(); ++anIt )
+  {
+    if ( (*anIt).myType == Open )
+      brValue++;
+    else if ( (*anIt).myType == Close )
+    {
+      if ( brValue > 0 )
+        brValue--;
+      else
+      {
+        setError( QtxEvalExpr::ExcessClose );
+        break;
+      }
+    }
+  }
+
+  if ( brValue > 0 )
+    setError( QtxEvalExpr::CloseExpected );
+
+  return error() == QtxEvalExpr::OK;
+}
+
+/*!
+  \brief Analyze the operations used.
+  
+  Second step of the parsing: analyze the types of the operations used in the expression.
+
+  \param post unsorted postfix
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::setOperationTypes( Postfix& post )
+{
+  if ( !checkOperations() )
+    return false;
+
+  QStringList anOpen, aClose;
+  bracketsList( anOpen, true );
+  bracketsList( aClose, false );
+
+  Postfix::iterator aPrev, aNext;
+  for ( Postfix::iterator anIt = post.begin(); anIt != post.end(); ++anIt )
+  {
+    aPrev = anIt;
+    aPrev--;
+    aNext = anIt;
+    aNext++;
+    if ( (*anIt).myType != Binary )
+      continue;
+
+    if ( ( anIt == post.begin() || (*aPrev).myType == Open ||
+           (*aPrev).myType == Pre || (*aPrev).myType == Binary ) &&  aNext != post.end() &&
+         ( (*aNext).myType == Value || (*aNext).myType == Param ||
+           (*aNext).myType == Open  || (*aNext).myType == Binary ) )
+      (*anIt).myType = Pre;
+    else if ( anIt != post.begin() && ( (*aPrev).myType == Close || (*aPrev).myType == Param ||
+                                        (*aPrev).myType == Value || (*aPrev).myType == Pre ||
+                                        (*aPrev).myType == Post || (*aPrev).myType == Binary ) &&
+              ( aNext == post.end() || (*aNext).myType == Close ) )
+      (*anIt).myType = Post;
+
+    if ( anOpen.contains( (*anIt).myValue.toString() ) )
+      (*anIt).myType = Pre;
+    else if ( aClose.contains( (*anIt).myValue.toString() ) )
+      (*anIt).myType = Post;
+  }
+
+  return error() == QtxEvalExpr::OK;
+}
+
+/*!
+  \brief Get the number of the globar brackets pairs.
+
+  For example, the expression '((2+3))' has 2 global brackets pairs.
+
+  \param post postfix to be checked
+  \param f starting position for the search
+  \param l last position for the search
+  \return number of brackets pairs
+*/
+int QtxEvalParser::globalBrackets( const QtxEvalParser::Postfix& post, int f, int l )
+{
+  int i;
+  int start_br = 0;
+  int fin_br = 0;
+  int br = 0;
+  int br_num = 0;
+  int min_br_num = (l-f+1)*5;
+    
+  for( i=f; i<=l; i++ )
+    if( post[ i ].myType==QtxEvalParser::Open )
+      start_br++;
+    else
+      break;
+  for( i=l; i>=f; i-- )
+    if( post[ i ].myType==QtxEvalParser::Close )
+      fin_br++;
+    else
+      break;
+
+  br = start_br<fin_br ? start_br : fin_br;
+  for( i=f+br; i<=l-br; i++ )
+  {
+    if( post[i].myType==QtxEvalParser::Open )
+      br_num++;
+    else if( post[i].myType==QtxEvalParser::Close )
+      br_num--;
+    if( br_num<min_br_num )
+      min_br_num = br_num;
+  }
+  
+  return br+min_br_num;
+}
+
+/*!
+  \brief Sort the operations in the postfix.
+
+  Third step of parsing: sort the postfix operations in order to convert it to real postfix.
+
+  \param post source postfix
+  \param res returning resulting postfix
+  \param anOpen list of open brackets
+  \param aClose list of close brackets
+  \param f start index of postfix for sorting
+  \param l last index of postfix for sorting
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::sort( const Postfix& post, Postfix& res, const QStringList& anOpen,
+                          const QStringList& aClose, int f, int l )
+{
+  if ( l < f )
+    return true;
+
+  if ( f < 0 )
+    f = 0;
+
+  if ( l < 0 )
+    l = post.count() - 1;
+
+  int br = globalBrackets( post, f, l );
+  f += br;
+  l -= br;
+
+  if ( f == l && f >= 0 )
+    res.append( post[f] );
+
+  if ( l <= f )
+    return true;
+
+  if ( !checkOperations() )
+    return false;
+
+  int min = -1;
+  QIntList argmin;
+  QList<PostfixItemType> min_types;
+
+  for ( int i = 0, j = f; j <= l; i++, j++ )
+  {
+    const PostfixItem& item = post[j];
+    PostfixItemType tt = item.myType;
+    if ( tt == Binary || tt == Pre || tt == Post )
+    {
+      int cur_pr = priority( item.myValue.toString(), tt == Binary );
+      if ( cur_pr > 0 )
+      {
+        if ( min < 0 || min >= cur_pr )
+        {
+          if ( min == cur_pr )
+          {
+            argmin.append( f + i );
+            min_types.append( tt );
+          }
+          else
+          {
+            min = cur_pr;
+            argmin.clear();
+            argmin.append( f + i );
+            min_types.clear(); min_types.append( tt );
+          }
+        }
+      }
+      else
+      {
+        setError( QtxEvalExpr::InvalidOperation );
+        break;
+      }
+    }
+    else if ( tt == Open )
+    {
+      QString opBr = item.myValue.toString();
+      int ind = anOpen.indexOf( opBr ), brValue = 0;
+      while ( j <= l )
+      {
+        const PostfixItem& anItem = post[j];
+        if ( anItem.myType == Open )
+          brValue++;
+
+        if ( anItem.myType == Close )
+        {
+          brValue--;
+          QString clBr = anItem.myValue.toString();
+          if ( aClose.indexOf( clBr ) == ind && brValue == 0 )
+            break;
+        }
+        i++; j++;
+      }
+
+      if ( brValue > 0 )
+      {
+        setError( QtxEvalExpr::CloseExpected );
+          break;
+      }
+    }
+  }
+
+  if ( error() == QtxEvalExpr::OK )
+  {
+    if ( min >= 0 )
+    {
+      Postfix one;
+      QList<Postfix> parts;
+      QIntList::const_iterator anIt = argmin.begin(), aLast = argmin.end();
+      bool ok = sort( post, one, anOpen, aClose, f, *anIt - 1 );
+      parts.append( one );
+      one.clear();
+      for ( ; anIt != aLast && ok; anIt++ )
+      {
+        QIntList::const_iterator aNext = anIt; aNext++;
+        ok = sort( post, one, anOpen, aClose, *anIt + 1, aNext == aLast ? l : *aNext - 1 );
+        parts.append( one );
+        one.clear();
+      }
+
+      if ( !ok )
+        return false;
+
+      QStack<PostfixItem> aStack;
+      QList<Postfix>::const_iterator aPIt = parts.begin();
+      QList<PostfixItemType>::const_iterator aTIt = min_types.begin();
+      res += (*aPIt);
+      aPIt++;
+      anIt = argmin.begin();
+      for ( ; anIt != aLast; anIt++, aPIt++, aTIt++ )
+      {
+        if ( *aTIt == Pre )
+        {
+          if ( anOpen.contains( post[*anIt].myValue.toString() ) == 0 )
+          {
+            res += (*aPIt);
+            aStack.push( post[ *anIt ] );
+          }
+          else
+          {
+            res.append( post[*anIt] );
+            res += *aPIt;
+          }
+        }
+        else
+        {
+          res += *aPIt;
+          while ( !aStack.isEmpty() )
+          {
+            res.append( aStack.top() );
+            aStack.pop();
+          }
+          res.append( post[*anIt] );
+        }
+      }
+      while ( !aStack.isEmpty() )
+      {
+        res.append( aStack.top() );
+        aStack.pop();
+      }
+    }
+    else
+    { //there are no operations
+      for ( int k = f; k <= l; k++ )
+      {
+        if ( post.at( k ).myType==Value || post.at( k ).myType == Param )
+          res.append( post.at( k ) );
+      }
+    }
+  }
+
+  return error() == QtxEvalExpr::OK;
+}
+
+/*!
+  \brief Parse the expression and build the posfix.
+
+  If by parsing error is found, the function returns \c false. In this case the code of the error
+  can be retrieved with error() method.
+
+  \param expr string expression
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::parse( const QString& expr )
+{
+  myPostfix.clear();
+
+  if ( !checkOperations() )
+    return false;
+
+  Postfix p;
+  QStringList opens, closes;
+
+  setError( QtxEvalExpr::OK );
+  bracketsList( opens, true );
+  bracketsList( closes, false );
+
+  return prepare( expr, p ) && setOperationTypes( p ) && sort( p, myPostfix, opens, closes );
+}
+
+/*!
+  \brief Calculate the operation.
+
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::calculate( const QString& op, QVariant& v1, QVariant& v2 )
+{
+  QtxEvalExpr::Error err = isValid( op, v1.type(), v2.type() );
+  if ( err == QtxEvalExpr::OK )
+    setError( calculation( op, v1, v2 ) );
+  else
+    setError( err );
+
+  return error() == QtxEvalExpr::OK;
+}
+
+/*!
+  \brief Calculate the expression without postfix rebuilding.
+  \return QVariant as result (it is invalid if there were errors during calculation)
+*/
+QVariant QtxEvalParser::calculate()
+{
+  if ( !checkOperations() )
+    return QVariant();
+
+  setError( QtxEvalExpr::OK );
+
+  QStringList anOpen, aClose;
+  bracketsList( anOpen, true );
+  bracketsList( aClose, false );
+
+  QStack<QVariant> aStack;
+  Postfix::iterator anIt = myPostfix.begin(), aLast = myPostfix.end();
+  for ( ; anIt != aLast && error() == QtxEvalExpr::OK; anIt++ )
+  {
+    QString nn = (*anIt).myValue.toString();
+    if ( (*anIt).myType == Param )
+    {
+      if ( hasParameter( nn ) )
+      {
+        QVariant& v = myParams[nn];
+        if ( v.isValid() )
+          aStack.push( v );
+        else
+          setError( QtxEvalExpr::InvalidToken );
+      }
+      else
+        setError( QtxEvalExpr::InvalidToken );
+    }
+    else if ( (*anIt).myType == Value )
+      aStack.push( (*anIt).myValue );
+    else if ( (*anIt).myType == Pre || (*anIt).myType == Post )
+    {
+      if ( anOpen.contains( nn ) )
+      {
+        QVariant inv;
+        if ( calculate( nn, inv, inv ) )
+          aStack.push( QVariant() );
+      }
+      else if ( aClose.contains( nn ) )
+      {
+        QList<QVariant> set;
+        while ( true )
+        {
+          if ( aStack.isEmpty() )
+          {
+            setError( QtxEvalExpr::StackUnderflow );
+            break;
+          }
+          if ( aStack.top().isValid() )
+          {
+            set.append( aStack.top() );
+            aStack.pop();
+          }
+          else
+          {
+            aStack.pop();
+            break;
+          }
+        }
+
+        QVariant qSet = set, inv;
+        if ( calculate( nn, qSet, inv ) )
+          aStack.push( set );
+      }
+      else if ( aStack.count() >= 1 )
+      {
+        QVariant inv;
+        QVariant* v1 = &aStack.top(), *v2 = &inv; //"post-" case
+        if ( (*anIt).myType == Pre )
+        {
+          v2 = &aStack.top();
+          v1 = &inv;
+        }
+        calculate( nn, *v1, *v2 );
+      }
+      else
+        setError( QtxEvalExpr::StackUnderflow );
+    }
+    else if ( (*anIt).myType == Binary )
+    {
+      if ( aStack.count() >= 2 )
+      {
+        QVariant v2 = aStack.top();
+        aStack.pop();
+        calculate( nn, aStack.top(), v2 );
+      }
+      else
+        setError( QtxEvalExpr::StackUnderflow );
+    }
+  }
+
+  QVariant res;
+  if ( error() == QtxEvalExpr::OK )
+  {
+    int count = aStack.count();
+    if ( count == 0 )
+      setError( QtxEvalExpr::StackUnderflow );
+    else if( count == 1 )
+      res = aStack.top();
+    else
+      setError( QtxEvalExpr::ExcessData );
+  }
+  return res;
+}
+
+/*!
+  \brief Change the expression, rebuild the postfix and calculate it.
+  \param expr new expression
+  \return QVariant as result (it is invalid if there were errors during calculation)
+*/
+QVariant QtxEvalParser::calculate( const QString& expr )
+{
+  setExpression( expr );
+  return calculate();
+}
+
+/*!
+  \brief Change the expression and rebuild the postfix.
+  \param expr new expression
+  \return \c true on success and \c false if error is found
+*/
+bool QtxEvalParser::setExpression( const QString& expr )
+{
+  return parse( expr );
+}
+
+/*!
+  \brief Check if the parser contains specified parameter.
+  \param name parameter name
+  \return \c true, if the parser contains parameter
+*/
+bool QtxEvalParser::hasParameter( const QString& name ) const
+{
+  return myParams.contains( name.trimmed() );
+}
+
+/*!
+  \brief Set parameters value.
+  \param name parameter name
+  \param value parameter value
+*/
+void QtxEvalParser::setParameter( const QString& name, const QVariant& value )
+{
+  myParams.insert( name.trimmed(), value );
+}
+
+/*!
+  \brief Remove parameter.
+  \param name parameter name
+  \return \c true on success
+*/
+bool QtxEvalParser::removeParameter( const QString& name )
+{
+  return myParams.remove( name.trimmed() );
+}
+
+/*!
+  \brief Get the parameter value.
+  \param name parameter name
+  \return parameter value or invalud QVariant if there is no such parameter
+*/
+QVariant QtxEvalParser::parameter( const QString& name ) const
+{
+  QVariant res;
+  if ( myParams.contains( name.trimmed() ) )
+    res = myParams[name.trimmed()].toString();
+  return res;
+}
+
+/*!
+  \brief Search first parameter with assigned invalid value.
+  \param name used to retrieve the name of the parameter if it is found
+  \return \c true if parameter is found
+*/
+bool QtxEvalParser::firstInvalid( QString& name ) const
+{
+  for ( ParamMap::const_iterator anIt = myParams.begin(); anIt != myParams.end(); anIt++ )
+  {
+    if ( !anIt.value().isValid() )
+    {
+      name = anIt.key();
+      return true;
+    }
+  }
+  return false;
+}
+
+/*!
+  \brief Remove all parameters with assigned invalid values.
+*/
+void QtxEvalParser::removeInvalids()
+{
+  QStringList toDelete;
+  for ( ParamMap::const_iterator anIt = myParams.begin(); anIt != myParams.end(); anIt++ )
+  {
+    if ( !anIt.value().isValid() )
+      toDelete.append( anIt.key() );
+  }
+
+  for ( QStringList::const_iterator aLIt = toDelete.begin(); aLIt != toDelete.end(); aLIt++ )
+    myParams.remove( *aLIt );
+}
+
+/*!
+  \brief Get the code of the latest parsing error.
+  \return last error code
+*/
+QtxEvalExpr::Error QtxEvalParser::error() const
+{
+  return myError;
+}
+
+/*!
+  \brief Set the error vode.
+  \internal
+  \param err error code
+*/
+void QtxEvalParser::setError( QtxEvalExpr::Error err )
+{
+  myError = err;
+}
+
+/*!
+  \brief Dump the current postfix contents to the string.
+  \return string representation of the internal parser postfix
+*/
+QString QtxEvalParser::dump() const
+{
+  return dump( myPostfix );
+}
+
+/*!
+  \brief Dump the postfix contents to the string.
+  \param post postfix to be dumped
+  \return string representation of the postfix
+*/
+QString QtxEvalParser::dump( const Postfix& post ) const
+{
+  QString res;
+
+  if ( !checkOperations() )
+    return res;
+
+  for ( Postfix::const_iterator anIt = post.begin(); anIt != post.end(); anIt++ )
+  {
+    if ( (*anIt).myType == Value && (*anIt).myValue.type() == QVariant::String )
+      res += "'" + (*anIt).myValue.toString() + "'";
+    else
+      res += (*anIt).myValue.toString();
+    
+    if ( (*anIt).myType == Pre )
+      res += "(pre)";
+    else if ( (*anIt).myType == Post )
+      res += "(post)";
+    else if ( (*anIt).myType == Binary )
+      res += "(bin)";
+
+    res += "_";
+  }
+
+  return res;
+}
+
+/*!
+  \brief Get the list of the parameters names.
+  \return parameters names
+*/
+QStringList QtxEvalParser::parameters() const
+{
+  QStringList lst;
+  for ( Postfix::const_iterator anIt = myPostfix.begin(); anIt != myPostfix.end(); anIt++ )
+  {
+    if ( (*anIt).myType == Param )
+    {
+      QString name = (*anIt).myValue.toString();
+      if ( !lst.contains( name ) )
+        lst.append( name );
+    }
+  }
+  return lst;
+}
+
+/*!
+  \brief Remove all parameters.
+*/
+void QtxEvalParser::clearParameters()
+{
+  myParams.clear();
+}
+
+/*!
+  \brief Get the string representation for the list of QVariant values.
+  \param list list to be converted
+  \return string representation for the list
+*/
+QString QtxEvalParser::toString( const QList<QVariant>& list )
+{
+  QString res = "set : [ ";
+  for ( QList<QVariant>::const_iterator anIt = list.begin(); anIt != list.end(); anIt++ )
+    res += (*anIt).toString() + " ";
+  res += "]";
+  return res;
+}
+
+/*!
+  \brief Get names of all operations used in the expression.
+  \param list returning list of the operations names
+*/
+void QtxEvalParser::operationList( QStringList& list ) const
+{
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
+  {
+    QStringList custom;
+    QtxEvalSet* set = *it;
+    set->operationList( custom );
+    for ( QStringList::const_iterator sIt = custom.begin(); sIt != custom.end(); ++sIt )
+    {
+      if ( !list.contains( *sIt ) )
+        list.append( *sIt );
+    }
+  }
+}
+
+/*!
+  \brief Get list of brackets.
+  \param list returning list of brackets
+  \param open if \c true, collect opening brackets, or closing brackets otherwise
+*/
+void QtxEvalParser::bracketsList( QStringList& list, bool open ) const
+{
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
+  {
+    QStringList custom;
+    QtxEvalSet* set = *it;
+    set->bracketsList( custom, open );
+    for ( QStringList::const_iterator sIt = custom.begin(); sIt != custom.end(); ++sIt )
+    {
+      if ( !list.contains( *sIt ) )
+        list.append( *sIt );
+    }
+  }
+}
+
+/*!
+  \brief Create value.
+  \param str parsed string
+  \param val returning value
+  \return \c true on success
+*/
+bool QtxEvalParser::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = false;
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && !ok; ++it )
+    ok = (*it)->createValue( str, val );
+  return ok;
+}
+
+/*!
+  \brief Get the operation priority level.
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalParser::priority( const QString& op, bool isBin ) const
+{
+  int i = 0;
+  int priority = 0;
+  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;
+}
+
+/*!
+  \brief Check operation validity.
+
+  If the operation is valid, QtxEvalExpr::OK is returned.
+
+  \param op operation
+  \param t1 first operand type
+  \param t2 second operand type
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalParser::isValid( const QString& op,
+                                           const QVariant::Type t1, const QVariant::Type t2 ) const
+{
+  QtxEvalExpr::Error err = QtxEvalExpr::OK;
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
+  {
+    err = (*it)->isValid( op, t1, t2 );
+    if ( err == QtxEvalExpr::OK )
+      break;
+  }
+  return err;
+}
+
+/*!
+  \brief Perform calculation
+  
+  The result of the operation is returned in the parameter \a v1.
+  If the operation is calculated correctly, the function returns QtxEvalExpr::OK.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalParser::calculation( const QString& op, QVariant& v1, QVariant& v2 ) const
+{
+  QVariant nv1, nv2;
+  for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
+  {
+    nv1 = v1;
+    nv2 = v2;
+    if ( (*it)->isValid( op, v1.type(), v2.type() ) == QtxEvalExpr::OK )
+    {
+      QtxEvalExpr::Error err = (*it)->calculate( op, nv1, nv2 );
+      if ( err == QtxEvalExpr::OK || err == QtxEvalExpr::InvalidResult )
+      {
+        v1 = nv1;
+        v2 = nv2;
+        return err;
+      }
+    }
+  }
+  return QtxEvalExpr::InvalidOperation;
+}
+
+/*!
+  \brief Check current operations set.
+  \return \c false if current set of operations is empty
+*/
+bool QtxEvalParser::checkOperations() const
+{
+  if ( !mySets.isEmpty() )
+    return true;
+
+  QtxEvalParser* that = (QtxEvalParser*)this;
+  that->setError( QtxEvalExpr::OperationsNull );
+  return false;
+}
+
+/*!
+  \class QtxEvalSet
+  \brief Generic class for all the operations sets used in expressions.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSet::QtxEvalSet()
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSet::~QtxEvalSet()
+{
+}
+
+/*!
+  \fn void QtxEvalSet::operationList( QStringList& list ) const;
+  \brief Get the list of possible operations.
+  \param list returning list of operations supported by the class
+*/
+
+/*!
+  \fn void QtxEvalSet::bracketsList( QStringList& list, bool open ) const;
+  \brief Get list of brackets.
+  \param list returning list of brackets
+  \param open if \c true, collect opening brackets, or closing brackets otherwise
+*/
+
+/*!
+  \brief Create value from its string representation.
+
+  By default, the string value is set, that corresponds to the parameter.
+  Base implementation always returns \c false (it means that string 
+  is evaluated to the parameter).
+  Successor class can re-implement this method to return \c true 
+  if the argument being parsed can be evaluated as custom value.
+
+  \param str string representration of the value
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSet::createValue( const QString& str, QVariant& val ) const
+{
+  val = str;
+  return false;
+}
+
+/*!
+  \fn int QtxEvalSet::priority( const QString& op, bool isBin ) const;
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function should return value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+
+/*!
+  \fn QtxEvalExpr::Error QtxEvalSet::isValid( const QString& op, const QVariant::Type t1, 
+                                              const QVariant::Type t2 ) const;
+  \brief Check operation validity.
+
+  If the operation is valid, QtxEvalExpr::OK is returned.
+  If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
+  or QtxEvalExpr::InvalidOperation.
+
+  \param op operation
+  \param t1 first operand type
+  \param t2 second operand type
+  \return error code (QtxEvalExpr::Error)
+*/
+
+/*!
+  \fn QtxEvalExpr::Error QtxEvalSet::calculate( const QString& op, QVariant& v1,
+                                                QVariant& v2 ) const;
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+
+/*!
+  \fn QString QtxEvalSet::name() const;
+  \brief Get unique operations set name.
+
+  Should be redefined in the successor classes.
+
+  \return operations set name
+*/
+
+/*!
+  \class QtxEvalSetBase
+  \brief Generic class. Provides functionality for standard operations sets.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetBase::QtxEvalSetBase()
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetBase::~QtxEvalSetBase()
+{
+}
+
+/*!
+  \brief Get list of brackets.
+  \param list returning list of brackets
+  \param open if \c true, collect opening brackets, or closing brackets otherwise
+*/
+void QtxEvalSetBase::bracketsList( QStringList& list, bool open ) const
+{
+  list.append( open ? "(" : ")" );
+}
+
+/*!
+  \brief Get the list of possible operations.
+  \param list returning list of operations supported by the class
+*/
+void QtxEvalSetBase::operationList( QStringList& list ) const
+{
+  list += myOpers;
+}
+
+/*!
+  \brief Add operation names to the internal list of operations.
+  \param list operations to be added
+*/
+void QtxEvalSetBase::addOperations( const QStringList& list )
+{
+  for ( QStringList::const_iterator anIt = list.begin(); anIt != list.end(); ++anIt )
+  {
+    if ( !myOpers.contains( *anIt ) )
+      myOpers.append( *anIt );
+  }
+}
+
+/*!
+  \brief Add operand types.
+  \param list operand types to be added
+*/
+void QtxEvalSetBase::addTypes( const ListOfTypes& list )
+{
+  for ( ListOfTypes::const_iterator anIt = list.begin(); anIt != list.end(); ++anIt )
+  {
+    if ( !myTypes.contains( *anIt ) )
+      myTypes.append( *anIt );
+  }
+}
+
+/*!
+  \brief Check operation validity.
+
+  If the operation is valid, QtxEvalExpr::OK is returned.
+  If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
+  or QtxEvalExpr::InvalidOperation.
+
+  \param op operation
+  \param t1 first operand type
+  \param t2 second operand type
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetBase::isValid( const QString& op,
+                                            const QVariant::Type t1, const QVariant::Type t2 ) const
+{
+  if ( ( t1 == QVariant::Invalid || myTypes.contains( t1 ) ) &&
+       ( t2 == QVariant::Invalid || myTypes.contains( t2 ) ) &&
+       ( t1 != QVariant::Invalid || t2 != QVariant::Invalid ) )
+  {
+    if ( priority( op, t1 != QVariant::Invalid && t2 != QVariant::Invalid ) > 0 )
+      return QtxEvalExpr::OK;
+    else
+      return QtxEvalExpr::InvalidOperation;
+  }
+  else
+    return QtxEvalExpr::OperandsNotMatch;
+}
+
+/*!
+  \class QtxEvalSetArithmetic
+  \brief Provides set of arithmetical operations for the parser.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetArithmetic::QtxEvalSetArithmetic()
+: QtxEvalSetBase()
+{
+  addOperations( QString( "+;-;*;/;=;<;>;<=;>=;<>;!=" ).split( ";" ) );
+
+  ListOfTypes aTypes;
+  aTypes.append( QVariant::Int );
+  aTypes.append( QVariant::UInt );
+  aTypes.append( QVariant::Double );
+  addTypes( aTypes );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetArithmetic::~QtxEvalSetArithmetic()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetArithmetic::Name()
+{
+  return "Arithmetic";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetArithmetic::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Create value from its string representation.
+
+  Creates numbers from string representation.
+
+  \param str string representration of the value
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSetArithmetic::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = false;
+  val = str.toInt( &ok );
+
+  if ( !ok )
+  {
+    val = str.toDouble( &ok );
+    if ( !ok )
+      ok = QtxEvalSetBase::createValue( str, val );
+  }
+  return ok;
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalSetArithmetic::priority( const QString& op, bool isBin ) const
+{
+  if ( isBin )
+  {
+    if ( op == "<" || op == ">" || op == "=" ||
+         op == "<=" || op == ">=" || op == "<>" || op == "!=" )
+      return 1;
+    else if ( op == "+" || op == "-" )
+      return 2;
+    else if( op == "*" || op == "/" )
+      return 3;
+    else
+      return 0;
+  }
+  else if ( op == "+" || op == "-" )
+    return 5;
+  else
+    return 0;
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetArithmetic::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
+{
+  QtxEvalExpr::Error err = QtxEvalExpr::OK;
+
+  if ( v1.isValid() && v2.isValid() )
+  {
+    // binary operations
+    if ( ( v1.type() == QVariant::Int || v1.type() == QVariant::UInt ) &&
+         ( v2.type() == QVariant::Int || v2.type() == QVariant::UInt ) )
+    {
+      int _v1 = v1.toInt();
+      int _v2 = v2.toInt();
+
+      if ( op == "+" )
+        v1 = _v1 + _v2;
+      else if ( op == "-" )
+        v1 = _v1 - _v2;
+      else if ( op == "*" )
+        v1 = _v1 * _v2;
+      else if ( op == "/" )
+      {
+        if ( _v2 != 0 )
+        {
+          if ( _v1 % _v2 == 0 )
+            v1 = _v1 / _v2;
+          else
+            v1 = double( _v1 ) / double( _v2 );
+        }
+        else
+          err = QtxEvalExpr::InvalidResult;
+      }
+      else if ( op == "<" )
+        v1 = _v1 < _v2;
+      else if ( op == ">" )
+        v1 = _v1 > _v2;
+      else if ( op == "=" )
+        v1 = _v1 == _v2;
+      else if ( op == "<=" )
+        v1 = _v1 <= _v2;
+      else if ( op == ">=" )
+        v1 = _v1 >= _v2;
+      else if ( op == "<>" || op == "!=" )
+        v1 = _v1 != _v2;
+    }
+    else if ( ( v1.type() == QVariant::Int || v1.type() == QVariant::Double ) &&
+              ( v2.type() == QVariant::Int || v2.type() == QVariant::Double ) )
+    {
+      double _v1 = v1.toDouble();
+      double _v2 = v2.toDouble();
+
+      if ( op == "+" )
+        v1 = _v1 + _v2;
+      else if ( op == "-" )
+        v1 = _v1 - _v2;
+      else if ( op == "*" )
+          v1 = _v1 * _v2;
+      else if ( op == "/" )
+      {
+        if ( _v2 != 0 )
+          v1 = _v1 / _v2;
+        else
+          err = QtxEvalExpr::InvalidResult;
+      }
+      else if ( op == "<" )
+        v1 = _v1 < _v2;
+      else if ( op == ">" )
+        v1 = _v1 > _v2;
+      else if ( op == "=" )
+        v1 = _v1 == _v2;
+      else if ( op == "<=" )
+        v1 = _v1 <= _v2;
+      else if ( op == ">=" )
+        v1 = _v1 >= _v2;
+      else if ( op == "<>" || op == "!=" )
+        v1 = _v1 != _v2;
+    }
+    else // prefix operations
+    {
+      if ( op == "-" )
+      {
+        if ( v2.type() == QVariant::Int )
+          v2 = -v2.toInt();
+        else if ( v2.type() == QVariant::Double )
+          v2 = -v2.toDouble();
+      }
+    }
+  }
+
+  return err;
+}
+
+/*!
+  \class QtxEvalSetLogic
+  \brief Provides set of logical operations for the parser.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetLogic::QtxEvalSetLogic()
+: QtxEvalSetBase()
+{
+  addOperations( QString( "and;&&;or;||;xor;not;!;imp;=" ).split( ";" ) );
+
+  ListOfTypes aTypes;
+  aTypes.append( QVariant::Bool );
+  aTypes.append( QVariant::Int );
+  aTypes.append( QVariant::UInt );
+  addTypes( aTypes );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetLogic::~QtxEvalSetLogic()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetLogic::Name()
+{
+  return "Logic";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetLogic::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Create value from its string representation.
+
+  Create \c true or \c false value from string representation.
+
+  \param str string representration of the value
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSetLogic::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = true;
+  QString valStr = str.toLower();
+  if ( valStr == "true" || valStr == "yes" )
+    val = QVariant( true );
+  else if ( valStr == "false" || valStr == "no" )
+    val = QVariant( false );
+  else
+    ok = QtxEvalSetBase::createValue( str, val );
+
+  return ok;
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalSetLogic::priority( const QString& op, bool isBin ) const
+{
+  if ( isBin )
+  {
+    if ( op == "and" || op == "or" || op == "xor" || op == "&&" || op == "||" || op == "imp" )
+      return 1;
+    else if ( op == "=" )
+      return 2;
+    else 
+      return 0;
+  }
+  else if ( op == "not" || op == "!" )
+    return 5;
+  else
+    return 0;
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+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 );
+  if ( v1.isValid() && v2.isValid() )
+  {
+    if ( op == "and" || op == "&&" )
+      v1 = val1 && val2;
+    else if ( op == "or" || op == "||" )
+      v1 = val1 || val2;
+    else if ( op == "xor" )
+      v1 = ( !val1 && val2 ) || ( val1 && !val2 );
+    else if ( op == "imp" )
+      v1 = !val1 || val2;
+    else if ( op == "=" )
+      v1 = val1 == val2;
+  }
+  else if ( op == "not" || op == "!" )
+    v2 = !val2;
+
+  return err;
+}
+
+/*!
+  \brief Convert value to the boolean.
+  \param v value being converted
+  \return converted value
+*/
+bool QtxEvalSetLogic::booleanValue( const QVariant& v ) const
+{
+  bool res = false;
+  switch ( v.type() )
+  {
+  case QVariant::Bool:
+    res = v.toBool();
+    break;
+  case QVariant::Int:
+    res = v.toInt() != 0;
+    break;
+  case QVariant::UInt:
+    res = v.toUInt() != 0;
+    break;
+  default:
+    res = false;
+    break;
+  }
+  return res;
+}
+
+/*!
+  \class QtxEvalSetMath
+  \brief Provides a set of more complex operations (mathematical functions)
+         for the parser (sqrt, sin, cos, etc).
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetMath::QtxEvalSetMath()
+: QtxEvalSetBase()
+{
+  addOperations( QString( "sqrt;abs;sin;cos;rad2grad;grad2rad" ).split( ";" ) );
+
+  ListOfTypes aTypes;
+  aTypes.append( QVariant::Int );
+  aTypes.append( QVariant::Double );
+  addTypes( aTypes );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetMath::~QtxEvalSetMath()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetMath::Name()
+{
+  return "Math";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetMath::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Create value from its string representation.
+
+  Creates numbers from string representation.
+
+  \param str string representration of the value
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSetMath::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = false;
+  val = str.toInt( &ok );
+
+  if ( !ok )
+  {
+    val = str.toDouble( &ok );
+    if ( !ok )
+      ok = QtxEvalSetBase::createValue( str, val );
+  }
+  return ok;
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalSetMath::priority( const QString& op, bool isBin ) const
+{
+  if ( isBin )
+    return 0;
+  else if ( op == "sqrt" || op == "abs" || op == "sin" ||
+            op == "cos" || op == "rad2grad" || op == "grad2rad" )
+    return 1;
+  else
+    return 0;
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetMath::calculate( const QString& op, QVariant&, QVariant& v2 ) const
+{
+  QtxEvalExpr::Error err = QtxEvalExpr::OK;
+  double val = v2.toDouble();
+  if ( op == "sqrt" )
+  {
+    if ( val >= 0 )
+      v2 = sqrt( val );
+    else
+      err = QtxEvalExpr::InvalidResult;
+  }
+  else if ( op == "abs" )
+  {
+    if ( v2.type() == QVariant::Int )
+      v2 = abs( v2.toInt() );
+    else 
+      v2 = fabs( v2.toDouble() );
+  }
+  else if ( op == "sin" )
+    v2 = sin( val );
+  else if ( op == "cos" )
+    v2 = cos( val );
+  else if ( op == "grad2rad" )
+    v2 = val * 3.14159256 / 180.0;
+  else if ( op == "rad2grad" )
+    v2 = val * 180.0 / 3.14159256;
+
+  return err;
+}
+
+/*!
+  \class QtxEvalSetString
+  \brief Provides set of string operations for the parser.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetString::QtxEvalSetString()
+: QtxEvalSetBase()
+{
+  addOperations( QString( "+;=;<;>;<=;>=;<>;!=;length;lower;upper" ).split( ";" ) );
+
+  ListOfTypes aTypes;
+  aTypes.append( QVariant::Int );
+  aTypes.append( QVariant::Double );
+  aTypes.append( QVariant::String );
+  addTypes( aTypes );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetString::~QtxEvalSetString()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetString::Name()
+{
+  return "String";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetString::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Create value from its string representation.
+
+  Creates string value from Qt string representation.
+
+  \param str string representration of the value
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSetString::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = false;
+  if ( str.length() > 1 && str[0] == '\'' && str[str.length() - 1] == '\'' )
+  {
+    val = str.mid( 1, str.length() - 2 );
+    ok = true;
+  }
+  else
+    ok = QtxEvalSetBase::createValue( str, val );
+  return ok;
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalSetString::priority( const QString& op, bool isBin ) const
+{
+  if ( isBin )
+  {
+    if ( op == "+" ) 
+      return 2;
+    else if ( op == "=" || op == "<" || op == ">" ||
+              op == "<=" || op == ">=" || op == "<>" || op == "!=" )
+      return 1;
+    else
+      return 0;
+  }
+  else if ( op == "length" || op == "lower" || op=="upper" )
+    return 5;
+  else
+    return 0;
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetString::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
+{
+  QtxEvalExpr::Error err = QtxEvalExpr::OK;
+  if ( v1.isValid() && v2.isValid() )
+  {
+    QString _v1 = v1.toString();
+    QString _v2 = v2.toString();
+    if ( op == "+" )
+      v1 = _v1 + _v2;
+    else if ( op == "=" )
+      v1 = _v1 ==_v2;
+    else if ( op == "<" )
+      v1 = _v1 < _v2;
+    else if ( op == ">" )
+      v1 = _v1 > _v2;
+    else if ( op == "<>" || op == "!=" )
+      v1 = _v1 != _v2;
+    else if ( op == "<=" )
+      v1 = _v1 < _v2 || _v1 == _v2;
+    else if ( op == ">=" )
+      v1 = _v1 > _v2 || _v1 == _v2;
+  }
+  else if ( !v1.isValid() && v2.isValid() )
+  {
+    QString val = v2.toString();
+    if ( op == "length" )
+      v2 = (int)val.length();
+    else if ( op == "lower" )
+      v2 = val.toLower();
+    else if ( op == "upper" )
+      v2 = val.toUpper();
+  }
+  return err;
+}
+
+/*!
+  \class QtxEvalSetSets
+  \brief Provides set of operations with sequences for the parser.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxEvalSetSets::QtxEvalSetSets()
+: QtxEvalSetBase()
+{
+  addOperations( QString( "{;};=;<>;!=;+;-;*;in;count" ).split( ";" ) );
+
+  ListOfTypes aTypes;
+  aTypes.append( QVariant::List );
+  addTypes( aTypes );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetSets::~QtxEvalSetSets()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetSets::Name()
+{
+  return "Sets";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetSets::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Get list of brackets.
+  \param list returning list of brackets
+  \param open if \c true, collect opening brackets, or closing brackets otherwise
+*/
+void QtxEvalSetSets::bracketsList( QStringList& list, bool open ) const
+{
+  list.append( open ? "{" : "}" );
+  QtxEvalSetBase::bracketsList( list, open );
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation
+  \param isBin \c true if the operation is binary and \c false if it is unary
+  \return operation priority
+*/
+int QtxEvalSetSets::priority( const QString& op, bool isBin ) const
+{
+  if ( isBin )
+  {
+    if ( op == "=" || op == "<>" || op == "!=" )
+      return 1;
+    else if ( op == "+" || op == "-" || op == "*" )
+      return 2;
+    else if ( op == "in" )
+      return 3;
+    else
+      return 0;
+  }
+  else if ( op == "{" || op == "}" )
+    return 5;
+  else if ( op == "count" )
+    return 4;
+  else
+    return 0;
+}
+
+/*!
+  \brief Check operation validity.
+
+  If the operation is valid, QtxEvalExpr::OK is returned.
+  If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
+  or QtxEvalExpr::InvalidOperation.
+
+  \param op operation
+  \param t1 first operand type
+  \param t2 second operand type
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetSets::isValid( const QString& op,
+                                            const QVariant::Type t1, const QVariant::Type t2 ) const
+{
+  if ( op == "{" )
+    return QtxEvalExpr::OK;
+
+  if ( op != "in" )
+    return QtxEvalSetBase::isValid( op, t1, t2 );
+
+  if ( t1 != QVariant::Invalid && t2 == QVariant::List )
+    return QtxEvalExpr::OK;
+  else
+    return QtxEvalExpr::OperandsNotMatch;
+}
+
+/*!
+  \brief Add new value \a v to the sequence \a set.
+  \param set sequence
+  \param v value to be added
+*/
+void QtxEvalSetSets::add( ValueSet& set, const QVariant& v )
+{
+  if ( v.isValid() && !set.contains( v ) )
+    set.append( v );
+}
+
+/*!
+  \brief Add all values from sequence \a s2 to the sequence \a s1.
+  \param s1 destination sequence
+  \param s2 source sequence
+*/
+void QtxEvalSetSets::add( ValueSet& s1, const ValueSet& s2 )
+{
+  for ( ValueSet::const_iterator anIt = s2.begin(); anIt != s2.end(); ++anIt )
+    add( s1, *anIt );
+}
+
+/*!
+  \brief Remove value \a v from sequence \a set.
+  \param set sequence
+  \param v value to be removed
+*/
+void QtxEvalSetSets::remove( ValueSet& set, const QVariant& v )
+{
+  set.removeAll( v );
+}
+
+/*!
+  \brief Remove all values listed in the sequence \a s2 from the sequence \a s1.
+  \param s1 sequence from which items are removed
+  \param s2 sequence which items are removed
+*/
+void QtxEvalSetSets::remove( ValueSet& s1, const ValueSet& s2 )
+{
+  for ( ValueSet::const_iterator anIt = s2.begin(); anIt != s2.end(); ++anIt )
+    s1.removeAll( *anIt );
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Process binary operation with values \a v1 and \a v2.
+  For unary operation the \v2 is invalid.
+  The result of the operation is returned in the parameter \a v1.
+
+  \param op operation name
+  \param v1 first argument (not valid for unary prefix operations)
+  \param v2 second argument (not valid for unary postfix operations)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetSets::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
+{
+  QtxEvalExpr::Error err = QtxEvalExpr::OK;
+
+  if ( op != "{" )
+  {
+    if ( op == "}" )
+    {
+      ValueSet aNewList;
+      add( aNewList, v1.toList() );
+      v1 = aNewList;
+    }
+    else if ( op == "=" || op == "<>" || op == "!=" || op == "+" || op == "-" || op == "*" )
+    {
+      ValueSet aNewList;
+      add( aNewList, v1.toList() );
+      if ( op == "=" || op == "<>" || op == "!=" || op == "-" )
+      {
+        remove( aNewList, v2.toList() );
+        if ( op == "=" )
+          v1 = aNewList.isEmpty() && v1.toList().count() == v2.toList().count();
+        else if ( op == "<>" || op == "!=" )
+          v1 = !aNewList.isEmpty() || v1.toList().count() != v2.toList().count();
+        else
+          v1 = aNewList;
+      }
+      else if ( op == "+" )
+      {
+        add( aNewList, v2.toList() );
+        v1 = aNewList;
+      }
+      else if ( op == "*" )
+      {
+        ValueSet toDelete;
+        add( toDelete, aNewList );
+        remove( toDelete, v2.toList() );
+        remove( aNewList, toDelete );
+        v1 = aNewList;
+      }
+    }
+    else if ( op== "count" )
+      v2 = (int)v2.toList().count();
+    else if ( op == "in" )
+    {
+      if ( v1.type() == QVariant::List )
+      {
+        bool res = true;
+        ValueSet lst1 = v1.toList();
+        ValueSet lst2 = v2.toList();
+        for ( ValueSet::const_iterator anIt = lst1.begin(); anIt != lst1.end() && res; ++anIt )
+          res = lst2.contains( *anIt );
+
+        v1 = res;
+      }
+      else
+             v1 = QVariant( v2.toList().contains( v1 ) );
+    }
+  }
+  return err;
+}
+
+/*!
+  \class QtxEvalSetConst
+  \brief Provides different standard constants.
+*/
+QtxEvalSetConst::QtxEvalSetConst()
+: QtxEvalSet()
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxEvalSetConst::~QtxEvalSetConst()
+{
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetConst::Name()
+{
+  return "Const";
+}
+
+/*!
+  \brief Get operations set name.
+  \return operations set name
+*/
+QString QtxEvalSetConst::name() const
+{
+  return Name();
+}
+
+/*!
+  \brief Create value from its string representation.
+
+  Convert constant name to its value.
+
+  \param str string representration of the constant
+  \param val returning value
+  \return \c true if \a str can be evaluated as custom value and \c false
+          otherwise (parameter)
+*/
+bool QtxEvalSetConst::createValue( const QString& str, QVariant& val ) const
+{
+  bool ok = true;
+  if ( str == "pi" )            // PI number
+    val = QVariant( 3.141593 );
+  else if ( str == "exp" )      // Exponent value (e)
+    val = QVariant( 2.718282 );
+  else if ( str == "g" )        // Free fall acceleration (g)
+    val = QVariant( 9.80665 );
+  else
+    ok = false;
+
+  return ok;
+}
+
+/*!
+  \brief Get the list of possible operations.
+  \param list returning list of operations supported by the class (not used)
+*/
+void QtxEvalSetConst::operationList( QStringList& /*list*/ ) const
+{
+}
+
+/*!
+  \brief Get list of brackets.
+  \param list returning list of brackets (not used)
+  \param open if \c true, collect opening brackets, or closing brackets otherwise (not used)
+*/
+void QtxEvalSetConst::bracketsList( QStringList& /*list*/, bool /*open*/ ) const
+{
+}
+
+/*!
+  \brief Get the operation priority.
+
+  Operation priority counts from 1.
+  If the operation is impossible, this function returns value <= 0.
+  
+  \param op operation (not used)
+  \param isBin \c true if the operation is binary and \c false if it is unary (not used)
+  \return operation priority
+*/
+int QtxEvalSetConst::priority( const QString& /*op*/, bool /*isBin*/ ) const
+{
+  return 0;
+}
+
+/*!
+  \brief Check operation validity.
+
+  Always returns QtxEvalExpr::InvalidOperation.
+
+  \param op operation (not used)
+  \param t1 first operand type (not used)
+  \param t2 second operand type (not used)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetConst::isValid( const QString&       /*op*/, 
+                                            const QVariant::Type /*t1*/,
+                                            const QVariant::Type /*t2*/ ) const
+{
+  return QtxEvalExpr::InvalidOperation;
+}
+
+/*!
+  \brief Calculate the operation.
+
+  Always returns QtxEvalExpr::InvalidOperation.
+
+  \param op operation name (not used)
+  \param v1 first argument (not valid for unary prefix operations) (not used)
+  \param v2 second argument (not valid for unary postfix operations) (not used)
+  \return error code (QtxEvalExpr::Error)
+*/
+QtxEvalExpr::Error QtxEvalSetConst::calculate( const QString&, QVariant&, QVariant& ) const
+{
+  return QtxEvalExpr::InvalidOperation;
+}
diff --git a/src/Qtx/QtxEvalExpr.h b/src/Qtx/QtxEvalExpr.h
new file mode 100644 (file)
index 0000000..34acd47
--- /dev/null
@@ -0,0 +1,324 @@
+// 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
+//
+// File:      QtxEvalExpr.h
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
+
+#ifndef QTXEVALEXPR_H
+#define QTXEVALEXPR_H
+
+#include "Qtx.h"
+
+#include <QList>
+#include <QVariant>
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QtxEvalSet;
+class QtxEvalParser;
+
+class QTX_EXPORT QtxEvalExpr
+{
+public:
+  //! Parsing error type
+  typedef enum
+  {
+    OK,               //!< No errors found
+    OperandsNotMatch, //!< Types of arguments are invalid for this operation
+    InvalidResult,    //!< Operation cannot find result (for example, division by zero)
+    InvalidOperation, //!< Unknown operation
+    OperationsNull,   //!< Internal operations pointer of parser is null
+    InvalidToken,     //!< Invalid token (neither operation, nor parameter of value)
+    CloseExpected,    //!< Closing bracket is expected
+    ExcessClose,      //!< Extra closing bracket is found
+    BracketsNotMatch, //!< Opening and closing brackets are of different type, e.g. [)
+    StackUnderflow,   //!< There are no arguments in the stack for the operation
+    ExcessData        //!< The parsing is finished, but there are more then one value in the stack
+  } Error;
+
+public:
+  QtxEvalExpr( const QString& = QString() );
+  QtxEvalExpr( const bool, const QString& = QString() );
+  ~QtxEvalExpr();
+
+  QVariant           calculate( const QString& = QString() );
+
+  QString            expression() const;
+  void               setExpression( const QString& );
+
+  Error              error() const;
+  QtxEvalParser*     parser() const;
+
+  bool               autoDeleteOperationSets() const;
+  void               setAutoDeleteOperationSets( const bool );
+
+  QList<QtxEvalSet*> operationSets() const;
+  QtxEvalSet*        operationSet( const QString& ) const;
+  void               removeOperationSet( QtxEvalSet* );
+  void               insertOperationSet( QtxEvalSet*, const int = -1 );
+
+private:
+  void               intialize( const bool, const QString& );
+
+private:
+  QString            myExpr;
+  QtxEvalParser*     myParser;
+};
+
+class QTX_EXPORT QtxEvalParser
+{
+public:
+  QtxEvalParser();
+  virtual ~QtxEvalParser();
+
+  QVariant           calculate();
+  QVariant           calculate( const QString& );
+  bool               setExpression( const QString& );
+
+  QList<QtxEvalSet*> operationSets() const;
+  QtxEvalSet*        operationSet( const QString& ) const;
+  void               removeOperationSet( QtxEvalSet* );
+  void               insertOperationSet( QtxEvalSet*, const int = -1 );
+
+  bool               autoDeleteOperationSets() const;
+  void               setAutoDeleteOperationSets( const bool );
+
+  virtual void       clearParameters();
+  virtual bool       removeParameter( const QString& name );
+  virtual QVariant   parameter( const QString& name ) const;
+  virtual bool       hasParameter( const QString& name ) const;
+  virtual void       setParameter( const QString& name, const QVariant& value );
+  QStringList        parameters() const;
+
+  QtxEvalExpr::Error error() const;
+
+  bool               firstInvalid( QString& ) const;
+  void               removeInvalids();
+  QString            dump() const;
+
+  static QString     toString( const QList<QVariant>& );
+
+protected:
+  //! Types of postfix representation elements
+  typedef enum
+  {
+    Value, //!< Value (number, string, etc.)
+    Param, //!< Parameter
+    Open,  //!< Open bracket
+    Close, //!< Close bracket
+    Pre,   //!< Unary prefix operation
+    Post,  //!< Unary postfix operation
+    Binary //!< Binary operation
+  } PostfixItemType;
+
+  //! Postfix representation element
+  typedef struct
+  {
+    QVariant          myValue;
+    PostfixItemType   myType;
+  } PostfixItem;
+
+  typedef QList<PostfixItem>      Postfix;   //!< postfix representation
+  typedef QList<QtxEvalSet*>      SetList;   //!< list of operations
+  typedef QMap<QString, QVariant> ParamMap;  //!< parameter-to-value map
+
+protected:
+  QString            dump( const Postfix& ) const;
+  virtual bool       prepare( const QString&, Postfix& );
+  virtual bool       setOperationTypes( Postfix& );
+  virtual bool       sort( const Postfix&, Postfix&, const QStringList&,
+                           const QStringList&, int f = -1, int l = -1 );
+
+  virtual bool       parse( const QString& );
+  virtual void       setError( const QtxEvalExpr::Error );
+
+  bool               calculate( const QString&, QVariant&, QVariant& );
+
+  static int         search( const QStringList&, const QString&,
+                             int offset, int& matchLen, int& listind );
+  static QString     note( const QString& str, int pos, int len );
+  static int         globalBrackets( const Postfix&, int, int );
+
+private:
+  void               operationList( QStringList& ) const;
+  void               bracketsList( QStringList&, bool ) const;
+  bool               createValue( const QString&, QVariant& ) const;
+  int                priority( const QString&, bool isBin ) const;
+  QtxEvalExpr::Error isValid( const QString&,
+                              const QVariant::Type, const QVariant::Type ) const;
+  QtxEvalExpr::Error calculation( const QString&, QVariant&, QVariant& ) const;
+
+  bool               checkOperations() const;
+
+private:
+  SetList            mySets;
+  QtxEvalExpr::Error myError;
+  ParamMap           myParams;
+  Postfix            myPostfix;
+  bool               myAutoDel;
+};
+
+class QTX_EXPORT QtxEvalSet
+{
+public:
+  QtxEvalSet();
+  virtual ~QtxEvalSet();
+
+  virtual QString            name() const = 0;
+
+  virtual void               operationList( QStringList& ) const = 0;
+
+  virtual void               bracketsList( QStringList&, bool open ) const = 0;
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+
+  virtual int                priority( const QString&, bool isBin ) const = 0;
+
+  virtual QtxEvalExpr::Error isValid( const QString&, const QVariant::Type,
+                                      const QVariant::Type ) const = 0;
+
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const = 0;
+};
+
+class QTX_EXPORT QtxEvalSetBase : public QtxEvalSet
+{
+public:
+  QtxEvalSetBase();
+  virtual ~QtxEvalSetBase();
+
+  virtual void               operationList( QStringList& ) const;
+  virtual void               bracketsList( QStringList&, bool open ) const;
+
+  virtual QtxEvalExpr::Error isValid( const QString&, const QVariant::Type,
+                                      const QVariant::Type ) const;
+protected: 
+  typedef QList<QVariant::Type> ListOfTypes;
+
+  void                       addTypes( const ListOfTypes& );
+  void                       addOperations( const QStringList& );
+
+private:
+  QStringList                myOpers;
+  ListOfTypes                myTypes;
+};
+
+class QTX_EXPORT QtxEvalSetArithmetic : public QtxEvalSetBase
+{
+public:
+  QtxEvalSetArithmetic();
+  virtual ~QtxEvalSetArithmetic();
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+
+  static QString             Name();
+  virtual QString            name() const;
+};
+
+class QTX_EXPORT QtxEvalSetLogic : public QtxEvalSetBase
+{
+public:
+  QtxEvalSetLogic();
+  virtual ~QtxEvalSetLogic();
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+
+  static QString             Name();
+  virtual QString            name() const;
+
+private:
+  bool                       booleanValue( const QVariant& v ) const;
+};
+
+class QTX_EXPORT QtxEvalSetMath : public QtxEvalSetBase
+{
+public:
+  QtxEvalSetMath();
+  virtual ~QtxEvalSetMath();
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+
+  static QString             Name();
+  virtual QString            name() const;
+};
+
+class QTX_EXPORT QtxEvalSetString : public QtxEvalSetBase
+{
+public:
+  QtxEvalSetString();
+  virtual ~QtxEvalSetString();
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+
+  static QString             Name();
+  virtual QString            name() const;
+};
+
+class QTX_EXPORT QtxEvalSetSets : public QtxEvalSetBase
+{
+public:
+  typedef QList<QVariant> ValueSet;
+
+public:
+  QtxEvalSetSets();
+  virtual ~QtxEvalSetSets();
+
+  virtual void               bracketsList( QStringList&, bool open ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error isValid( const QString&, const QVariant::Type,
+                                      const QVariant::Type ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+
+  static void add( ValueSet&, const QVariant& );
+  static void add( ValueSet&, const ValueSet& );
+  static void remove( ValueSet&, const QVariant& );
+  static void remove( ValueSet&, const ValueSet& );
+
+  static QString             Name();
+  virtual QString            name() const;
+};
+
+class QTX_EXPORT QtxEvalSetConst : public QtxEvalSet
+{
+public:
+  QtxEvalSetConst();
+  virtual ~QtxEvalSetConst();
+
+  static QString             Name();
+  virtual QString            name() const;
+
+  virtual bool               createValue( const QString&, QVariant& ) const;
+
+  virtual void               operationList( QStringList& ) const;
+  virtual void               bracketsList( QStringList&, bool open ) const;
+  virtual int                priority( const QString&, bool isBin ) const;
+  virtual QtxEvalExpr::Error isValid( const QString&, const QVariant::Type,
+                                      const QVariant::Type ) const;
+  virtual QtxEvalExpr::Error calculate( const QString&, QVariant&, QVariant& ) const;
+};
+
+#endif // QTXEVALEXPR_H
diff --git a/src/Qtx/QtxFontEdit.cxx b/src/Qtx/QtxFontEdit.cxx
new file mode 100644 (file)
index 0000000..30970d8
--- /dev/null
@@ -0,0 +1,298 @@
+// 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
+//
+// File:      QtxFontEdit.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxFontEdit.h"
+
+#include "QtxComboBox.h"
+
+#include <QLayout>
+#include <QToolButton>
+#include <QFontDialog>
+#include <QFontDatabase>
+#include <QFontComboBox>
+
+/*!
+  \class QtxFontEdit
+  \brief The QtxFontEdit class represents a widget for font
+  preference items editing.
+
+  The font preference item is represented as the drop-down combo box 
+  filled with the list of available fonts. Additional controls for
+  modifying font properties ('bold', 'italic', font size, etc) are also
+  available for use.
+
+  Initial font value can be set with setCurrentFont() method. Chosen font
+  can be retrieved with the currentFont() method.
+
+  Font properties can be set with the setFontSize(), setFontFamily(), 
+  setFontScripting() methods and retrieved with fontSize(), fontFamily(), 
+  fontScripting() methods.
+
+  Additional widgets for direct modyfing font properties are available
+  with use of setFeatures() method.
+*/
+
+/*!
+  \brief Constructor
+  \param feat font widget features (ORed QtxFontEdit::Features flags)
+  \param parent parent widget
+*/
+QtxFontEdit::QtxFontEdit( const int feat, QWidget* parent )
+: QFrame( parent ),
+  myFeatures( feat )
+{
+  initialize();
+}
+
+/*!
+  \brief Constructor
+  \param parent parent widget
+
+  All font widget features are enabled.
+*/
+QtxFontEdit::QtxFontEdit( QWidget* parent )
+: QFrame( parent ),
+  myFeatures( All )
+{
+  initialize();
+}
+
+/*!
+  \brief Destructor
+*/
+QtxFontEdit::~QtxFontEdit()
+{
+}
+
+/*!
+  \brief Get font widget features.
+  \return font widget features (ORed QtxFontEdit::Features flags)
+  \sa setFeatures()
+*/
+int QtxFontEdit::features() const
+{
+  return myFeatures;
+}
+
+/*!
+  \brief Set font widget features.
+  \param f font widget features (ORed QtxFontEdit::Features flags)
+  \sa features()
+*/
+void QtxFontEdit::setFeatures( const int f )
+{
+  if ( myFeatures == f )
+    return;
+
+  myFeatures = f;
+  updateState();
+}
+
+/*!
+  \brief Get currently selected font.
+  \return current font
+  \sa setCurrentFont()
+*/
+QFont QtxFontEdit::currentFont() const
+{
+  QFont fnt( fontFamily(), fontSize() );
+
+  int script = fontScripting();
+  fnt.setBold( script & Bold );
+  fnt.setItalic( script & Italic );
+  fnt.setUnderline( script & Underline );
+
+  return fnt;
+}
+
+/*!
+  \brief Set currently selected font.
+  \param fnt current font
+  \sa currentFont()
+*/
+void QtxFontEdit::setCurrentFont( const QFont& fnt )
+{
+  setFontFamily( fnt.family() );
+  setFontSize( fnt.pointSize() );
+  setFontScripting( ( fnt.bold() ? Bold : 0 ) |
+                    ( fnt.italic() ? Italic : 0 ) |
+                    ( fnt.underline() ? Underline : 0 ) );
+}
+
+/*!
+  \brief Get selected font family name.
+  \return current font family name
+  \sa setFontFamily()
+*/
+QString QtxFontEdit::fontFamily() const
+{
+  return myFamily->currentFont().family();
+}
+
+/*!
+  \brief Get selected font size.
+  \return current font size
+  \sa setFontSize()
+*/
+int QtxFontEdit::fontSize() const
+{
+  bool ok;
+  int pSize = mySize->currentText().toInt( &ok );
+  return ok ? pSize : 0;
+}
+
+/*!
+  \brief Get selected font scripting.
+  \return current font scripting
+  \sa setFontScripting()
+*/
+int QtxFontEdit::fontScripting() const
+{
+  return ( myB->isChecked() ? Bold : 0 ) |
+         ( myI->isChecked() ? Italic : 0 ) |
+         ( myU->isChecked() ? Underline : 0 );
+}
+
+/*!
+  \brief Set font family name.
+  \param fam new font family name
+  \sa fontFamily()
+*/
+void QtxFontEdit::setFontFamily( const QString& fam )
+{
+  myFamily->setCurrentFont( QFont( fam ) );
+  onFontChanged( myFamily->currentFont() );  
+}
+
+/*!
+  \brief Set font size.
+  \param fam new font size
+  \sa fontSize()
+*/
+void QtxFontEdit::setFontSize( const int s )
+{
+  if ( s <= 0 )
+    return;
+
+  int idx = mySize->findText( QString::number( s ) );
+  if ( idx != -1 )
+    mySize->setCurrentIndex( idx );
+  else if ( mySize->isEditable() )
+    mySize->setEditText( QString::number( s ) );
+}
+
+/*!
+  \brief Set font scripting.
+  \param fam new font scripting
+  \sa fontScripting()
+*/
+void QtxFontEdit::setFontScripting( const int script )
+{
+  myB->setChecked( script & Bold );
+  myI->setChecked( script & Italic );
+  myU->setChecked( script & Underline );
+}
+
+/*!
+  \brief Update widget state
+*/
+void QtxFontEdit::updateState()
+{
+  int feat = features();
+
+  myFamily->setVisible( feat & Family );
+  mySize->setVisible( feat & Size );
+  myB->setVisible( feat & Bold );
+  myI->setVisible( feat & Italic );
+  myU->setVisible( feat & Underline );
+  myPreview->setVisible( feat & Preview );
+
+  mySize->setEditable( feat & UserSize );
+}
+
+/*!
+  \brief Called when current font is changed.
+  \param f (not used)
+*/
+void QtxFontEdit::onFontChanged( const QFont& /*f*/ )
+{
+  int s = fontSize();
+  mySize->clear();
+
+  QList<int> szList = QFontDatabase().pointSizes( fontFamily() );
+  QStringList sizes;
+  for ( QList<int>::const_iterator it = szList.begin(); it != szList.end(); ++it )
+    sizes.append( QString::number( *it ) );
+  mySize->addItems( sizes );
+
+  setFontSize( s );
+}
+
+/*!
+  \brief Called when "Preview" button is clicked.
+  \param on (not used)
+*/
+void QtxFontEdit::onPreview( bool /*on*/ )
+{
+  bool ok;
+  QFont fnt = QFontDialog::getFont( &ok, currentFont() );
+
+  if ( ok )
+    setCurrentFont( fnt );
+}
+
+/*
+  \brief Perform internal intialization.
+*/
+void QtxFontEdit::initialize()
+{
+  QHBoxLayout* base = new QHBoxLayout( this );
+  base->setMargin( 0 );
+  base->setSpacing( 5 );
+
+  base->addWidget( myFamily = new QFontComboBox( this ) );
+  base->addWidget( mySize = new QtxComboBox( this ) );
+  mySize->setInsertPolicy( QComboBox::NoInsert );
+  mySize->setValidator( new QIntValidator( 1, 250, mySize ) );
+
+  base->addWidget( myB = new QToolButton( this ) );
+  myB->setText( tr( "B" ) );
+  myB->setCheckable( true );
+
+  base->addWidget( myI = new QToolButton( this ) );
+  myI->setText( tr( "I" ) );
+  myI->setCheckable( true );
+
+  base->addWidget( myU = new QToolButton( this ) );
+  myU->setText( tr( "U" ) );
+  myU->setCheckable( true );
+
+  base->addWidget( myPreview = new QToolButton( this ) );
+  myPreview->setText( "..." );
+
+  myFamily->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
+
+  connect( myPreview, SIGNAL( clicked( bool ) ), this, SLOT( onPreview( bool ) ) );
+  connect( myFamily, SIGNAL( currentFontChanged( const QFont& ) ), this, SLOT( onFontChanged( const QFont& ) ) );
+
+  updateState();
+  onFontChanged( currentFont() );
+}
diff --git a/src/Qtx/QtxFontEdit.h b/src/Qtx/QtxFontEdit.h
new file mode 100644 (file)
index 0000000..b0ef25e
--- /dev/null
@@ -0,0 +1,86 @@
+// 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
+//
+// File:      QtxFontEdit.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXFONTEDIT_H
+#define QTXFONTEDIT_H
+
+#include "Qtx.h"
+
+#include <QFrame>
+
+class QtxComboBox;
+class QToolButton;
+class QFontComboBox;
+
+class QTX_EXPORT QtxFontEdit : public QFrame
+{
+  Q_OBJECT
+
+public:
+  //! Font widget features
+  typedef enum { 
+    Family    = 0x01,                                      //!< show font family selection widget
+    Size      = 0x02,                                      //!< show font size widget
+    UserSize  = 0x04,                                      //!< allow font size direct change
+    Bold      = 0x08,                                      //!< show 'bold' widget
+    Italic    = 0x10,                                      //!< show 'italic' widget
+    Underline = 0x20,                                      //!< show 'underline' widget
+    Preview   = 0x40,                                      //!< show font preview widget
+    Scripting = Bold | Italic | Underline,                 //!< show font scripting widgets ('bold','italic','underline')
+    All = Family | Size | UserSize | Scripting | Preview   //!< show all font widgets
+  } Features;
+
+public:
+  QtxFontEdit( const int, QWidget* = 0 );
+  QtxFontEdit( QWidget* = 0 );
+  virtual ~QtxFontEdit();
+
+  QFont          currentFont() const;
+  void           setCurrentFont( const QFont& );
+
+  int            fontSize() const;
+  QString        fontFamily() const;
+  int            fontScripting() const;
+
+  void           setFontSize( const int );
+  void           setFontFamily( const QString& );
+  void           setFontScripting( const int );
+
+  int            features() const;
+  void           setFeatures( const int );
+
+private slots:
+  void           onPreview( bool );
+  void           onFontChanged( const QFont& );
+private:
+  void           initialize();
+  void           updateState();
+
+private:
+  QtxComboBox*   mySize;
+  QFontComboBox* myFamily;
+  QToolButton*   myPreview;
+  int            myFeatures;
+  QToolButton    *myB, *myI, *myU;
+};
+
+#endif // QTXFONTEDIT_H
diff --git a/src/Qtx/QtxGridBox.cxx b/src/Qtx/QtxGridBox.cxx
new file mode 100644 (file)
index 0000000..bb2d336
--- /dev/null
@@ -0,0 +1,362 @@
+// 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
+//
+// File:      QtxGridBox.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxGridBox.h"
+
+#include <QGridLayout>
+#include <QChildEvent>
+
+/*!
+  \class QtxGridBox::Space
+  \internal
+  \brief Represents a space in the grid box.
+*/
+
+class QtxGridBox::Space : public QWidget
+{
+public:
+  Space( const int, QtxGridBox* );
+  virtual ~Space();
+
+  virtual QSize sizeHint() const;
+  virtual QSize minimumSizeHint() const;
+
+private:
+  int           mySize;
+  QtxGridBox*   myGrid;
+};
+
+/*!
+  \brief Constructor.
+  \param sz size
+  \param gb parent grid box
+*/
+QtxGridBox::Space::Space( const int sz, QtxGridBox* gb )
+: QWidget( gb ),
+  mySize( sz ),
+  myGrid( gb )
+{
+  setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxGridBox::Space::~Space()
+{
+}
+
+/*!
+  \brief Get recommended size for the widget.
+  \return recommended size for the widget
+*/
+QSize QtxGridBox::Space::sizeHint() const
+{
+  return minimumSizeHint();
+}
+
+/*!
+  \brief Get recommended minimum size for the widget.
+  \return recommended minimum size for the widget
+*/
+QSize QtxGridBox::Space::minimumSizeHint() const
+{
+  QSize sz( 0, 0 );
+  if ( myGrid && myGrid->orientation() == Qt::Horizontal )
+    sz.setWidth( mySize );
+  else
+    sz.setHeight( mySize );
+  return sz;
+}
+
+/*!
+  \class QtxGridBox
+  \brief A container widget with possibility to automatically layout
+         child widgets.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+  \param m grid box margin
+  \param s grid box spacing
+*/
+QtxGridBox::QtxGridBox( QWidget* parent, const int m, const int s )
+: QWidget( parent ),
+  myCols( 1 ),
+  mySkip( false ),
+  myOrient( Qt::Vertical ),
+  myCol( 0 ),
+  myRow( 0 )
+{
+  myLayout = new QGridLayout( this );
+  myLayout->setMargin( m );
+  myLayout->setSpacing( s );
+}
+
+/*!
+  \brief Constructor.
+  \param cols number of grid box columns or rows (depending on the orientation)
+  \param o grid box orientation
+  \param parent parent widget
+  \param m grid box margin
+  \param s grid box spacing
+*/
+QtxGridBox::QtxGridBox( const int cols, Qt::Orientation o, QWidget* parent, const int m, const int s )
+: QWidget( parent ),
+  myCols( cols ),
+  mySkip( false ),
+  myOrient( o ),
+  myLayout( 0 ),
+  myCol( 0 ),
+  myRow( 0 )
+{
+  myLayout = new QGridLayout( this );
+  myLayout->setMargin( m );
+  myLayout->setSpacing( s );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxGridBox::~QtxGridBox()
+{
+}
+
+/*!
+  \brief Get number of grid box columns/rows (depending on the orientation).
+  \return number of columns (rows)
+*/
+int QtxGridBox::columns() const
+{
+  return myCols;
+}
+
+/*!
+  \brief Get the grid box orientation.
+  \return orientation
+*/
+Qt::Orientation QtxGridBox::orientation() const
+{
+  return myOrient;
+}
+
+/*!
+  \brief Set number of grid box columns/rows (depending on the orientation).
+  \param cols number of columns (rows)
+*/
+void QtxGridBox::setColumns( const int cols )
+{
+  setLayout( cols, orientation() );
+}
+
+/*!
+  \brief Set the grid box orientation.
+  \param o orientation
+*/
+void QtxGridBox::setOrientation( Qt::Orientation o )
+{
+  setLayout( columns(), o );
+}
+
+/*!
+  \brief Initialize internal layout.
+  \param cols number of columns (rows)
+  \param o orientation
+*/
+void QtxGridBox::setLayout( const int cols, Qt::Orientation o )
+{
+  if ( myCols == cols && myOrient == o )
+    return;
+
+  myCols = cols;
+  myOrient = o;
+
+  arrangeWidgets();
+}
+
+/*!
+  \brief Get "skip invisible widgets" flags.
+  \return current flag state
+*/
+bool QtxGridBox::skipInvisible() const
+{
+  return mySkip;
+}
+
+/*!
+  \brief Set "skip invisible widgets" flags.
+
+  If this flag is set to \c false, invisible widgets
+  are not taken into account when layouting widgets.
+
+  \param on new flag state
+*/
+void QtxGridBox::setSkipInvisible( const bool on )
+{
+  if ( mySkip == on )
+    return;
+
+  mySkip = on;
+  arrangeWidgets();
+}
+
+/*!
+  \brief Add space (empty cell) to the grid box.
+  \param sp requied space size
+*/
+void QtxGridBox::addSpace( const int sp )
+{
+  new Space( sp, this );
+}
+
+/*!
+  \brief Get grid box's inside margin size.
+  \return inside margin size
+*/
+int QtxGridBox::insideMargin() const
+{
+  return myLayout->margin();
+}
+
+/*!
+  \brief Get grid box's inside spacing size.
+  \return inside spacing size
+*/
+int QtxGridBox::insideSpacing() const
+{
+  return myLayout->spacing();
+}
+
+/*!
+  \brief Set grid box's inside margin size.
+  \param m new inside margin size
+*/
+void QtxGridBox::setInsideMargin( const int m )
+{
+  myLayout->setMargin( m );
+}
+
+/*!
+  \brief Set grid box's inside spacing size.
+  \param s new inside spacing size
+*/
+void QtxGridBox::setInsideSpacing( const int s )
+{
+  myLayout->setSpacing( s );
+}
+
+/*!
+  \brief Custom event filter.
+  \param o event receiver object.
+  \param e event
+  \return \c true if the event processing should be stopped
+*/
+bool QtxGridBox::eventFilter( QObject* o, QEvent* e )
+{
+  if ( skipInvisible() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
+                            e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
+    arrangeWidgets();
+
+  return QWidget::eventFilter( o, e );
+}
+
+/*!
+  \brief Customize child event.
+  \param e child event
+*/
+void QtxGridBox::childEvent( QChildEvent* e )
+{
+  if ( e->child()->isWidgetType() )
+  {
+    QWidget* wid = (QWidget*)e->child();
+    if ( e->type() == QEvent::ChildAdded )
+    {
+      placeWidget( wid );
+      wid->installEventFilter( this );
+    }
+    else if ( e->type() == QEvent::ChildRemoved )
+      wid->removeEventFilter( this );
+  }
+  QWidget::childEvent( e );
+}
+
+/*!
+  \brief Increment the grid box current cell.
+*/
+void QtxGridBox::skip()
+{
+  if ( orientation() == Qt::Horizontal )
+  {
+    myCol++;
+    if ( myCol >= columns() )
+    {
+      myRow++;
+      myCol = 0;
+    }
+  }
+  else
+  {
+    myRow++;
+    if ( myRow >= columns() )
+    {
+      myCol++;
+      myRow = 0;
+    }
+  }
+}
+
+/*!
+  \brief Arrange child widgets.
+*/
+void QtxGridBox::arrangeWidgets()
+{
+  myRow = myCol = 0;
+  int m = myLayout ? myLayout->margin() : 0;
+  int s = myLayout ? myLayout->spacing() : 0;
+  delete myLayout;
+  myLayout = new QGridLayout( this );
+  myLayout->setMargin( m );
+  myLayout->setSpacing( s );
+
+  QObjectList list = children();
+  for ( QObjectList::iterator it = list.begin(); it != list.end(); ++it )
+  {
+    if ( !(*it)->isWidgetType() )
+      continue;
+
+    QWidget* wid = (QWidget*)(*it);
+    if ( !skipInvisible() || wid->isVisibleTo( this ) )
+      placeWidget( wid );
+  }
+  updateGeometry();
+}
+
+/*!
+  \brief Place new widget to the current grid box cell.
+  \param wid widget being inserted
+*/
+void QtxGridBox::placeWidget( QWidget* wid )
+{
+  myLayout->addWidget( wid, myRow, myCol );
+
+  skip();
+}
diff --git a/src/Qtx/QtxGridBox.h b/src/Qtx/QtxGridBox.h
new file mode 100644 (file)
index 0000000..4ca39aa
--- /dev/null
@@ -0,0 +1,79 @@
+// 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
+//
+// File:      QtxGridBox.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXGRIDBOX_H
+#define QTXGRIDBOX_H
+
+#include "Qtx.h"
+
+#include <QWidget>
+
+class QGridLayout;
+
+class QTX_EXPORT QtxGridBox : public QWidget
+{
+  Q_OBJECT
+
+  class Space;
+
+public:
+  QtxGridBox( QWidget* = 0, const int = 5, const int = 5 );
+  QtxGridBox( const int, Qt::Orientation, QWidget* = 0, const int = 5, const int = 5 );
+  virtual ~QtxGridBox();
+
+  int             columns() const;
+  Qt::Orientation orientation() const;
+
+  void            setColumns( const int );
+  void            setOrientation( Qt::Orientation );
+
+  void            setLayout( const int, Qt::Orientation );
+
+  bool            skipInvisible() const;
+  void            setSkipInvisible( const bool );
+
+  void            addSpace( const int );
+
+  int             insideMargin() const;
+  int             insideSpacing() const;
+  void            setInsideMargin( const int );
+  void            setInsideSpacing( const int );
+
+  virtual bool    eventFilter( QObject*, QEvent* );
+
+protected:
+  void            childEvent( QChildEvent* );
+
+private:
+  void            skip();
+  void            arrangeWidgets();
+  void            placeWidget( QWidget* );
+
+private:
+  int             myCols;
+  bool            mySkip;
+  Qt::Orientation myOrient;
+  QGridLayout*    myLayout;
+
+  int             myCol, myRow;
+};
+
+#endif
diff --git a/src/Qtx/QtxGroupBox.cxx b/src/Qtx/QtxGroupBox.cxx
new file mode 100644 (file)
index 0000000..e99532e
--- /dev/null
@@ -0,0 +1,345 @@
+// 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
+//
+// File:      QtxGroupBox.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxGroupBox.h"
+
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QEvent>
+#include <QObjectList>
+#include <QApplication>
+
+/*!
+  \class QtxGroupBox
+  \brief Enhanced group box widget.
+
+  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.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget 
+*/
+QtxGroupBox::QtxGroupBox( QWidget* parent )
+: QGroupBox( parent ),
+  myContainer( 0 )
+{
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+  \param title group box title text
+  \param parent parent widget 
+*/
+QtxGroupBox::QtxGroupBox( const QString& title, QWidget* parent )
+: QGroupBox( title, parent ),
+  myContainer( 0 )
+{
+  initialize();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxGroupBox::~QtxGroupBox()
+{
+}
+
+/*!
+  \brief Initialize the group box.
+
+  Creates horizontal box as container for title widgets.
+*/
+void QtxGroupBox::initialize()
+{
+  myContainer = new QWidget( this );
+  QHBoxLayout* base = new QHBoxLayout( myContainer );
+  base->setMargin( 0 );
+  base->setSpacing( 0 );
+
+  updateTitle();
+}
+
+/*!
+  \brief Add widget to the group box title.
+  \param wid widget being added to the title
+*/
+void QtxGroupBox::insertTitleWidget( QWidget* wid )
+{
+  if ( !myContainer )
+    return;
+
+  myContainer->layout()->addWidget( wid );
+  wid->installEventFilter( this );
+
+  updateTitle();
+}
+
+/*!
+  \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;
+
+  myContainer->layout()->removeWidget( wid );
+  wid->setParent( 0 );
+  wid->removeEventFilter( this );
+  wid->hide();
+
+  updateTitle();
+}
+
+/*!
+  \brief Show/hide group box.
+  \param on if \c true, show group box, otherwise, hide it
+*/
+void QtxGroupBox::setVisible( bool on )
+{
+  if ( on )
+    updateTitle();
+
+  QGroupBox::setVisible( on );
+}
+
+/*!
+  \brief Get recommended size for the widget.
+  \return recommended size for the widget
+*/
+QSize QtxGroupBox::sizeHint() const
+{
+  return expandTo( QGroupBox::sizeHint() );
+}
+
+/*!
+  \brief Get recommended minimum size for the widget.
+  \return recommended minimum size for the widget
+*/
+QSize QtxGroupBox::minimumSizeHint() const
+{
+  return expandTo( QGroupBox::minimumSizeHint() );
+}
+
+/*!
+  \brief Custom event filter.
+  \param obj event receiver
+  \param e event
+  \return \c true if event processing should be stopped
+*/
+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 QEvent( QEvent::User ) );
+
+  return QGroupBox::eventFilter( obj, e );
+}
+/*!
+  \brief Get central widget (or first found one).
+  \return widget
+*/
+QWidget* QtxGroupBox::widget() const
+{
+  if ( !layout() )
+    return 0;
+
+  QWidget* w = 0;
+  for ( int i = 0; i < (int)layout()->count() && !w; i++ )
+    w = layout()->itemAt( i )->widget();
+  return w;
+}
+
+/*!
+  \brief Set central widget to the group box.
+  \param wid widget being added to the group box
+*/
+void QtxGroupBox::setWidget( QWidget* wid )
+{
+  QWidget* w = widget();
+  if ( w == wid )
+    return;
+
+  if ( layout() )
+    layout()->removeWidget( w );
+
+  if ( !wid )
+    delete layout();
+  else if ( !layout() )
+  {
+    QLayout* bl = new QVBoxLayout( this );
+    bl->setMargin( 0 );
+    bl->setSpacing( 0 );
+  }
+
+  if ( layout() )
+    layout()->addWidget( wid );
+
+  if ( wid )
+    wid->updateGeometry();
+}
+
+/*!
+  \brief Customize resize event.
+  \param e resize event
+*/
+void QtxGroupBox::resizeEvent( QResizeEvent* e )
+{
+  QGroupBox::resizeEvent( e );
+
+  updateTitle();
+}
+
+/*!
+  \brief Customize child event.
+  \param e child event
+*/
+void QtxGroupBox::childEvent( QChildEvent* e )
+{
+/*
+  if ( e->type() == QEvent::ChildAdded && e->child() == myContainer )
+    return;
+*/
+  QGroupBox::childEvent( e );
+}
+
+/*!
+  \brief Process custom events.
+  \param e custom event (not used)
+*/
+void QtxGroupBox::customEvent( QEvent* /*e*/ )
+{
+  updateTitle();
+}
+
+/*!
+  \brief Get the group box title size.
+  \return title size
+*/
+QSize QtxGroupBox::titleSize() const
+{
+  return QSize( fontMetrics().width( title() ), fontMetrics().height() );
+}
+
+/*!
+  \brief Update the group box title.
+*/
+void QtxGroupBox::updateTitle()
+{
+  if ( !myContainer )
+    return;
+
+  int align = alignment();
+
+  if ( title().isEmpty() )
+    align = Qt::AlignRight;
+
+  QSize ts = titleSize();
+
+  int m = 5;
+
+  int w = width() - ts.width();
+  if ( align == Qt::AlignCenter )
+    w = w / 2;
+
+  w -= m;
+
+  myContainer->resize( myContainer->minimumSizeHint() );
+
+  bool vis = false;
+  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 ( !vis )
+    myContainer->hide();
+  else
+  {
+    int x = 0;
+    if ( align == Qt::AlignRight )
+      x = rect().left() + m;
+    else
+      x = rect().right() - myContainer->width() - m;
+
+    int y = rect().top() - ( myContainer->height() - ts.height() ) / 2;
+
+    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 );
+}
diff --git a/src/Qtx/QtxGroupBox.h b/src/Qtx/QtxGroupBox.h
new file mode 100644 (file)
index 0000000..c2aa4e6
--- /dev/null
@@ -0,0 +1,68 @@
+// 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
+//
+// File:      QtxGroupBox.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXGROUPBOX_H
+#define QTXGROUPBOX_H
+
+#include "Qtx.h"
+
+#include <QGroupBox>
+
+class QTX_EXPORT QtxGroupBox : public QGroupBox
+{
+  Q_OBJECT
+
+public:
+  QtxGroupBox( QWidget* = 0 );
+  QtxGroupBox( const QString&, QWidget* = 0 );
+  virtual ~QtxGroupBox();
+
+  virtual void  insertTitleWidget( QWidget* );
+  virtual void  removeTitleWidget( QWidget* );
+
+  virtual QSize sizeHint() const;
+  virtual QSize minimumSizeHint() const;
+
+  virtual bool  eventFilter( QObject*, QEvent* );
+
+  QWidget*      widget() const;
+  void          setWidget( QWidget* );
+
+public slots:
+  virtual void  setVisible( bool );
+
+protected:
+  virtual void  childEvent( QChildEvent* );
+  virtual void  resizeEvent( QResizeEvent* );
+  virtual void  customEvent( QEvent* );
+
+private:
+  void          initialize();
+  void          updateTitle();
+  QSize         titleSize() const;
+  void          setInsideMargin( const int );
+  QSize         expandTo( const QSize& ) const;
+
+private:
+  QWidget*      myContainer;
+};
+
+#endif
diff --git a/src/Qtx/QtxIntSpinBox.cxx b/src/Qtx/QtxIntSpinBox.cxx
new file mode 100755 (executable)
index 0000000..175a297
--- /dev/null
@@ -0,0 +1,149 @@
+// 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
+//
+// File:      QtxIntSpinBox.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxIntSpinBox.h"
+
+#include <QLineEdit>
+/*!
+  \class QtxIntSpinBox
+  \brief Enhanced version of the Qt's spin box.
+
+  The QtxIntSpinBox class represents the widget for entering the
+  integer values. In addition to the functionality provided by
+  QSpinBox, this class supports "cleared" state - this is the
+  state corresponding to "None" (or empty) entered value.
+
+  To set "cleared" state use setCleared() method. To check if the spin
+  box stores "cleared" state, use isCleared() method.
+  For example:
+  \code
+  if (mySpinBox->isCleared()) {
+    ... // process "None" state
+  }
+  else {
+    int value = mySpinBox->value();
+    ... // process entered value
+  }
+  \endcode
+*/
+
+/*!
+  \brief Constructor.
+
+  Constructs a spin box with 0 as minimum value and 99 as maximum value, 
+  a step value of 1. The value is initially set to 0.
+
+  \param parent parent object
+*/
+QtxIntSpinBox::QtxIntSpinBox( QWidget* parent )
+: QSpinBox( parent ),
+  myCleared( false )
+{
+  connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), 
+          this, SLOT( onTextChanged( const QString& ) ) );
+}
+
+/*!
+  \brief Constructor.
+
+  Constructs a spin box with specified minimum, maximum and step value.
+  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
+*/
+QtxIntSpinBox::QtxIntSpinBox( int min, int max, int step, QWidget* parent )
+: QSpinBox( parent ),
+  myCleared( false )
+{
+  setMinimum( min );
+  setMaximum( max );
+  setSingleStep( step );
+
+  connect( lineEdit(), SIGNAL( textChanged( const QString& ) ), 
+          this, SLOT( onTextChanged( const QString& ) ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxIntSpinBox::~QtxIntSpinBox()
+{
+}
+
+/*!
+  \brief Check if spin box is in the "cleared" state.
+  \return \c true if spin box is cleared
+*/
+bool QtxIntSpinBox::isCleared() const
+{
+  return myCleared;
+}
+
+/*!
+  \brief Change "cleared" status of the spin box.
+  \param on new "cleared" status
+*/
+void QtxIntSpinBox::setCleared( const bool on )
+{
+  if ( myCleared == on )
+    return;
+  
+  myCleared = on;
+  setSpecialValueText( specialValueText() );
+}
+
+/*!
+  \brief Convert value to the text.
+  \param val value being converted
+  \return string containing the converted value
+*/
+QString QtxIntSpinBox::textFromValue( int val ) const
+{
+  return myCleared ? QString() : QSpinBox::textFromValue( val );
+}
+
+/*!
+  \brief Perform \a steps increment/decrement steps.
+  
+  The \a steps value can be any integer number. If it is > 0,
+  the value incrementing is done, otherwise value is decremented
+  \a steps times.  
+
+  \param steps number of increment/decrement steps
+*/
+void QtxIntSpinBox::stepBy( int steps )
+{
+  myCleared = false;
+
+  QSpinBox::stepBy( steps );
+}
+
+/*!
+  \brief Called when user enters the text in the spin box.
+  \param txt current spin box text (not used)
+*/
+void QtxIntSpinBox::onTextChanged( const QString& )
+{
+  myCleared = false;
+}
diff --git a/src/Qtx/QtxIntSpinBox.h b/src/Qtx/QtxIntSpinBox.h
new file mode 100755 (executable)
index 0000000..31580a1
--- /dev/null
@@ -0,0 +1,53 @@
+// 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
+//
+// File:      QtxIntSpinBox.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXINTSPINBOX_H
+#define QTXINTSPINBOX_H
+
+#include "Qtx.h"
+
+#include <QSpinBox>
+
+class QTX_EXPORT QtxIntSpinBox : public QSpinBox
+{
+  Q_OBJECT
+
+public:
+  QtxIntSpinBox( QWidget* = 0 );
+  QtxIntSpinBox( int, int, int = 1, QWidget* = 0 );
+  virtual ~QtxIntSpinBox();
+    
+  bool            isCleared() const;
+  virtual void    setCleared( const bool );
+    
+  virtual void    stepBy( int );
+  
+protected slots:
+  virtual void    onTextChanged( const QString& );
+  
+protected:
+  virtual QString textFromValue( int ) const;
+    
+private:
+  bool            myCleared;
+};
+
+#endif
diff --git a/src/Qtx/QtxListAction.cxx b/src/Qtx/QtxListAction.cxx
new file mode 100755 (executable)
index 0000000..813d052
--- /dev/null
@@ -0,0 +1,927 @@
+// 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
+//
+// File:      QtxListAction.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxListAction.h"
+
+#include <QMenu>
+#include <QLabel>
+#include <QVBoxLayout>
+#include <QMouseEvent>
+#include <QListWidget>
+#include <QToolButton>
+#include <QApplication>
+
+/*!
+  \class QtxListAction::ScrollEvent
+  \internal
+  \brief Event for the scrolling in the list of actions.
+*/
+
+class QtxListAction::ScrollEvent : public QEvent
+{
+public:
+  enum { Scroll = User + 1 };
+
+  ScrollEvent( bool down ) : QEvent( (QEvent::Type)Scroll ), myDown( down ) {}
+  virtual ~ScrollEvent() {}
+
+  bool isDown() const { return myDown; }
+
+private:
+  bool myDown;
+};
+
+/*!
+  \class QtxListAction::ListWidget
+  \internal
+  \brief List of actions.
+*/
+
+class QtxListAction::ListWidget : public QListWidget
+{
+public:
+  ListWidget( QWidget* parent = 0 ) : QListWidget( parent ) {}
+  virtual ~ListWidget() {}
+
+protected:
+  virtual void scrollContentsBy( int dx, int dy )
+  {
+    QListWidget::scrollContentsBy( dx, dy );
+    if ( dy != 0 )
+      QApplication::postEvent( viewport(), new ScrollEvent( dy <= 0 ) );
+  }
+};
+
+/*!
+  \class QtxListAction::ListFrame
+  \internal
+  \brief Expanding frame with action list and comment.
+*/
+
+class QtxListAction::ListFrame: public QMenu
+{
+public:
+  ListFrame( QtxListAction*, QWidget* parent );
+  virtual ~ListFrame();
+
+  void                    clear();
+  const QStringList       names() const;
+  void                    addNames( const QStringList& );
+
+  void                    setSingleComment( const QString& );
+  void                    setMultipleComment( const QString& );
+
+  int                     selected() const;
+  void                    setSelected( const int );
+
+  int                     linesNumber() const;
+  int                     charsNumber() const;
+
+  void                    setLinesNumber( const int );
+  void                    setCharsNumber( const int );
+
+  virtual QSize           sizeHint() const;
+  virtual QSize           minimumSizeHint() const;
+
+  virtual bool            eventFilter( QObject*, QEvent* );
+
+  virtual void            setVisible( bool );
+
+protected:
+  virtual void            keyPressEvent( QKeyEvent* );
+
+private:
+  void                    accept();
+  void                    updateComment();
+  void                    setNames( const QStringList& );
+  void                    removePostedEvens( QObject*, int );
+
+private:
+  QListWidget*            myList;
+  QStringList             myNames;
+  QtxListAction*          myAction;
+  QLabel*                 myComment;
+
+  int                     myLines;
+  int                     myChars;
+
+  QString                 mySingleComment;
+  QString                 myMultipleComment;
+};
+
+/*!
+  \brief Constructor.
+  \param a list action
+  \param parent parent widget
+*/
+QtxListAction::ListFrame::ListFrame( QtxListAction* a, QWidget* parent )
+: QMenu( parent ),
+  myList( 0 ),
+  myAction( a ),
+  myComment( 0 ),
+  myLines( 5 ),
+  myChars( 5 )
+{
+  QVBoxLayout* top = new QVBoxLayout( this );
+  top->setMargin( 0 );
+  QFrame* main = new QFrame( this );
+  main->setFrameStyle( QFrame::Panel | QFrame::Raised );
+  top->addWidget( main );
+
+  QVBoxLayout* base = new QVBoxLayout( main );
+  base->setMargin( 3 );
+  base->setSpacing( 2 );
+
+  myList = new ListWidget( main );
+  myList->setSelectionMode( QListWidget::MultiSelection );
+  myList->setVerticalScrollMode( QListWidget::ScrollPerItem );
+  myList->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
+  myList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+  myList->viewport()->installEventFilter( this );
+  myList->viewport()->setMouseTracking( true );
+  myList->setFocusPolicy( Qt::NoFocus );
+
+  myComment = new QLabel( main );
+  myComment->setFrameStyle( QFrame::Panel | QFrame::Sunken );
+  myComment->setAlignment( Qt::AlignCenter );
+  myMultipleComment = "%1";
+
+  base->addWidget( myList );
+  base->addWidget( myComment );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxListAction::ListFrame::~ListFrame()
+{
+}
+
+/*!
+  \brief Clear list of names.
+*/
+void QtxListAction::ListFrame::clear()
+{
+  myNames.clear();
+  setNames( myNames );
+}
+
+/*!
+  \brief Add names to the list.
+
+  Truncates each name to fit the frame width.
+  Method QtxListAction::setCharsNumber(int) can be used to change
+  the frame width (in characters).
+
+  \param names list of names to be added
+  \sa setNames(), QtxListAction::setCharsNumber(int)
+*/
+void QtxListAction::ListFrame::addNames( const QStringList& names )
+{
+  for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it )
+    myNames.append( *it );
+  setNames( myNames );
+}
+
+/*!
+  \brief Set names to the list.
+
+  Truncates each name to fit the frame width.
+  Method QtxListAction::setCharsNumber(int) can be used to change
+  the frame width (in characters).
+
+  \param names list of names to be set
+  \sa addNames(), QtxListAction::setCharsNumber(int)
+*/
+void QtxListAction::ListFrame::setNames( const QStringList& names )
+{
+  if ( !myList )
+    return;
+
+  myList->clear();
+  QStringList strList;
+  for ( QStringList::const_iterator it = names.begin(); it != names.end(); ++it )
+  {
+    QString s = *it;
+    QFontMetrics fm = myList->fontMetrics();
+    int maxW = charsNumber() * fm.maxWidth();
+    int w = fm.width( s );
+    if ( w > maxW )
+    {
+      QString extra( "..." );
+      int len = s.length();
+      int extraLen = fm.width( extra ) + 1;
+      while ( true )
+      {
+        w = fm.width( s, --len );
+        if ( w + extraLen < maxW )
+        {
+          s = s.left( len );
+          break;
+        }
+      }
+      s += extra;
+    }
+    strList.append( s );
+  }
+  myList->addItems( strList );
+}
+
+/*!
+  \brief Get list of names.
+  \return list of names
+*/
+const QStringList QtxListAction::ListFrame::names() const
+{
+  return myNames;
+}
+
+/*!
+  \brief Get maximum numer of lines shown without activation of vertical scroll bar.
+  \return number of lines
+  \sa setLinesNumber(), charsNumber(), setCharsNumber()
+*/
+int QtxListAction::ListFrame::linesNumber() const
+{
+  return myLines;
+}
+
+/*!
+  \brief Get maximum numer of characters in the line.
+
+  If the name length is greater than this value, it will be truncated.
+
+  \return number of characters
+  \sa setCharsNumber(), linesNumber(), setLinesNumber()
+*/
+int QtxListAction::ListFrame::charsNumber() const
+{
+  return myChars;
+}
+
+/*!
+  \brief Set maximum numer of lines shown without activation of vertical scroll bar.
+  \param maxLines number of lines
+  \sa linesNumber(), charsNumber(), setCharsNumber()
+*/
+void QtxListAction::ListFrame::setLinesNumber( const int maxLines )
+{
+  myLines = maxLines;
+}
+
+/*!
+  \brief Set maximum numer of characters in the line.
+
+  If the name length is greater than this value, it will be truncated.
+
+  \param maxChars number of characters
+  \sa charsNumber(), linesNumber(), setLinesNumber()
+*/
+void QtxListAction::ListFrame::setCharsNumber( const int maxChars )
+{
+  if ( myChars == maxChars )
+    return;
+
+  myChars = maxChars;
+  setNames( myNames );
+}
+
+/*!
+  \brief Set comment which is displayed when single name is selected.
+  \param comment comment format
+*/
+void QtxListAction::ListFrame::setSingleComment( const QString& comment )
+{
+  mySingleComment = comment;
+  setNames( myNames );
+  updateComment();
+}
+
+/*!
+  \brief Set comment which is displayed when multiple names are selected.
+  \param comment comment format
+*/
+void QtxListAction::ListFrame::setMultipleComment( const QString& comment )
+{
+  myMultipleComment = comment;
+  setNames( myNames );
+  updateComment();
+}
+
+/*!
+  \brief Update displayed comment.
+*/
+void QtxListAction::ListFrame::updateComment()
+{
+  QString com;
+  int selNum = selected();
+  if ( selNum > 1 )
+    com = myMultipleComment;
+  else if ( selNum > 0 && !mySingleComment.isEmpty() )
+    com = mySingleComment;
+  
+  if ( !com.isEmpty() )
+    com = com.arg( selNum );
+  
+  myComment->setText( com );
+}
+
+/*!
+  \brief Get preferable size for the list widget.
+  \return preferable size
+*/
+QSize QtxListAction::ListFrame::sizeHint() const
+{
+  return QSize( myList->fontMetrics().maxWidth() * charsNumber() + 10,
+                qMax( 1, linesNumber() ) * ( myList->fontMetrics().height() + 2 ) +
+                myComment->sizeHint().height() );
+}
+
+/*!
+  \brief Get preferable minimum size for the list widget.
+  \return preferable minimum size
+*/
+QSize QtxListAction::ListFrame::minimumSizeHint() const
+{
+  return QSize( myList->fontMetrics().maxWidth() * charsNumber() + 10,
+                qMax( 1, linesNumber() ) * ( myList->fontMetrics().height() + 2 ) +
+                myComment->sizeHint().height() );
+}
+
+/*!
+  \brief Validate the action.
+*/
+void QtxListAction::ListFrame::accept()
+{
+  int sel = selected();
+  if ( sel && myAction )
+    myAction->onMultiple( sel );
+}
+
+/*!
+  \brief Called when list widget is shown/hidden.
+  \param on if \c true, widget is shown, otherswise it is hidden
+*/
+void QtxListAction::ListFrame::setVisible( bool on )
+{
+  if ( on )
+  {
+    myList->setFocus();
+    myList->scrollToItem( myList->item( 0 ), QListWidget::PositionAtTop );
+    setSelected( 0 );
+    updateComment();
+  }
+
+  QMenu::setVisible( on );
+}
+
+/*!
+  \brief Process key press event.
+
+  The following keys are supported:
+  - Up/Down
+  - PageUp/PageDown
+  - Enter
+  - Escape
+
+  \param e key press event
+*/
+void QtxListAction::ListFrame::keyPressEvent( QKeyEvent* e )
+{
+  if ( e->type() == QEvent::KeyRelease )
+    return;
+
+  e->accept();
+
+  int selNum = selected();
+  switch( e->key() )
+  {
+  case Qt::Key_Up:
+    setSelected( qMax( 1, selNum - 1 ) );
+    break;
+  case Qt::Key_Down:
+    setSelected( qMax( 1, selNum + 1 ) );
+    break;
+  case Qt::Key_PageUp:
+    setSelected( qMax( 1, selNum - linesNumber() ) );
+    break;
+  case Qt::Key_PageDown:
+    setSelected( selNum += linesNumber() );
+    break;
+  case Qt::Key_Home:
+    setSelected( 1 );
+    break;
+  case Qt::Key_End:
+    setSelected( myList->count() );
+    break;
+  case Qt::Key_Return:
+    accept();
+    break;
+  case Qt::Key_Escape:
+    hide();
+    break;
+  }
+}
+
+/*!
+  \brief Process mouse events on the viewport of the list widget.
+  \param o object recieving event (viewport)
+  \param e event
+  \return \c true if further event processing should be stopped.
+*/
+bool QtxListAction::ListFrame::eventFilter( QObject* o, QEvent* e )
+{
+  bool res = true;
+
+  switch( e->type() )
+  {
+  case QEvent::MouseMove:
+    {
+      QMouseEvent* me = (QMouseEvent*)e;
+      if ( !myList->viewport()->rect().contains( me->pos() ) )
+        setSelected( 0 );
+      else if ( myList->itemAt( me->pos() ) )
+        setSelected( myList->row( myList->itemAt( me->pos() ) ) + 1 );
+    }
+    break;
+  case QEvent::MouseButtonRelease:
+    accept();
+  case QEvent::MouseButtonPress:
+  case QEvent::MouseButtonDblClick:
+    break;
+  case ScrollEvent::Scroll:
+    {
+      ScrollEvent* se = (ScrollEvent*)e;
+      QPoint pos = myList->viewport()->mapFromGlobal( QCursor::pos() );
+      if ( myList->viewport()->rect().contains( pos ) )
+      {
+        if ( myList->itemAt( pos ) )
+          setSelected( myList->row( myList->itemAt( pos ) ) + 1 );
+      }
+      else if ( se->isDown() )
+        setSelected( myList->row( myList->itemAt( myList->viewport()->rect().bottomLeft() -
+                                                  QPoint( 0, myList->fontMetrics().height() / 2 ) ) ) + 1 );
+      else
+        setSelected( myList->row( myList->itemAt( myList->viewport()->rect().topLeft() +
+                                                  QPoint( 0, myList->fontMetrics().height() / 2 ) ) ) + 1 );
+    }
+    break;
+  default:
+    res = false;
+    break;
+  }
+
+  if ( res )
+    return true;
+  else
+    return QMenu::eventFilter( o, e );
+}
+
+/*!
+  \brief Get number of selected names.
+  \return number of selected items
+*/
+int QtxListAction::ListFrame::selected() const
+{
+  int sel = 0;
+  QModelIndexList indexes = myList->selectionModel()->selectedRows();
+  for ( QModelIndexList::const_iterator it = indexes.begin(); it != indexes.end(); ++it )
+    sel = qMax( sel, (*it).row() + 1 );
+  
+  return sel;
+}
+
+/*!
+  \brief Set number of selected names.
+  \param lastSel number of items to be selected
+*/
+void QtxListAction::ListFrame::setSelected( const int lastSel )
+{
+  int last = qMin( lastSel, (int)myList->count() );
+
+  QItemSelection selection;
+  QItemSelectionModel* selModel = myList->selectionModel();
+
+  for ( int i = 0; i < last; i++ )
+    selection.select( selModel->model()->index( i, 0 ), selModel->model()->index( i, 0 ) );
+
+  selModel->select( selection, QItemSelectionModel::ClearAndSelect );
+  
+  int item = last - 1;
+
+  myList->scrollToItem( myList->item( item ) );
+  myList->clearFocus();
+
+  removePostedEvens( myList->viewport(), ScrollEvent::Scroll );
+
+  updateComment();
+}
+
+/*!
+  \brief Filter all events of specified type sent to specified object.
+  \param o object
+  \param type event type to be filtered
+*/
+void QtxListAction::ListFrame::removePostedEvens( QObject* o, int type )
+{
+  class Filter : public QObject
+  {
+  public:
+    Filter() : QObject( 0 ) {}
+    virtual bool eventFilter( QObject*, QEvent* )
+    {
+      return true;
+    }
+  };
+
+  Filter f;
+  o->installEventFilter( &f );
+  QApplication::sendPostedEvents( o, type );
+}
+
+/*!
+  \class QtxListAction
+  \brief Action with associated list of items.
+  
+  This class can be helpuful, for example, for creation of Undo/Redo
+  toolbar items which show list of available commands in the popup list box.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent object
+*/
+QtxListAction::QtxListAction( QObject* parent )
+: QWidgetAction( parent ),
+  myFrame( 0 )
+{
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+  \param icon action icon
+  \param menuText menu text
+  \param accel key accelerator
+  \param parent parent object
+*/
+QtxListAction::QtxListAction( const QIcon& icon, const QString& menuText, 
+                             int accel, QObject* parent )
+: QWidgetAction( parent ),
+  myFrame( 0 )
+{
+  setIcon( icon );
+  setText( menuText );
+  setShortcut( accel );
+
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+  \param menuText menu text
+  \param accel key accelerator
+  \param parent parent object
+*/
+QtxListAction::QtxListAction( const QString& menuText, int accel, QObject* parent )
+: QWidgetAction( parent ),
+  myFrame( 0 )
+{
+  setText( menuText );
+  setShortcut( accel );
+
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+  \param text action description text (tooltip)
+  \param menuText menu text
+  \param accel key accelerator
+  \param parent parent object
+*/
+QtxListAction::QtxListAction( const QString& text, const QString& menuText, 
+                             int accel, QObject* parent )
+: QWidgetAction( parent ),
+  myFrame( 0 )
+{
+  setText( menuText );
+  setShortcut( accel );
+  setToolTip( text );
+
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+  \param text action description text (tooltip)
+  \param icon action icon
+  \param menuText menu text
+  \param accel key accelerator
+  \param parent parent object
+*/
+QtxListAction::QtxListAction( const QString& text, const QIcon& icon, 
+                             const QString& menuText, int accel, QObject* parent )
+: QWidgetAction( parent ),
+  myFrame( 0 )
+{
+  setIcon( icon );
+  setText( menuText );
+  setShortcut( accel );
+  setToolTip( text );
+
+  initialize();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxListAction::~QtxListAction()
+{
+  delete myFrame;
+  myFrame = 0;
+}
+
+/*!
+  \brief Get popup mode.
+  \return current popup mode (QtxListAction::PopupMode)
+  \sa setPopupMode()
+*/
+int QtxListAction::popupMode() const
+{
+  return menu() ? SubMenu : Item;
+}
+
+/*!
+  \brief Set popup mode.
+  \param mode new popup mode (QtxListAction::PopupMode)
+  \sa popupMode()
+*/
+void QtxListAction::setPopupMode( const int mode )
+{
+  if ( mode == popupMode() )
+    return;
+
+  if ( mode == Item )
+  {
+    delete menu();
+    setMenu( 0 );
+  }
+  else
+    setMenu( new QMenu( 0 ) );
+
+  onChanged();
+}
+
+/*!
+  \brief Get current list of names.
+  \return list of names
+*/
+QStringList QtxListAction::names() const
+{
+  QStringList lst;
+  if ( myFrame )
+    lst = myFrame->names();
+  return lst;
+}
+
+/*!
+  \brief Add names to the list.
+
+  Truncates each name to fit the frame width.
+  Method setCharsNumber() can be used to change
+  the frame width (in characters).
+
+  \param names list of names to be added
+  \param clear if \c true, remove the old contents from the list
+  \sa setCharsNumber()
+*/
+void QtxListAction::addNames( const QStringList& names, bool clear )
+{
+  if ( !myFrame )
+    return;
+
+  if ( clear )
+    myFrame->clear();
+
+  myFrame->addNames( names );
+
+  onChanged();
+}
+
+/*!
+  \brief Get maximum numer of lines shown without activation of vertical scroll bar.
+  \return number of lines
+  \sa setLinesNumber(), charsNumber(), setCharsNumber()
+*/
+int QtxListAction::linesNumber() const
+{
+  return myFrame->linesNumber();
+}
+
+/*!
+  \brief Get maximum numer of characters in the line.
+
+  If the name length is greater than this value, it will be truncated.
+
+  \return number of characters
+  \sa setCharsNumber(), linesNumber(), setLinesNumber()
+*/
+int QtxListAction::charsNumber() const
+{
+  return myFrame->charsNumber();
+}
+
+/*!
+  \brief Set maximum numer of lines shown without activation of vertical scroll bar.
+  \param nlines number of lines (5 by default)
+  \sa linesNumber(), charsNumber(), setCharsNumber()
+*/
+void QtxListAction::setLinesNumber( const int nlines )
+{
+  myFrame->setLinesNumber( nlines );
+}
+
+/*!
+  \brief Set maximum numer of characters in the line.
+
+  If the name length is greater than this value, it will be truncated.
+
+  \param maxChars number of characters (5 by default)
+  \sa charsNumber(), linesNumber(), setLinesNumber()
+*/
+
+void QtxListAction::setCharsNumber( const int nchars )
+{
+  myFrame->setCharsNumber( nchars );
+}
+
+/*!
+  \brief Set the format Qt string for comments displayed under the list
+         of actions for one action and for several actions.
+
+  Example: "Undo %1 actions" format string will work as "Undo 3 actions"
+  when 3 actions are selected. The default format string is "%1".
+
+  \param c single action comment format
+  \param c multiple actions comment format
+*/
+void QtxListAction::setComment( const QString& c, const QString& sc )
+{
+  if ( !myFrame )
+    return;
+
+  myFrame->setSingleComment( sc.isEmpty() ? c : sc );
+  myFrame->setMultipleComment( c );
+}
+
+/*!
+  \brief Create action widget.
+
+  This function is called whenever the action is added 
+  to a container widget that supports custom widgets like menu or toolbar.
+  
+  \param parent container widget the action is added to
+  \return tool button for toolbar and 0 otherwise
+*/
+QWidget* QtxListAction::createWidget( QWidget* parent )
+{
+  if ( parent && parent->inherits( "QMenu" ) )
+    return 0;
+
+  QToolButton* tb = new QToolButton( parent );
+  tb->setText( text() );
+  tb->setIcon( icon() );
+  tb->setPopupMode( QToolButton::MenuButtonPopup );
+  tb->setMenu( myFrame );
+  tb->setEnabled( isEnabled() && !names().isEmpty() );
+  tb->setToolTip( toolTip() );
+  connect( tb, SIGNAL( clicked( bool ) ), this, SLOT( onSingle( bool ) ) );
+
+  return tb;
+}
+
+/*!
+  \brief Destroy action widget.
+
+  This function is called whenever the action is removed
+  from a container widget that supports custom widgets like menu or toolbar.
+  
+  \param widget container widget the action is removed from
+*/
+void QtxListAction::deleteWidget( QWidget* widget )
+{
+  delete widget;
+}
+
+/*!
+  \brief Initialize the action.
+*/
+void QtxListAction::initialize()
+{
+  setPopupMode( Item );
+  
+  myFrame = new QtxListAction::ListFrame( this, 0 );
+  myFrame->setLinesNumber( 7 );
+  myFrame->setCharsNumber( 5 );
+
+  myFrame->hide();
+
+  connect( this, SIGNAL( changed() ), this, SLOT( onChanged() ) );
+  connect( this, SIGNAL( triggered( bool ) ), this, SLOT( onSingle( bool ) ) );
+}
+
+/*!
+  \brief Called the action contents is changed.
+*/
+void QtxListAction::onChanged()
+{
+  QStringList lst = myFrame->names();
+
+  if ( menu() )
+  {
+    menu()->clear();
+    for ( QStringList::iterator iter = lst.begin(); iter != lst.end(); ++iter )
+    {
+      QAction* a = new QAction( *iter, menu() );
+      menu()->addAction( a );
+      connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onTriggered( bool ) ) );
+    }
+  }
+
+  QList<QWidget*> widList = createdWidgets();
+  for ( QList<QWidget*>::iterator it = widList.begin(); it != widList.end(); ++it )
+  {
+    (*it)->setEnabled( isEnabled() && !lst.isEmpty() );
+    QToolButton* tb = ::qobject_cast<QToolButton*>( *it );
+    if ( tb )
+    {
+      tb->setText( text() );
+      tb->setIcon( icon() );
+      tb->setToolTip( toolTip() );
+    }
+  }
+}
+
+/*!
+  \brief Called when a user click action button.
+  \param on (not used)
+*/
+
+void QtxListAction::onSingle( bool /*on*/ )
+{
+  onMultiple( 1 );
+}
+
+/*!
+  \brief Called when multiple items are selected. 
+*/
+void QtxListAction::onMultiple( const int numActions )
+{
+  if ( myFrame )
+    myFrame->hide();
+
+  if ( numActions > 0 )
+    emit activated( numActions );
+}
+
+/*!
+  \brief Called when user activates an items in the popup sub menu. 
+  \param on (not used)
+*/
+void QtxListAction::onTriggered( bool /*on*/ )
+{
+  if ( !menu() )
+    return;
+
+  QList<QAction*> actionList = menu()->actions();
+  int idx = actionList.indexOf( ::qobject_cast<QAction*>( sender() ) );
+  if ( idx < 0 )
+    return;
+
+  emit activated( idx + 1 );
+}
+
+/*!
+  \fn QtxListAction::activated(int numItems );
+  \brief This signal is emitted when an action is activated.
+  \param numItems number of items being selected in the action list.
+*/
diff --git a/src/Qtx/QtxListAction.h b/src/Qtx/QtxListAction.h
new file mode 100755 (executable)
index 0000000..1826985
--- /dev/null
@@ -0,0 +1,96 @@
+// 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
+//
+// File:      QtxListAction.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXLISTACTION_H
+#define QTXLISTACTION_H
+
+#include "Qtx.h"
+
+#include <QStringList>
+#include <QWidgetAction>
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxListAction : public QWidgetAction
+{
+  Q_OBJECT
+
+  class ListFrame;
+  class ListWidget;
+  class ScrollEvent;
+
+public:
+  //! Popup mode
+  enum { 
+    Item,         //!< action is added to popup menu as menu item
+    SubMenu       //!< action is added to popup menu as sub menu with list of items
+  } PopupMode;
+
+public:
+  QtxListAction( QObject* = 0 );
+  QtxListAction( const QString&, int, QObject* );
+  QtxListAction( const QString&, const QString&, int, QObject* );
+  QtxListAction( const QIcon&, const QString&, int, QObject* );
+  QtxListAction( const QString&, const QIcon&, const QString&, int, QObject* );
+  virtual ~QtxListAction();
+
+  int              popupMode() const;
+  void             setPopupMode( const int );
+
+  QStringList      names() const;
+  void             addNames( const QStringList&, bool = true );
+  void             setComment( const QString&, const QString& = QString() );
+
+  int              linesNumber() const;
+  int              charsNumber() const;
+
+  void             setLinesNumber( const int );
+  void             setCharsNumber( const int );
+
+signals:
+  void             activated( int );
+
+private slots:
+  void             onChanged();
+  void             onMultiple( const int );
+  void             onSingle( bool = false );
+  void             onTriggered( bool = false );
+
+protected:
+  virtual QWidget* createWidget( QWidget* );
+  virtual void     deleteWidget( QWidget* );
+
+private:
+  void             initialize();
+
+private:
+  ListFrame*       myFrame;   //!< list of actions shown as submenu
+
+  friend class QtxListAction::ListFrame;
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
index 47a8d5628ad0b1c2466bb84139855ba162e31ac4..e04d32fdfeb381b26161b8dc92e4f8ee1b8a5e93 100644 (file)
@@ -16,6 +16,9 @@
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+// File:      QtxLogoMgr.cxx
+// Author:    Sergey TELKOV
+
 #include "QtxLogoMgr.h"
 
 #include <QLabel>
@@ -153,12 +156,12 @@ void QtxLogoMgr::LogoBox::updateContents()
   base->setMargin( 0 );
   base->setSpacing( 3 );
 
-  if ( myCornWid )
-    base->addWidget( myCornWid );
-
   for ( QList<QLabel*>::const_iterator it = myLabels.begin(); it != myLabels.end(); ++it )
     base->addWidget( *it );
 
+  if ( myCornWid )
+    base->addWidget( myCornWid );
+
   QApplication::sendPostedEvents();
 }
 
@@ -406,7 +409,7 @@ void QtxLogoMgr::generate()
 int QtxLogoMgr::find( const QString& id ) const
 {
   int idx = -1;
-  for ( uint i = 0; i < myLogos.count() && idx < 0; i++ )
+  for ( int i = 0; i < myLogos.count() && idx < 0; i++ )
   {
     if ( myLogos.at( i ).id == id )
       idx = i;
index ff43fddaa9aca7e51290b34f7c53ba8301440da2..73b49ee5ad4df75bae5d4b75cdfaad63b5b9361b 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#ifndef QTX_LOGOMGR_H
-#define QTX_LOGOMGR_H
+// File:      QtxLogoMgr.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXLOGOMGR_H
+#define QTXLOGOMGR_H
 
 #include "Qtx.h"
 
@@ -66,12 +69,12 @@ private:
   void       movies( const QString&, QList<QMovie*>& ) const;
 
 private:
-  LogoBox*   myBox;
-  LogoList   myLogos;
+  LogoBox*   myBox;         //!< widget containing logox
+  LogoList   myLogos;       //!< list of logo data
 };
 
 #ifdef WIN32
 #pragma warning( default : 4251 )
 #endif
 
-#endif
+#endif // QTXLOGOMGR_H
index bb4dca63829c73b8271c91b61aa7ff8c4d66e463..f8a5dd9b0e034a64484b94454df9a3addd809a1a 100755 (executable)
@@ -24,7 +24,6 @@
 
 #include "QtxAction.h"
 
-#include <QMap>
 #include <QStringList>
 
 class QtxResourceMgr;
@@ -37,10 +36,13 @@ class QTX_EXPORT QtxMRUAction : public QtxAction
 {
   Q_OBJECT
 
-  Q_PROPERTY( int visibleCount READ visibleCount WRITE setVisibleCount )
-
 public:
-  enum { MoveFirst, MoveLast, AddFirst, AddLast };
+  //! Items insertion policy
+  typedef enum { MoveFirst,   //!< put the specified item to the beginning
+                MoveLast,    //!< put the specified item to the end
+                AddFirst,    //!< if specified item doesn't exist, add it to the beginning
+                AddLast      //!< if specified item doesn't exist, add it to the end
+  } InsertionMode;
 
 public:
   QtxMRUAction( QObject* = 0 );
@@ -68,7 +70,7 @@ public:
   virtual void loadLinks( QtxResourceMgr*, const QString&, const bool = true );
   virtual void saveLinks( QtxResourceMgr*, const QString&, const bool = true ) const;
 
-Q_SIGNALS:
+signals:
   void         activated( const QString& );
 
 private slots:
@@ -79,9 +81,9 @@ private:
   void         updateMenu();
 
 private:
-  QStringList  myLinks;
-  int          myVisCount;
-  int          myInsertMode;
+  QStringList  myLinks;        //!< most recent used items
+  int          myVisCount;     //!< number of visible MRU items
+  int          myInsertMode;   //!< items insertion policy
 };
 
 #endif
index 8ecc6e96c5c64766419ffd6790392c18d7fe4741..7ca329ac2e8ef97af7f0206c0384f554cafb79b9 100644 (file)
 #include "QtxToolBar.h"
 #include "QtxResourceMgr.h"
 
-#include <QtGui/qevent.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qmenubar.h>
-#include <QtGui/qstatusbar.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qdesktopwidget.h>
+#include <QEvent>
+#include <QMenuBar>
+#include <QStatusBar>
+#include <QApplication>
+#include <QDesktopWidget>
 
 /*!
-    Class: QtxMainWindow::Filter [Internal]
-    Descr: Internal object with event filter for QtxMainWindow.
+  \class QtxMainWindow::Filter
+  \internal
+  \brief Internal object used to filter child removal events for 
+         specified widget from parent widget.
 */
 
 class QtxMainWindow::Filter : public QObject
@@ -45,30 +46,39 @@ public:
   virtual bool eventFilter( QObject*, QEvent* );
 
 private:
-  QMainWindow* myMain;
-  QWidget*     myWidget;
+  QMainWindow* myMain;      //!< parent main window
+  QWidget*     myWidget;    //!< widget being watched
 };
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param wid widget to be watched
+  \param mw parent main window
+  \param parent parent object (in terms of QObject)
 */
 QtxMainWindow::Filter::Filter( QWidget* wid, QtxMainWindow* mw, QObject* parent )
 : QObject( parent ),
-myMain( mw ),
-myWidget( wid )
+  myMain( mw ),
+  myWidget( wid )
 {
   QApplication::instance()->installEventFilter( this );
 };
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxMainWindow::Filter::~Filter()
 {
 }
 
 /*!
-  Custom event filter
+  \brief Event filter.
+
+  Watches for the specified widget and prevents its removal from the
+  parent main window.
+
+  \param o recevier object
+  \param e event
 */
 bool QtxMainWindow::Filter::eventFilter( QObject* o, QEvent* e )
 {
@@ -79,21 +89,27 @@ bool QtxMainWindow::Filter::eventFilter( QObject* o, QEvent* e )
   return QObject::eventFilter( o, e );
 }
 
+
+/*!
+  \class QtxMainWindow
+  \brief Enhanced main window which supports dockable menubar and status bar
+         plus geometry saving/restoring.
+*/
+
 /*!
-    Class: QtxMainWindow [Public]
-    Descr: Main window with support of dockable menubar/status bar
-           and geometry store/retrieve.
+  \brief Constructor.
+  \param parent parent widget
+  \param f widget flags (Qt::WindowFlags)
 */
 QtxMainWindow::QtxMainWindow( QWidget* parent, Qt::WindowFlags f )
 : QMainWindow( parent, f ),
-myMode( -1 ),
-myMenuBar( 0 ),
-myStatusBar( 0 )
+  myMenuBar( 0 ),
+  myStatusBar( 0 )
 {
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxMainWindow::~QtxMainWindow()
 {
@@ -102,16 +118,18 @@ QtxMainWindow::~QtxMainWindow()
 }
 
 /*!
-  \return true if menu bar exists
+  \brief Check if the menu bar is dockable.
+  \return \c true if dockable menu bar exists
 */
 bool QtxMainWindow::isDockableMenuBar() const
 {
-  return myMenuBar;
+  return myMenuBar != 0;
 }
 
 /*!
-  Creates or deletes menu bar
-  \param on - if it is true, then to create, otherwise - to delete
+  \brief Set menu bar dockable/undockable.
+  \param on if \c true, make menu bar dockable, otherwise 
+            make menu bar undockable
 */
 void QtxMainWindow::setDockableMenuBar( const bool on )
 {
@@ -147,7 +165,8 @@ void QtxMainWindow::setDockableMenuBar( const bool on )
 }
 
 /*!
-  \return true if status bar exists
+  \brief Check if the status bar is dockable.
+  \return \c true if dockable status bar exists
 */
 bool QtxMainWindow::isDockableStatusBar() const
 {
@@ -155,8 +174,9 @@ bool QtxMainWindow::isDockableStatusBar() const
 }
 
 /*!
-  Creates or deletes status bar
-  \param on - if it is true, then to create, otherwise - to delete
+  \brief Set status bar dockable/undockable.
+  \param on if \c true, make status bar dockable, otherwise 
+            make status bar undockable
 */
 void QtxMainWindow::setDockableStatusBar( const bool on )
 {
@@ -193,7 +213,11 @@ void QtxMainWindow::setDockableStatusBar( const bool on )
   }
 }
 
-QString QtxMainWindow::saveGeometry() const
+/*!
+  \brief Dump main window geometry to the string.
+  \return string represenation of the window geometry
+*/
+QString QtxMainWindow::storeGeometry() const
 {
   QRect frame = frameGeometry();
   QRect screen = QApplication::desktop()->availableGeometry( this );
@@ -236,7 +260,11 @@ QString QtxMainWindow::saveGeometry() const
   return geom;
 }
 
-void QtxMainWindow::loadGeometry( const QString& str )
+/*!
+  \brief Restore main window geometry from the string.
+  \param str string represenation of the window geometry
+*/
+void QtxMainWindow::retrieveGeometry( const QString& str )
 {
   QString geom = str;
   geom.remove( '\t' );
@@ -268,7 +296,7 @@ void QtxMainWindow::loadGeometry( const QString& str )
       rect.setSize( QSize( w, h ) );
   }
 
-  QRegExp posRx( "([+|-]\\d+\%?)\\s*([+|-]\\d+\%?)" );
+  QRegExp posRx( "([+|-]\\d+%?)\\s*([+|-]\\d+%?)" );
   if ( posRx.indexIn( geom ) != -1 )
   {
     int x = -1;
@@ -316,6 +344,19 @@ void QtxMainWindow::loadGeometry( const QString& str )
     setWindowState( state );
 }
 
+/*!
+  \brief Retrieve numerical value from the string.
+  
+  Numerical value in the string have the structure [+|-]\d*[%],
+  that is one or more digits which can start from "+" or "-" and
+  can end with "%" symbol.
+
+  \param str string being converted
+  \param num returning value (> 0)
+  \param percent if string ends with "%" this parameter is equal to \c true after
+         returning from the function
+  \return -1 if value < 0, 1 if value > 0 and 0 in case of error
+*/
 int QtxMainWindow::geometryValue( const QString& str, int& num, bool& percent ) const
 {
   num = -1;
@@ -340,158 +381,11 @@ int QtxMainWindow::geometryValue( const QString& str, int& num, bool& percent )
 }
 
 /*!
-  Retrieve the geometry information from the specified resource manager section.
-  \param resMgr - instance of ersource manager
-  \param section - section name
-*/
-void QtxMainWindow::loadGeometry( QtxResourceMgr* resMgr, const QString& section )
-{
-  QString sec = section.trimmed();
-  if ( !resMgr || sec.isEmpty() )
-    return;
-  /*
-  int winState = -1;
-  if ( !resMgr->value( sec, "state", winState ) )
-  {
-    QString stateStr;
-    if ( resMgr->value( sec, "state", stateStr ) )
-      winState = windowState( stateStr );
-  }
-
-  int win_w = resMgr->integerValue( sec, "width", width() );
-  int win_h = resMgr->integerValue( sec, "height", height() );
-
-  int winPosX = windowPosition( resMgr->stringValue( sec, QString( "pos_x" ), QString::null ) );
-  int winPosY = windowPosition( resMgr->stringValue( sec, QString( "pos_y" ), QString::null ) );
-
-  QWidget* desk = QApplication::desktop();
-
-  int win_x = 0;
-  if ( winPosX == WP_Absolute )
-    win_x = resMgr->integerValue( sec, "pos_x", x() );
-  else if ( desk )
-    win_x = relativeCoordinate( winPosX, desk->width(), win_w );
-
-  int win_y = 0;
-  if ( winPosX == WP_Absolute )
-    win_y = resMgr->integerValue( sec, "pos_y", y() );
-  else if ( desk )
-    win_y = relativeCoordinate( winPosY, desk->height(), win_h );
-
-  bool vis = isVisibleTo( parentWidget() );
-
-  resize( win_w, win_h );
-  move( win_x, win_y );
-
-  myMode = -1;
-  */
-/*
-  if ( vis )
-    QApplication::postEvent( this, new QEvent( QEvent::User, (void*)winState ) );
-  else
-    myMode = winState;
-*/
-}
-
-/*!
-  Shows main window
-*/
-void QtxMainWindow::show()
-{
-/*
-  if ( myMode != -1 )
-    QApplication::postEvent( this, new QCustomEvent( QEvent::User, (void*)myMode ) );
-*/
-  myMode = -1;
-
-  QMainWindow::show();
-}
-
-/*!
-  Handler of custom events
-*/
-void QtxMainWindow::customEvent( QEvent* e )
-{
-  QMainWindow::customEvent( e );
-
-  int mode = WS_Normal;
-//  int mode = (int)e->data();
-  switch ( mode )
-  {
-  case WS_Normal:
-    showNormal();
-    break;
-  case WS_Minimized:
-    showMinimized();
-    break;
-  case WS_Maximized:
-    showMaximized();
-    break;
-  }
-}
-
-/*!
-  \return relative co-ordinate by two points
-  \param type - type of result: WP_Center (center), WP_Left (left), WP_Right (right)
-  \param wh - left point
-  \param WH - right point
-*/
-/*
-int QtxMainWindow::relativeCoordinate( const int type, const int WH, const int wh ) const
-{
-  int res = 0;
-  switch ( type )
-  {
-  case WP_Center:
-    res = ( WH - wh ) / 2;
-    break;
-  case WP_Left:
-    res = 0;
-    break;
-  case WP_Right:
-    res = WH - wh;
-    break;
-  }
-  return res;
-}
-*/
-
-/*!
-  Store the geometry information into the specified resource manager section.
-  \param resMgr - instance of ersource manager
-  \param section - section name
-*/
-void QtxMainWindow::saveGeometry( QtxResourceMgr* resMgr, const QString& section ) const
-{
-  QString sec = section.trimmed();
-  if ( !resMgr || sec.isEmpty() )
-    return;
-  /*
-  resMgr->setValue( sec, "pos_x", pos().x() );
-  resMgr->setValue( sec, "pos_y", pos().y() );
-  resMgr->setValue( sec, "width", width() );
-  resMgr->setValue( sec, "height", height() );
-
-  int winState = WS_Normal;
-  if ( isMinimized() )
-    winState = WS_Minimized;
-  else if ( isMaximized() )
-    winState = WS_Maximized;
-
-  resMgr->setValue( sec, "state", winState );
-  */
-}
+  \brief Called when child object (menu bar, status bar) is destroyed.
+  
+  Clears internal pointer to prevent crashes.
 
-/*!
-  Custom event filter
-*/
-bool QtxMainWindow::eventFilter( QObject* o, QEvent* e )
-{
-  return QMainWindow::eventFilter( o, e );
-}
-
-/*!
-  SLOT: called on object destroyed, clears internal fields in case of deletion of menu bar or status bar
+  \param obj signal sender (object being destroyed)
 */
 void QtxMainWindow::onDestroyed( QObject* obj )
 {
@@ -514,58 +408,3 @@ void QtxMainWindow::onDestroyed( QObject* obj )
   }
 }
 
-/*!
-  \return flag of window state by it's name
-  \param str - name of flag
-*/
-/*
-int QtxMainWindow::windowState( const QString& str ) const
-{
-  static QMap<QString, int> winStateMap;
-  if ( winStateMap.isEmpty() )
-  {
-    winStateMap["normal"]    = WS_Normal;
-    winStateMap["min"]       = WS_Minimized;
-    winStateMap["mini"]      = WS_Minimized;
-    winStateMap["minimized"] = WS_Minimized;
-    winStateMap["max"]       = WS_Maximized;
-    winStateMap["maxi"]      = WS_Maximized;
-    winStateMap["maximized"] = WS_Maximized;
-    winStateMap["hidden"]    = WS_Hidden;
-    winStateMap["hided"]     = WS_Hidden;
-    winStateMap["hide"]      = WS_Hidden;
-    winStateMap["invisible"] = WS_Hidden;
-  }
-
-  int res = -1;
-  QString stateStr = str.trimmed().toLower();
-  if ( winStateMap.contains( stateStr ) )
-    res = winStateMap[stateStr];
-  return res;
-}
-*/
-
-/*!
-  \return flag of position by it's name
-  \param str - name of position
-*/
-/*
-int QtxMainWindow::windowPosition( const QString& str ) const
-{
-  static QMap<QString, int> winPosMap;
-  if ( winPosMap.isEmpty() )
-  {
-    winPosMap["center"] = WP_Center;
-    winPosMap["left"]   = WP_Left;
-    winPosMap["right"]  = WP_Right;
-    winPosMap["top"]    = WP_Top;
-    winPosMap["bottom"] = WP_Bottom;
-  }
-
-  int res = WP_Absolute;
-  QString posStr = str.trimmed().toLower();
-  if ( winPosMap.contains( posStr ) )
-    res = winPosMap[posStr];
-  return res;
-}
-*/
index 833a95e71890edcb2d668796fe9a2c8f5ee94ea5..10accc407b3deee5c2e759d8639ce48b05572a39 100644 (file)
@@ -24,9 +24,8 @@
 
 #include "Qtx.h"
 
-#include <QtGui/qmainwindow.h>
+#include <QMainWindow>
 
-class QDockWindow;
 class QtxResourceMgr;
 
 class QTX_EXPORT QtxMainWindow : public QMainWindow
@@ -35,9 +34,6 @@ class QTX_EXPORT QtxMainWindow : public QMainWindow
 
   class Filter;
 
-  enum { WS_Normal, WS_Minimized, WS_Maximized, WS_Hidden };
-  enum { WP_Absolute, WP_Center, WP_Left, WP_Right, WP_Top = WP_Left, WP_Bottom = WP_Right };
-
 public:
   QtxMainWindow( QWidget* = 0, Qt::WindowFlags = 0 );
   virtual ~QtxMainWindow();
@@ -48,33 +44,18 @@ public:
   bool              isDockableStatusBar() const;
   void              setDockableStatusBar( const bool );
 
-  QString           saveGeometry() const;
-  void              loadGeometry( const QString& );
-
-  void              loadGeometry( QtxResourceMgr*, const QString& );
-  void              saveGeometry( QtxResourceMgr*, const QString& ) const;
-
-  virtual bool      eventFilter( QObject*, QEvent* );
-
-public slots:
-  virtual void      show();
-
-protected:
-  virtual void      customEvent( QEvent* );
+  QString           storeGeometry() const;
+  void              retrieveGeometry( const QString& );
 
 private slots:
   void              onDestroyed( QObject* );
 
 private:
   int               geometryValue( const QString&, int&, bool& ) const;
-//  int               windowState( const QString& ) const;
-//  int               windowPosition( const QString& ) const;
-//  int               relativeCoordinate( const int, const int, const int ) const;
 
 private:
-  int               myMode;
-  QToolBar*         myMenuBar;
-  QToolBar*         myStatusBar;
+  QToolBar*         myMenuBar;       //!< dockable menu bar
+  QToolBar*         myStatusBar;     //!< dockable status bar
 };
 
-#endif
+#endif // QTXMAINWINDOW_H
diff --git a/src/Qtx/QtxMap.h b/src/Qtx/QtxMap.h
new file mode 100644 (file)
index 0000000..403fc32
--- /dev/null
@@ -0,0 +1,210 @@
+// 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
+//
+// File:      QtxMap.h
+// Author:    Vadim SANDLER
+
+#ifndef QTXMAP_H
+#define QTXMAP_H
+
+template <class Key, class Value> class IMap;
+template <class Key, class Value> class IMapIterator;
+template <class Key, class Value> class IMapConstIterator;
+
+/*!
+  \brief Indexed map template class.
+*/
+template <class Key, class Value> class IMap
+{
+public:
+  typedef IMapIterator<Key,Value>      Iterator;
+  typedef IMapConstIterator<Key,Value> ConstIterator;
+
+public:
+  IMap() {}
+  IMap( const IMap& m ) : myKeys( m.myKeys ), myData( m.myData ) {}
+  IMap& operator=( const IMap& m ) { myKeys = m.myKeys; myData = m.myData; return *this; }
+  
+  int  count() const   { return myData.count(); }
+  int  size() const    { return myData.count(); }
+  bool empty() const   { return myData.empty(); }
+  bool isEmpty() const { return myData.empty(); }
+  
+  void clear() { myKeys.clear(); myData.clear(); }
+  
+  QList<Key>   keys()   const { return myKeys; }
+  QList<Value> values() const { QList<Value> l; for ( int i = 0; i < count(); i++ ) l.append( value( i ) ); return l; }
+  bool         contains ( const Key& key ) const { return myData.contains( key ); }
+  
+  Iterator      begin()       { return Iterator( this );               }
+  Iterator      end()         { return Iterator( this, count() );      }
+  ConstIterator begin() const { return ConstIterator( this );          }
+  ConstIterator end() const   { return ConstIterator( this, count() ); }
+  
+  Iterator insert( const Key& key, const Value& value, bool overwrite = true )
+  { 
+    if ( myData.find( key ) == myData.end() || overwrite )
+    {
+      if ( myData.find( key ) != myData.end() && overwrite )
+        myKeys.removeAt( myKeys.indexOf( key ) );
+      myKeys.append( key );
+      myData[key] = value;
+    }
+    return Iterator( this, index( key ) );
+  }
+
+  Iterator replace( const Key& key, const Value& value )
+  { 
+    if ( myData.find( key ) == myData.end() )
+      myKeys.append( key );
+    myData[ key ] = value;
+    return Iterator( this, index( key ) );
+  }
+
+  int           index( const Key& key ) const { return myKeys.indexOf( key );      }
+  Iterator      at( const int index )         { return Iterator( this, index );      }
+  ConstIterator at( const int index ) const   { return ConstIterator( this, index ); }
+
+  Key& key( const int index )
+  {
+    if ( index < 0 || index >= (int)myKeys.count() ) 
+      return dummyKey;
+    return myKeys[index];
+  }
+
+  Value value( const int index )
+  {
+    if ( index < 0 || index >= (int)myKeys.count() ) 
+      return dummyValue;
+    return myData[ myKeys[index] ];
+  }
+
+  Value operator[]( const Key& key )
+  {
+    if ( myData.find( key ) == myData.end() )
+      insert( key, Value() );
+    return myData[ key ];
+  }
+
+  const Value operator[]( const Key& key ) const
+  {
+    if ( myData.find( key ) == myData.end() )
+      return dummyValue;
+    return myData[key];
+  }
+
+  void erase( Iterator it )     { remove( it );    }
+  void erase( const Key& key )  { remove( key );   }
+  void erase( const int index ) { remove( index ); }
+  void remove( Iterator it )    { if ( it.myMap != this ) return; remove( it.myIndex ); }
+  void remove( const Key& key ) { remove( index( key ) ); }
+  void remove( const int index )
+  {
+    if ( index >= 0 && index < (int)myKeys.count() )
+    {
+      myData.remove( myKeys[index] );
+      myKeys.removeAt( index );
+    }
+  }
+
+private:
+  QList<Key>      myKeys;
+  QMap<Key,Value> myData;
+  Key             dummyKey;
+  Value           dummyValue;
+
+  friend class IMapIterator<Key,Value>;
+  friend class IMapConstIterator<Key,Value>;
+};
+
+/*!
+  \brief Indexed map iterator template class.
+*/
+template <class Key, class Value> class IMapIterator
+{
+public:
+  IMapIterator()                           : myMap( 0 ), myIndex( 0 )                                   { init(); }
+  IMapIterator( const IMap<Key,Value>* m ) : myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( 0 ) { init(); }
+  IMapIterator( const IMapIterator& i )    : myMap( i.myMap ), myIndex( i.myIndex )                     { init(); }
+
+  bool operator==( const IMapIterator& i ) { return !operator!=( i );                                   }
+  bool operator!=( const IMapIterator& i ) { return !myMap || myMap != i.myMap || myIndex != i.myIndex; }
+  
+  operator bool() const { return myIndex >= 0; }
+
+  const Key&   key() const  { return myMap->key( myIndex );   }
+  Value&       value()       { return myMap->value( myIndex ); }
+  const Value& value() const { return myMap->value( myIndex ); }
+
+  Value& operator*() { return value(); }
+
+  IMapIterator& operator++()      { myIndex++; init(); return *this;                     }
+  IMapIterator  operator++( int ) { IMapIterator i = *this; myIndex++; init(); return i; }
+  IMapIterator& operator--()      { myIndex--; init(); return *this;                     }
+  IMapIterator  operator--( int ) { IMapIterator i = *this; myIndex--; init(); return i; }
+
+private:
+  IMapIterator( const IMap<Key,Value>* m, const int index ) : myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( index ) { init(); }
+  void init() { if ( !myMap || myIndex >= myMap->count() ) myIndex = -1; }
+
+private:
+  IMap<Key,Value>* myMap;
+  int              myIndex;
+
+  friend class IMap<Key, Value>;
+  friend class IMapConstIterator<Key, Value>;
+};
+
+/*!
+  \brief Indexed map const iterator template class.
+*/
+template <class Key, class Value> class IMapConstIterator
+{
+public:
+  IMapConstIterator()                                    : myMap( 0 ), myIndex( 0 )                                    { init(); }
+  IMapConstIterator( const IMap<Key,Value>* m )          : myMap( const_cast< IMap<Key,Value>* >( m )  ), myIndex( 0 ) { init(); }
+  IMapConstIterator( const IMapConstIterator& i )        : myMap( i.myMap ), myIndex( i.myIndex )                      { init(); }
+  IMapConstIterator( const IMapIterator<Key, Value>& i ) : myMap( i.myMap ), myIndex( i.myIndex )                      { init(); }
+  
+  bool operator==( const IMapConstIterator& i ) { return !operator!=( i );                                   }
+  bool operator!=( const IMapConstIterator& i ) { return !myMap || myMap != i.myMap || myIndex != i.myIndex; }
+  
+  operator bool() const { return myIndex >= 0; }
+  
+  const Key&   key() const  { return myMap->key( myIndex );   }
+  const Value value() const { return myMap->value( myIndex ); }
+  
+  const Value operator*() const { return value(); }
+
+  IMapConstIterator& operator++()      { myIndex++; init(); return *this;                          }
+  IMapConstIterator  operator++( int ) { IMapConstIterator i = *this; myIndex++; init(); return i; }
+  IMapConstIterator& operator--()      { myIndex--; init(); return *this;                          }
+  IMapConstIterator  operator--( int ) { IMapConstIterator i = *this; myIndex--; init(); return i; }
+  
+private:
+  IMapConstIterator( const IMap<Key,Value>* m, const int index ): myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( index ) { init(); }
+  void init() { if ( !myMap || myIndex >= myMap->count() ) myIndex = -1; }
+  
+private:
+  IMap<Key,Value>* myMap;
+  int              myIndex;
+  
+  friend class IMap<Key,Value>;
+};
+
+#endif // QTXMAP_H
diff --git a/src/Qtx/QtxPagePrefMgr.cxx b/src/Qtx/QtxPagePrefMgr.cxx
new file mode 100644 (file)
index 0000000..5697e44
--- /dev/null
@@ -0,0 +1,3316 @@
+// 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
+//
+// File:      QtxPagePrefMgr.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxPagePrefMgr.h"
+
+#include "QtxGridBox.h"
+#include "QtxFontEdit.h"
+#include "QtxGroupBox.h"
+#include "QtxComboBox.h"
+#include "QtxIntSpinBox.h"
+#include "QtxColorButton.h"
+#include "QtxDoubleSpinBox.h"
+
+#include <QEvent>
+#include <QLayout>
+#include <QToolBox>
+#include <QLineEdit>
+#include <QTextEdit>
+#include <QCheckBox>
+#include <QSplitter>
+#include <QTabWidget>
+#include <QListWidget>
+#include <QDateTimeEdit>
+#include <QStackedWidget>
+
+/*!
+  \class QtxPagePrefMgr
+  \brief GUI implementation of the QtxPreferenceMgr class: preferences manager.
+*/
+
+/*!
+  \brief Constructor.
+  \param resMgr resource manager
+  \param parent parent widget
+*/
+QtxPagePrefMgr::QtxPagePrefMgr( QtxResourceMgr* resMgr, QWidget* parent )
+: QFrame( parent ),
+  QtxPreferenceMgr( resMgr ),
+  myInit( false )
+{
+  myBox = new QtxGridBox( 1, Qt::Horizontal, this, 0 );
+  QVBoxLayout* base = new QVBoxLayout( this );
+  base->setMargin( 0 );
+  base->setSpacing( 0 );
+  base->addWidget( myBox );
+}
+
+/*!
+  \brief Destructor
+*/
+QtxPagePrefMgr::~QtxPagePrefMgr()
+{
+}
+
+/*!
+  \brief Get recommended size for the widget.
+  \return recommended widget size
+*/
+QSize QtxPagePrefMgr::sizeHint() const
+{
+  initialize();
+
+  return QFrame::sizeHint();
+}
+
+/*!
+  \brief Get recommended minimum size for the widget.
+  \return recommended minimum widget size
+*/
+QSize QtxPagePrefMgr::minimumSizeHint() const
+{
+  initialize();
+
+  return QFrame::minimumSizeHint();
+}
+
+/*!
+  \brief Customize show/hide widget operation.
+  \param on if \c true the widget is being shown, otherswise 
+  it is being hidden
+*/
+void QtxPagePrefMgr::setVisible( bool on )
+{
+  if ( on && !myInit )
+    updateContents();
+
+  QFrame::setVisible( on );
+}
+
+/*!
+  \brief Update widget contents.
+*/
+void QtxPagePrefMgr::updateContents()
+{
+  QtxPreferenceMgr::updateContents();
+
+  QList<QtxPreferenceItem*> lst = childItems();
+  for ( QList<QtxPreferenceItem*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    if ( (*it)->rtti() == QtxPagePrefItem::RTTI() )
+    {
+      QtxPagePrefItem* item = (QtxPagePrefItem*)(*it);
+      if ( item->widget() && item->widget()->parent() != myBox )
+        item->widget()->setParent( myBox );
+    }
+  }
+
+  setWindowIcon( icon() );
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is added.
+  \param item child item being added
+  \sa itemRemoved(), itemChanged()
+*/
+void QtxPagePrefMgr::itemAdded( QtxPreferenceItem* /*item*/ )
+{
+  triggerUpdate();
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is removed.
+  \param item child item being removed
+  \sa itemAdded(), itemChanged()
+*/
+void QtxPagePrefMgr::itemRemoved( QtxPreferenceItem* /*item*/ )
+{
+  triggerUpdate();
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is modified.
+  \param item child item being modified
+  \sa itemAdded(), itemRemoved()
+*/
+void QtxPagePrefMgr::itemChanged( QtxPreferenceItem* /*item*/ )
+{
+  triggerUpdate();
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefMgr::optionValue( const QString& name ) const
+{
+  if ( name == "orientation" )
+    return myBox->orientation() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
+  else
+    return QtxPreferenceMgr::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefMgr::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "orientation" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      myBox->setOrientation( val.toInt() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal );
+  }
+  else
+    QtxPreferenceMgr::setOptionValue( name, val );
+}
+
+/*!
+  \brief Perform internal initialization.
+*/
+void QtxPagePrefMgr::initialize() const
+{
+  if ( myInit )
+    return;
+
+  QtxPagePrefMgr* that = (QtxPagePrefMgr*)this;
+    
+  that->updateContents();
+
+  QList<QtxPreferenceItem*> lst = childItems( true );
+  for ( QList<QtxPreferenceItem*>::iterator it = lst.begin(); it != lst.end(); ++it )
+    (*it)->updateContents();
+
+  that->myInit = true;
+}
+
+/*!
+  \class QtxPagePrefItem
+  \brief Base class for implementation of all the widget-based
+  preference items.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefItem::QtxPagePrefItem( const QString& title, QtxPreferenceItem* parent,
+                                  const QString& sect, const QString& param )
+: QtxPreferenceItem( title, sect, param, parent ),
+  myWidget( 0 )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefItem::~QtxPagePrefItem()
+{
+  delete myWidget;
+}
+
+/*!
+  \brief Get unique item type identifier.
+  \return item type ID
+*/
+int QtxPagePrefItem::rtti() const
+{
+  return QtxPagePrefItem::RTTI();
+}
+
+/*!
+  \brief Get preference item editor widget.
+  \return editor widget
+  \sa setWidget()
+*/
+QWidget* QtxPagePrefItem::widget() const
+{
+  return myWidget;
+}
+
+/*!
+  \brief Specify unique item class identifier.
+  \return item class ID
+*/
+int QtxPagePrefItem::RTTI()
+{
+  return 1000;
+}
+
+/*!
+  \brief Set preference item editor widget.
+  \param wid editor widget
+  \sa widget()
+*/
+void QtxPagePrefItem::setWidget( QWidget* wid )
+{
+  myWidget = wid;
+  sendItemChanges();
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is added.
+  \param item child item being added
+  \sa itemRemoved(), itemChanged()
+*/
+void QtxPagePrefItem::itemAdded( QtxPreferenceItem* /*item*/ )
+{
+  contentChanged();
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is removed.
+  \param item child item being removed
+  \sa itemAdded(), itemChanged()
+*/
+void QtxPagePrefItem::itemRemoved( QtxPreferenceItem* /*item*/ )
+{
+  contentChanged();
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is modified.
+  \param item child item being modified
+  \sa itemAdded(), itemRemoved()
+*/
+void QtxPagePrefItem::itemChanged( QtxPreferenceItem* /*item*/ )
+{
+  contentChanged();
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  
+  This method should be reimplemented in the subclasses.
+  Base implementation does nothing.
+
+  \sa retrieve()
+*/
+void QtxPagePrefItem::store()
+{
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  
+  This method should be reimplemented in the subclasses.
+  Base implementation does nothing.
+
+  \sa store()
+*/
+void QtxPagePrefItem::retrieve()
+{
+}
+
+/*!
+  \brief Find all child items of the QtxPagePrefItem type.
+  \param list used to return list of child items
+  \param rec if \c true, perform recursive search
+*/
+void QtxPagePrefItem::pageChildItems( QList<QtxPagePrefItem*>& list, const bool rec ) const
+{
+  QList<QtxPreferenceItem*> lst = childItems( rec );
+  for ( QList<QtxPreferenceItem*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    if ( (*it)->rtti() == QtxPagePrefItem::RTTI() )
+      list.append( (QtxPagePrefItem*)*it );
+  }
+}
+
+/*!
+  \brief Called when contents is changed (item is added, removed or modified).
+  
+  Triggers the item update.
+*/
+void QtxPagePrefItem::contentChanged()
+{
+  triggerUpdate();
+}
+
+/*!
+  \class QtxPageNamedPrefItem
+  \brief Base class for implementation of the named preference items
+  (items with text labels).
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPageNamedPrefItem::QtxPageNamedPrefItem( const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param ),
+  myControl( 0 )
+{
+  QWidget* main = new QWidget();
+  QHBoxLayout* base = new QHBoxLayout( main );
+  base->setMargin( 0 );
+  base->setSpacing( 5 );
+
+  myLabel = new QLabel( title, main );
+  base->addWidget( myLabel );
+
+  setWidget( main );
+
+  myLabel->setVisible( !title.isEmpty() );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPageNamedPrefItem::~QtxPageNamedPrefItem()
+{
+}
+
+/*!
+  \brief Set preference title.
+  \param txt new preference title.
+*/
+void QtxPageNamedPrefItem::setTitle( const QString& txt )
+{
+  QtxPagePrefItem::setTitle( txt );
+
+  label()->setText( title() );
+  if ( !title().isEmpty() )
+    label()->setVisible( true );
+}
+
+/*!
+  \brief Get label widget corresponding to the preference item.
+  \return label widget
+*/
+QLabel* QtxPageNamedPrefItem::label() const
+{
+  return myLabel;
+}
+
+/*!
+  \brief Get control widget corresponding to the preference item.
+  \return control widget
+  \sa setControl()
+*/
+QWidget* QtxPageNamedPrefItem::control() const
+{
+  return myControl;
+}
+
+/*!
+  \brief Set control widget corresponding to the preference item.
+  \param wid control widget
+  \sa control()
+*/
+void QtxPageNamedPrefItem::setControl( QWidget* wid )
+{
+  if ( myControl == wid )
+    return;
+
+  delete myControl;
+  myControl = wid;
+
+  if ( myControl )
+    widget()->layout()->addWidget( myControl );
+}
+
+/*!
+  \class QtxPagePrefListItem
+  \brief GUI implementation of the list container preference item.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefListItem::QtxPagePrefListItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param ),
+  myFix( false )
+{
+  QSplitter* main = new QSplitter( Qt::Horizontal );
+  main->setChildrenCollapsible( false );
+
+  main->addWidget( myList = new QListWidget( main ) );
+  main->addWidget( myStack = new QStackedWidget( main ) );
+
+  myList->setSelectionMode( QListWidget::SingleSelection );
+
+  myStack->addWidget( myInfLabel = new QLabel( myStack ) );
+  myInfLabel->setAlignment( Qt::AlignCenter );
+
+  connect( myList, SIGNAL( itemSelectionChanged() ), this, SLOT( onItemSelectionChanged() ) );
+
+  setWidget( main );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefListItem::~QtxPagePrefListItem()
+{
+}
+
+/*!
+  \brief Get message text which is shown if the container is empty.
+  \return message text
+  \sa setEmptyInfo()
+*/
+QString QtxPagePrefListItem::emptyInfo() const
+{
+  return myInfText;
+}
+
+/*!
+  \brief Set message text which is shown if the container is empty.
+  \param new message text
+  \sa emptyInfo()
+*/
+void QtxPagePrefListItem::setEmptyInfo( const QString& inf )
+{
+  if ( myInfText == inf )
+    return;
+
+  myInfText = inf;
+
+  updateVisible();
+}
+
+/*!
+  \brief Check if the preference item widget is of fixed size.
+  \return \c true if the widget has the fixed size
+  \sa setFixedSize()
+*/
+bool QtxPagePrefListItem::isFixedSize() const
+{
+  return myFix;
+}
+
+/*!
+  \brief Set the preference item widget to be of fixed size.
+  \param on if \c true, the widget will have the fixed size
+  \sa isFixedSize()
+*/
+void QtxPagePrefListItem::setFixedSize( const bool on )
+{
+  if ( myFix == on )
+    return;
+
+  myFix = on;
+
+  updateGeom();
+}
+
+/*!
+  \brief Update widget contents.
+*/
+void QtxPagePrefListItem::updateContents()
+{
+  updateVisible();
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefListItem::optionValue( const QString& name ) const
+{
+  if ( name == "fixed_size" )
+    return isFixedSize();
+  else if ( name == "empty_info" || name == "info" )
+    return emptyInfo();
+  else
+    return QtxPagePrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefListItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "fixed_size" )
+  {
+    if ( val.canConvert( QVariant::Bool ) )
+      setFixedSize( val.toBool() );
+  }
+  else if ( name == "empty_info" || name == "info" )
+  {
+    if ( val.canConvert( QVariant::String ) )
+      setEmptyInfo( val.toString() );
+  }
+  else
+    QtxPagePrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Called when the selection in the list box is changed.
+*/
+void QtxPagePrefListItem::onItemSelectionChanged()
+{
+  updateState();
+}
+
+/*!
+  \brief Update information label widget.
+*/
+void QtxPagePrefListItem::updateInfo()
+{
+  QString infoText;
+  QtxPagePrefItem* item = selectedItem();
+  if ( item )
+  {
+    infoText = emptyInfo();
+    QRegExp rx( "%([%|N])" );
+
+    int idx = 0;
+    while ( ( idx = rx.indexIn( infoText ) ) != -1 )
+    {
+      if ( rx.cap() == QString( "%%" ) )
+        infoText.replace( idx, rx.matchedLength(), "%" );
+      else if ( rx.cap() == QString( "%N" ) )
+        infoText.replace( idx, rx.matchedLength(), item->title() );
+    }
+  }
+  myInfLabel->setText( infoText );
+}
+
+/*!
+  \brief Update widget state.
+*/
+void QtxPagePrefListItem::updateState()
+{
+  QtxPagePrefItem* item = selectedItem();
+  QWidget* wid = item && !item->isEmpty() ? item->widget() : myInfLabel;
+  if ( wid )
+    myStack->setCurrentWidget( wid );
+
+  updateInfo();
+}
+
+/*!
+  \brief Update visibile child widgets.
+*/
+void QtxPagePrefListItem::updateVisible()
+{
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  QMap<QWidget*, int> map;
+  for ( int i = 0; i < (int)myStack->count(); i++ )
+    map.insert( myStack->widget( i ), 0 );
+
+  int selId = selected();
+  myList->clear();
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    if ( (*it)->isEmpty() && myInfText.isEmpty() )
+      continue;
+
+    myList->addItem( (*it)->title() );
+    myList->item( myList->count() - 1 )->setIcon( (*it)->icon() );
+    myList->item( myList->count() - 1 )->setData( Qt::UserRole, (*it)->id() );
+
+    QWidget* wid = (*it)->widget();
+    if ( !map.contains( wid ) )
+      myStack->addWidget( wid );
+
+    map.remove( wid );
+  }
+
+  map.remove( myInfLabel );
+
+  for ( QMap<QWidget*, int>::const_iterator it = map.begin(); it != map.end(); ++it )
+    myStack->removeWidget( it.key() );
+
+  setSelected( selId );
+  if ( selected() == -1 && myList->count() )
+    setSelected( myList->item( 0 )->data( Qt::UserRole ).toInt() );
+
+  //myList->setVisible( myList->count() > 1 );
+
+  updateState();
+  updateGeom();
+}
+
+/*!
+  \brief Update widget geometry.
+*/
+void QtxPagePrefListItem::updateGeom()
+{
+  if ( myFix )
+    myList->setFixedWidth( myList->minimumSizeHint().width() + 10 );
+  else
+  {
+    myList->setMinimumWidth( 0 );
+    myList->setMaximumWidth( 16777215 );
+
+    QSplitter* s = ::qobject_cast<QSplitter*>( widget() );
+    if ( s )
+    {
+      int w = myList->minimumSizeHint().width() + 30;
+      QList<int> szList;
+      szList.append( w );
+      szList.append( s->width() - w );
+      s->setSizes( szList );
+    }
+  }
+}
+
+/*!
+  \brief Get identifier of the currently selected preference item.
+  \return identifier of the currently selected item or -1 if no item is selected
+  \sa setSelected()
+*/
+int QtxPagePrefListItem::selected() const
+{
+  QList<QListWidgetItem*> selList = myList->selectedItems();
+  if ( selList.isEmpty() )
+    return -1;
+
+  QVariant v = selList.first()->data( Qt::UserRole );
+  return v.canConvert( QVariant::Int ) ? v.toInt() : -1;
+}
+
+/*!
+  \brief Get currently selected preference item.
+  \return currently selected item or 0 if no item is selected
+  \sa setSelected()
+*/
+QtxPagePrefItem* QtxPagePrefListItem::selectedItem() const
+{
+  int selId = selected();
+
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  QtxPagePrefItem* item = 0;
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end() && !item; ++it )
+  {
+    if ( (*it)->id() == selId )
+      item = *it;
+  }
+  return item;
+}
+
+/*!
+  \brief Set currently selected preference item.
+  \param id identifier of the preference item to make selected
+*/
+void QtxPagePrefListItem::setSelected( const int id )
+{
+  int idx = -1;
+  for ( int i = 0; i < (int)myList->count() && idx < 0; i++ )
+  {
+    QVariant v = myList->item( i )->data( Qt::UserRole );
+    if ( v.canConvert( QVariant::Int ) && v.toInt() == id )
+      idx = i;
+  }
+
+  QItemSelection sel;
+  QItemSelectionModel* selModel = myList->selectionModel();
+
+  if ( idx >= 0 )
+    sel.select( myList->model()->index( idx, 0 ), myList->model()->index( idx, 0 ) );
+
+  selModel->select( sel, QItemSelectionModel::ClearAndSelect );
+}
+
+/*!
+  \class QtxPagePrefToolBoxItem
+*/
+
+QtxPagePrefToolBoxItem::QtxPagePrefToolBoxItem( const QString& title, QtxPreferenceItem* parent,
+                                                const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  setWidget( myToolBox = new QToolBox( 0 ) );
+}
+
+QtxPagePrefToolBoxItem::~QtxPagePrefToolBoxItem()
+{
+}
+
+void QtxPagePrefToolBoxItem::updateContents()
+{
+  updateToolBox();
+}
+
+void QtxPagePrefToolBoxItem::updateToolBox()
+{
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  QWidget* cur = myToolBox->currentWidget();
+
+  int i = 0;
+  QMap<QWidget*, int> map;
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QWidget* wid = (*it)->widget();
+    if ( !wid )
+      continue;
+
+    if ( myToolBox->widget( i ) != wid )
+    {
+      if ( myToolBox->indexOf( wid ) != -1 )
+        myToolBox->removeItem( myToolBox->indexOf( wid ) );
+
+      myToolBox->insertItem( i, wid, (*it)->title() );
+    }
+    else
+      myToolBox->setItemText( i, (*it)->title() );
+
+    myToolBox->setItemIcon( i, (*it)->icon() );
+
+    i++;
+    map.insert( wid, 0 );
+  }
+
+  QList<QWidget*> del;
+  for ( int idx = 0; idx < (int)myToolBox->count(); idx++ )
+  {
+    QWidget* w = myToolBox->widget( idx );
+    if ( !map.contains( w ) )
+      del.append( w );
+  }
+
+  for ( QList<QWidget*>::const_iterator itr = del.begin(); itr != del.end(); ++itr )
+    myToolBox->removeItem( myToolBox->indexOf( *itr ) );
+
+  if ( cur )
+    myToolBox->setCurrentWidget( cur );
+}
+
+/*!
+  \class QtxPagePrefTabsItem
+  \brief GUI implementation of the tab widget container.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefTabsItem::QtxPagePrefTabsItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  setWidget( myTabs = new QTabWidget( 0 ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefTabsItem::~QtxPagePrefTabsItem()
+{
+}
+
+/*!
+  \brief Update widget contents.
+*/
+void QtxPagePrefTabsItem::updateContents()
+{
+  updateTabs();
+}
+
+/*!
+  \brief Get tabs position.
+  \return current tabs position (QTabWidget::TabPosition)
+  \sa setTabPosition()
+*/
+int QtxPagePrefTabsItem::tabPosition() const
+{
+  return myTabs->tabPosition();
+}
+
+/*!
+  \brief Set tabs position.
+  \param tp new tabs position (QTabWidget::TabPosition)
+  \sa tabPosition()
+*/
+void QtxPagePrefTabsItem::setTabPosition( const int tp )
+{
+  myTabs->setTabPosition( (QTabWidget::TabPosition)tp );
+}
+
+/*!
+  \brief Get tabs shape.
+  \return current tabs shape (QTabWidget::TabShape)
+  \sa setTabShape()
+*/
+int QtxPagePrefTabsItem::tabShape() const
+{
+  return myTabs->tabShape();
+}
+
+/*!
+  \brief Set tabs shape.
+  \param ts new tabs shape (QTabWidget::TabShape)
+  \sa tabShape()
+*/
+void QtxPagePrefTabsItem::setTabShape( const int ts )
+{
+  myTabs->setTabShape( (QTabWidget::TabShape)ts );
+}
+
+/*!
+  \brief Get tabs icon size.
+  \return current tabs icon size
+  \sa setTabIconSize()
+*/
+QSize QtxPagePrefTabsItem::tabIconSize() const
+{
+  return myTabs->iconSize();
+}
+
+/*!
+  \brief Set tabs icon size.
+  \param sz new tabs icon size
+  \sa tabIconSize()
+*/
+void QtxPagePrefTabsItem::setTabIconSize( const QSize& sz )
+{
+  myTabs->setIconSize( sz );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefTabsItem::optionValue( const QString& name ) const
+{
+  if ( name == "position" )
+    return tabPosition();
+  else if ( name == "shape" )
+    return tabShape();
+  else if ( name == "icon_size" )
+    return tabIconSize();
+  else
+    return QtxPagePrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefTabsItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "position" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setTabPosition( val.toInt() );
+  }
+  else if ( name == "shape" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setTabShape( val.toInt() );
+  }
+  else if ( name == "icon_size" )
+  {
+    if ( val.canConvert( QVariant::Size ) )
+      setTabIconSize( val.toSize() );
+  }
+  else
+    QtxPagePrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Update tabs.
+*/
+void QtxPagePrefTabsItem::updateTabs()
+{
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  QWidget* cur = myTabs->currentWidget();
+
+  int i = 0;
+  QMap<QWidget*, int> map;
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QWidget* wid = (*it)->widget();
+    if ( !wid )
+      continue;
+
+    if ( myTabs->widget( i ) != wid )
+    {
+      if ( myTabs->indexOf( wid ) != -1 )
+        myTabs->removeTab( myTabs->indexOf( wid ) );
+
+      myTabs->insertTab( i, wid, (*it)->title() );
+    }
+    else
+      myTabs->setTabText( i, (*it)->title() );
+
+    myTabs->setTabIcon( i, (*it)->icon() );
+
+    i++;
+    map.insert( wid, 0 );
+  }
+
+  QList<QWidget*> del;
+  for ( int idx = 0; idx < (int)myTabs->count(); idx++ )
+  {
+    QWidget* w = myTabs->widget( idx );
+    if ( !map.contains( w ) )
+      del.append( w );
+  }
+
+  for ( QList<QWidget*>::const_iterator itr = del.begin(); itr != del.end(); ++itr )
+    myTabs->removeTab( myTabs->indexOf( *itr ) );
+
+  if ( cur )
+    myTabs->setCurrentWidget( cur );
+}
+
+/*!
+  \class QtxPagePrefFrameItem
+  \brief GUI implementation of the frame widget container.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefFrameItem::QtxPagePrefFrameItem( const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  QWidget* main = new QWidget();
+  QVBoxLayout* base = new QVBoxLayout( main );
+  base->setMargin( 0 );
+  base->setSpacing( 0 );
+
+  base->addWidget( myBox = new QtxGridBox( 1, Qt::Horizontal, main, 5, 5 ) );
+  base->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
+
+  setWidget( main );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefFrameItem::~QtxPagePrefFrameItem()
+{
+}
+
+/*!
+  \brief Update widget contents.
+*/
+void QtxPagePrefFrameItem::updateContents()
+{
+  updateFrame();
+}
+
+/*!
+  \brief Get frame margin.
+  \return current frame margin
+  \sa setMargin()
+*/
+int QtxPagePrefFrameItem::margin() const
+{
+  return myBox->insideMargin();
+}
+
+/*!
+  \brief Get frame margin.
+  \param m new frame margin
+  \sa margin()
+*/
+void QtxPagePrefFrameItem::setMargin( const int m )
+{
+  myBox->setInsideMargin( m );
+}
+
+/*!
+  \brief Get frame spacing.
+  \return current frame spacing
+  \sa setSpacing()
+*/
+int QtxPagePrefFrameItem::spacing() const
+{
+  return myBox->insideSpacing();
+}
+
+/*!
+  \brief Set frame spacing.
+  \param s new frame spacing
+  \sa spacing()
+*/
+void QtxPagePrefFrameItem::setSpacing( const int s )
+{
+  myBox->setInsideSpacing( s );
+}
+
+/*!
+  \brief Get number of frame columns.
+  \return current columns number
+  \sa setColumns()
+*/
+int QtxPagePrefFrameItem::columns() const
+{
+  return myBox->columns();
+}
+
+/*!
+  \brief Set number of frame columns.
+  \param c new columns number
+  \sa columns()
+*/
+void QtxPagePrefFrameItem::setColumns( const int c )
+{
+  myBox->setColumns( c );
+}
+
+/*!
+  \brief Get frame box orientation.
+  \return current frame orientation
+  \sa setOrientation()
+*/
+Qt::Orientation QtxPagePrefFrameItem::orientation() const
+{
+  return myBox->orientation();
+}
+
+/*!
+  \brief Set frame box orientation.
+  \param o new frame orientation
+  \sa orientation()
+*/
+void QtxPagePrefFrameItem::setOrientation( const Qt::Orientation o )
+{
+  myBox->setOrientation( o );
+}
+
+bool QtxPagePrefFrameItem::stretch() const
+{
+  QSpacerItem* s = 0;
+  QLayout* l = widget() ? widget()->layout() : 0;
+  for ( int i = 0; l && i < l->count() && !s; i++ )
+    s = l->itemAt( i )->spacerItem();
+
+  return s ? ( s->expandingDirections() & Qt::Vertical ) != 0 : false;
+}
+
+void QtxPagePrefFrameItem::setStretch( const bool on )
+{
+  QSpacerItem* s = 0;
+  QLayout* l = widget() ? widget()->layout() : 0;
+  for ( int i = 0; l && i < l->count() && !s; i++ )
+    s = l->itemAt( i )->spacerItem();
+
+  if ( s )
+    s->changeSize( 0, 0, QSizePolicy::Minimum, on ? QSizePolicy::Expanding : QSizePolicy::Minimum );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefFrameItem::optionValue( const QString& name ) const
+{
+  if ( name == "margin" )
+    return margin();
+  else if ( name == "spacing" )
+    return spacing();
+  else if ( name == "columns" )
+    return columns();
+  else if ( name == "orientation" )
+    return orientation();
+  else if ( name == "stretch" )
+    return stretch();
+  else
+    return QtxPagePrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefFrameItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "margin" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setMargin( val.toInt() );
+  }
+  else if ( name == "spacing" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setSpacing( val.toInt() );
+  }
+  else if ( name == "columns" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setColumns( val.toInt() );
+  }
+  else if ( name == "orientation" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setOrientation( (Qt::Orientation)val.toInt() );
+  }
+  else if ( name == "stretch" )
+  {
+    if ( val.canConvert( QVariant::Bool ) )
+      setStretch( val.toBool() );
+  }
+  else
+    QtxPagePrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Update frame widget.
+*/
+void QtxPagePrefFrameItem::updateFrame()
+{
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QWidget* wid = (*it)->widget();
+    if ( !wid )
+      continue;
+
+    if ( wid->parent() != myBox )
+      wid->setParent( myBox );
+  }
+}
+
+/*!
+  \class QtxPagePrefGroupItem
+  \brief GUI implementation of the group widget container.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefGroupItem::QtxPagePrefGroupItem( const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  myGroup = new QtxGroupBox( title, 0 );
+  myBox = new QtxGridBox( 1, Qt::Horizontal, myGroup, 5, 5 );
+  myGroup->setWidget( myBox );
+
+  setWidget( myGroup );
+}
+
+/*!
+  \brief Constructor.
+  \param cols columns number
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefGroupItem::QtxPagePrefGroupItem( const int cols, const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  myGroup = new QtxGroupBox( title, 0 );
+  myBox = new QtxGridBox( cols, Qt::Horizontal, myGroup, 5, 5 );
+  myGroup->setWidget( myBox );
+
+  setWidget( myGroup );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefGroupItem::~QtxPagePrefGroupItem()
+{
+}
+
+/*!
+  \brief Assign resource file settings to the preference item.
+  \param sect resource file section name
+  \param param resource file parameter name
+  \sa resource()
+*/
+void QtxPagePrefGroupItem::setResource( const QString& sect, const QString& param )
+{
+  QtxPagePrefItem::setResource( sect, param );
+  updateState();
+}
+
+/*!
+  \brief Update widget contents.
+*/
+void QtxPagePrefGroupItem::updateContents()
+{
+  myGroup->setTitle( title() );
+
+  updateState();
+  updateGroup();
+}
+
+/*!
+  \brief Get group box margin.
+  \return current group box margin
+  \sa setMargin()
+*/
+int QtxPagePrefGroupItem::margin() const
+{
+  return myBox->insideMargin();
+}
+
+/*!
+  \brief Get group box margin.
+  \param m new group box margin
+  \sa margin()
+*/
+void QtxPagePrefGroupItem::setMargin( const int m )
+{
+  myBox->setInsideMargin( m );
+}
+
+/*!
+  \brief Get group box spacing.
+  \return current group box spacing
+  \sa setSpacing()
+*/
+int QtxPagePrefGroupItem::spacing() const
+{
+  return myBox->insideSpacing();
+}
+
+/*!
+  \brief Set group box spacing.
+  \param s new group box spacing
+  \sa spacing()
+*/
+void QtxPagePrefGroupItem::setSpacing( const int s )
+{
+  myBox->setInsideSpacing( s );
+}
+
+/*!
+  \brief Get number of group box columns.
+  \return current columns number
+  \sa setColumns()
+*/
+int QtxPagePrefGroupItem::columns() const
+{
+  return myBox->columns();
+}
+
+/*!
+  \brief Set number of group box columns.
+  \param c new columns number
+  \sa columns()
+*/
+void QtxPagePrefGroupItem::setColumns( const int c )
+{
+  myBox->setColumns( c );
+}
+
+/*!
+  \brief Get group box orientation.
+  \return current group box orientation
+  \sa setOrientation()
+*/
+Qt::Orientation QtxPagePrefGroupItem::orientation() const
+{
+  return myBox->orientation();
+}
+
+/*!
+  \brief Set group box orientation.
+  \param o new group box orientation
+  \sa orientation()
+*/
+void QtxPagePrefGroupItem::setOrientation( const Qt::Orientation o )
+{
+  myBox->setOrientation( o );
+}
+
+/*!
+  \brief Get 'flat' flag of the group box widget.
+  \return \c true if the group box is flat
+*/
+bool QtxPagePrefGroupItem::isFlat() const
+{
+  return myGroup->isFlat();
+}
+
+/*!
+  \brief Get 'flat' flag of the group box widget.
+  \param on if \c true the group box will be made flat
+*/
+void QtxPagePrefGroupItem::setFlat( const bool on )
+{
+  myGroup->setFlat( on );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefGroupItem::store()
+{
+  if ( myGroup->isCheckable() )
+    setBoolean( myGroup->isChecked() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefGroupItem::retrieve()
+{
+  if ( myGroup->isCheckable() )
+    myGroup->setChecked( getBoolean() );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefGroupItem::optionValue( const QString& name ) const
+{
+  if ( name == "margin" )
+    return margin();
+  else if ( name == "spacing" )
+    return spacing();
+  else if ( name == "columns" )
+    return columns();
+  else if ( name == "orientation" )
+    return orientation();
+  else if ( name == "flat" )
+    return isFlat();
+  else
+    return QtxPagePrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefGroupItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "margin" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setMargin( val.toInt() );
+  }
+  else if ( name == "spacing" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setSpacing( val.toInt() );
+  }
+  else if ( name == "columns" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setColumns( val.toInt() );
+  }
+  else if ( name == "orientation" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setOrientation( (Qt::Orientation)val.toInt() );
+  }
+  else if ( name == "flat" )
+  {
+    if ( val.canConvert( QVariant::Bool ) )
+      setFlat( val.toBool() );
+  }
+  else
+    QtxPagePrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Update widget state.
+*/
+void QtxPagePrefGroupItem::updateState()
+{
+  QString section, param;
+  resource( section, param );
+  myGroup->setCheckable( !title().isEmpty() && !section.isEmpty() && !param.isEmpty() );
+}
+
+/*!
+  \brief Update group box widget.
+*/
+void QtxPagePrefGroupItem::updateGroup()
+{
+  QList<QtxPagePrefItem*> items;
+  pageChildItems( items );
+
+  for ( QList<QtxPagePrefItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QWidget* wid = (*it)->widget();
+    if ( !wid )
+      continue;
+
+    if ( wid->parent() != myBox )
+      wid->setParent( myBox );
+  }
+}
+
+/*!
+  \class QtxPagePrefSpaceItem
+  \brief Simple spacer item which can be used in the preferences
+  editor dialog box.
+*/
+
+/*!
+  \brief Constructor.
+
+  Creates spacer item with zero width and height and expanding 
+  on both directions (by height and width).
+
+  \param parent parent preference item
+*/
+QtxPagePrefSpaceItem::QtxPagePrefSpaceItem( QtxPreferenceItem* parent )
+: QtxPagePrefItem( QString(), parent )
+{
+  initialize( 0, 0, 1, 1 );
+}
+
+/*!
+  \brief Constructor.
+
+  Creates spacer item with zero width and height and expanding 
+  according to the specified orientation.
+
+  \param o spacer orientation
+  \param parent parent preference item
+*/
+QtxPagePrefSpaceItem::QtxPagePrefSpaceItem( Qt::Orientation o, QtxPreferenceItem* parent )
+: QtxPagePrefItem( QString(), parent )
+{
+  if ( o == Qt::Horizontal )
+    initialize( 0, 0, 1, 0 );
+  else
+    initialize( 0, 0, 0, 1 );
+}
+
+/*!
+  \brief Constructor.
+
+  Creates spacer item with specified width and height. The spacing
+  item is expanding horizontally if \a w <= 0 and vertically
+  if \a h <= 0.
+
+  \param w spacer width
+  \param h spacer height
+  \param parent parent preference item
+*/
+QtxPagePrefSpaceItem::QtxPagePrefSpaceItem( const int w, const int h, QtxPreferenceItem* parent )
+: QtxPagePrefItem( QString(), parent )
+{
+  initialize( w, h, w > 0 ? 0 : 1, h > 0 ? 0 : 1 );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefSpaceItem::~QtxPagePrefSpaceItem()
+{
+}
+
+/*!
+  \brief Get spacer item size for the specified direction.
+  \param o direction
+  \return size for the specified direction
+  \sa setSize()
+*/
+int QtxPagePrefSpaceItem::size( Qt::Orientation o ) const
+{
+  return o == Qt::Horizontal ? widget()->minimumWidth() : widget()->minimumHeight();
+}
+
+/*!
+  \brief Set spacer item size for the specified direction.
+  \param o direction
+  \param sz new size for the specified direction
+  \sa size()
+*/
+void QtxPagePrefSpaceItem::setSize( Qt::Orientation o, const int sz )
+{
+  if ( o == Qt::Horizontal )
+    widget()->setMinimumWidth( sz );
+  else
+    widget()->setMinimumHeight( sz );
+}
+
+/*!
+  \brief Get spacer item stretch factor for the specified direction.
+  \param o direction
+  \return stretch factor for the specified direction
+  \sa setStretch()
+*/
+int QtxPagePrefSpaceItem::stretch( Qt::Orientation o ) const
+{
+  QSizePolicy sp = widget()->sizePolicy();
+  return o == Qt::Horizontal ? sp.horizontalStretch() : sp.verticalStretch();
+}
+
+/*!
+  \brief Set spacer item stretch factor for the specified direction.
+  \param o direction
+  \param sf new stretch factor for the specified direction
+  \sa stretch()
+*/
+void QtxPagePrefSpaceItem::setStretch( Qt::Orientation o, const int sf )
+{
+  QSizePolicy sp = widget()->sizePolicy();
+  if ( o == Qt::Horizontal )
+  {
+    sp.setHorizontalStretch( sf );
+    sp.setHorizontalPolicy( sf > 0 ? QSizePolicy::Expanding : QSizePolicy::Fixed );
+  }
+  else
+  {
+    sp.setVerticalStretch( sf );
+    sp.setVerticalPolicy( sf > 0 ? QSizePolicy::Expanding : QSizePolicy::Fixed );
+  }
+    
+  widget()->setSizePolicy( sp );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefSpaceItem::optionValue( const QString& name ) const
+{
+  if ( name == "horizontal_size" || name == "hsize" )
+    return size( Qt::Horizontal );
+  else if ( name == "vertical_size" || name == "vsize" )
+    return size( Qt::Vertical );
+  else if ( name == "horizontal_stretch" || name == "hstretch" )
+    return stretch( Qt::Horizontal );
+  else if ( name == "vertical_stretch" || name == "vstretch" )
+    return stretch( Qt::Vertical );
+  else
+    return QtxPagePrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefSpaceItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "horizontal_size" || name == "hsize" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setSize( Qt::Horizontal, val.toInt() );
+  }
+  else if ( name == "vertical_size" || name == "vsize" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setSize( Qt::Vertical, val.toInt() );
+  }
+  else if ( name == "horizontal_stretch" || name == "hstretch" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setStretch( Qt::Horizontal, val.toInt() );
+  }
+  else if ( name == "vertical_stretch" || name == "vstretch" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setStretch( Qt::Vertical, val.toInt() );
+  }
+  else
+    QtxPagePrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Perform internal initialization.
+  \param w spacer item width
+  \param h spacer item height
+  \param ws spacer item horizontal stretch factor
+  \param hs spacer item vertical stretch factor
+*/
+void QtxPagePrefSpaceItem::initialize( const int w, const int h, const int hs, const int vs )
+{
+  QSizePolicy sp;
+  sp.setHorizontalPolicy( hs > 0 ? QSizePolicy::Expanding : QSizePolicy::Fixed );
+  sp.setVerticalPolicy( vs > 0 ? QSizePolicy::Expanding : QSizePolicy::Fixed );
+  
+  sp.setHorizontalStretch( hs );
+  sp.setVerticalStretch( vs );
+
+  QWidget* wid = new QWidget();
+  wid->setSizePolicy( sp );
+
+  wid->setMinimumSize( w, h );
+  
+  setWidget( wid );
+}
+
+/*!
+  \class  QtxPagePrefCheckItem
+  \brief GUI implementation of the resources check box item (boolean).
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefCheckItem::QtxPagePrefCheckItem( const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+
+: QtxPagePrefItem( title, parent, sect, param )
+{
+  myCheck = new QCheckBox( title );
+  myCheck->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  setWidget( myCheck );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefCheckItem::~QtxPagePrefCheckItem()
+{
+}
+
+/*!
+  \brief Set preference item title.
+  \param txt new preference title.
+*/
+void QtxPagePrefCheckItem::setTitle( const QString& txt )
+{
+  QtxPagePrefItem::setTitle( txt );
+
+  myCheck->setText( title() );
+}
+                                            
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefCheckItem::store()
+{
+  setBoolean( myCheck->isChecked() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefCheckItem::retrieve()
+{
+  myCheck->setChecked( getBoolean() );
+}
+
+/*!
+  \class QtxPagePrefEditItem
+  \brief GUI implementation of the resources line edit box item
+  for string, integer and double values.
+*/
+
+/*!
+  \brief Constructor.
+
+  Creates preference item for string value editing.
+
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefEditItem::QtxPagePrefEditItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( String )
+{
+  setControl( myEditor = new QLineEdit() );
+  updateEditor();
+}
+
+/*!
+  \brief Constructor.
+
+  Creates preference item for editing of the value which type
+  is specified by parameter \a type.
+
+  \param type preference item input type (QtxPagePrefEditItem::InputType)
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefEditItem::QtxPagePrefEditItem( const int type, const QString& title,
+                                          QtxPreferenceItem* parent, const QString& sect, 
+                                         const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( type )
+{
+  setControl( myEditor = new QLineEdit() );
+  updateEditor();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefEditItem::~QtxPagePrefEditItem()
+{
+}
+
+/*!
+  \brief Get edit box preference item input type.
+  \return preference item input type (QtxPagePrefEditItem::InputType)
+  \sa setInputType()
+*/
+int QtxPagePrefEditItem::inputType() const
+{
+  return myType;
+}
+
+/*!
+  \brief Set edit box preference item input type.
+  \param type new preference item input type (QtxPagePrefEditItem::InputType)
+  \sa inputType()
+*/
+void QtxPagePrefEditItem::setInputType( const int type )
+{
+  if ( myType == type )
+    return;
+
+  myType = type;
+  updateEditor();
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefEditItem::store()
+{
+  setString( myEditor->text() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefEditItem::retrieve()
+{
+  QString txt = getString();
+  if ( myEditor->validator() )
+  {
+    int pos = 0;
+    if ( myEditor->validator()->validate( txt, pos ) == QValidator::Invalid )
+      txt.clear();
+  }
+  myEditor->setText( txt );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefEditItem::optionValue( const QString& name ) const
+{
+  if ( name == "input_type" || name == "type" )
+    return inputType();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefEditItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "input_type" || name == "type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setInputType( val.toInt() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Update edit box widget.
+*/
+void QtxPagePrefEditItem::updateEditor()
+{
+  QValidator* val = 0;
+  switch ( inputType() )
+  {
+  case Integer:
+    val = new QIntValidator( myEditor );
+    break;
+  case Double:
+    val = new QDoubleValidator( myEditor );
+    break;
+  default:
+    break;
+  }
+
+  if ( !myEditor->text().isEmpty() && val )
+  {
+    int pos = 0;
+    QString str = myEditor->text();
+    if ( val->validate( str, pos ) == QValidator::Invalid )
+      myEditor->clear();
+  }
+
+  delete myEditor->validator();
+  myEditor->setValidator( val );
+}
+
+/*!
+  \class QtxPagePrefSelectItem
+  \brief GUI implementation of the resources selector item 
+  (string, integer or double values list).
+
+  All items in the list (represented as combo box) should be specified
+  by the unique identifier which is stored to the resource file instead
+  of the value itself.
+*/
+
+/*!
+  \brief Constructor.
+  
+  Creates preference item with combo box widget which is not editable
+  (direct value entering is disabled).
+
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefSelectItem::QtxPagePrefSelectItem( const QString& title, QtxPreferenceItem* parent,
+                                              const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( NoInput )
+{
+  setControl( mySelector = new QtxComboBox() );
+  mySelector->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  mySelector->setDuplicatesEnabled( false );
+  updateSelector();
+}
+
+/*!
+  \brief Constructor.
+  
+  Creates preference item with combo box widget which is editable
+  according to the specified input type (integer, double or string values).
+
+  \param type input type (QtxPagePrefSelectItem::InputType)
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefSelectItem::QtxPagePrefSelectItem( const int type, const QString& title, QtxPreferenceItem* parent,
+                                              const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( type )
+{
+  setControl( mySelector = new QtxComboBox() );
+  mySelector->setDuplicatesEnabled( false );
+  updateSelector();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefSelectItem::~QtxPagePrefSelectItem()
+{
+}
+
+/*!
+  \brief Get edit box preference item input type.
+  \return preference item input type (QtxPagePrefSelectItem::InputType)
+  \sa setInputType()
+*/
+int QtxPagePrefSelectItem::inputType() const
+{
+  return myType;
+}
+
+/*!
+  \brief Set edit box preference item input type.
+  \param type new preference item input type (QtxPagePrefSelectItem::InputType)
+  \sa inputType()
+*/
+void QtxPagePrefSelectItem::setInputType( const int type )
+{
+  if ( myType == type )
+    return;
+
+  myType = type;
+  updateSelector();
+}
+
+/*!
+  \brief Get the list of the values from the selection widget.
+  \return list of values
+  \sa numbers(), setStrings()
+*/
+QStringList QtxPagePrefSelectItem::strings() const
+{
+  QStringList res;
+  for ( int i = 0; i < mySelector->count(); i++ )
+    res.append( mySelector->itemText( i ) );
+  return res;
+}
+
+/*!
+  \brief Get the list of the values identifiers from the selection widget.
+  \return list of values IDs
+  \sa strings(), setNumbers()
+*/
+QList<int> QtxPagePrefSelectItem::numbers() const
+{
+  QList<int> res;
+  for ( int i = 0; i < mySelector->count(); i++ )
+  {
+    if ( mySelector->hasId( i ) )
+      res.append( mySelector->id( i ) );
+  }
+  return res;
+}
+
+/*!
+  \brief Set the list of the values to the selection widget.
+  \param lst new list of values
+  \sa strings(), setNumbers()
+*/
+void QtxPagePrefSelectItem::setStrings( const QStringList& lst )
+{
+  mySelector->clear();
+  mySelector->addItems( lst );
+}
+
+/*!
+  \brief Set the list of the values identifiers to the selection widget.
+  \param ids new list of values IDs
+  \sa numbers(), setStrings()
+*/
+void QtxPagePrefSelectItem::setNumbers( const QList<int>& ids )
+{
+  int i = 0;
+  for ( QList<int>::const_iterator it = ids.begin(); it != ids.end() && i < mySelector->count(); ++it, i++ )
+    mySelector->setId( i, *it );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefSelectItem::store()
+{
+  if ( mySelector->isCleared() )
+    return;
+
+  int idx = mySelector->currentIndex();
+
+  if ( mySelector->hasId( idx ) )
+    setInteger( mySelector->id( idx ) );
+  else if ( idx >= 0 )
+    setString( mySelector->itemText( idx ) );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefSelectItem::retrieve()
+{
+  QString txt = getString();
+
+  int idx = -1;
+
+  bool ok = false;
+  int num = txt.toInt( &ok );
+  if ( ok )
+    idx = mySelector->index( num );
+  else
+  {
+    for ( int i = 0; i < mySelector->count() && idx == -1; i++ )
+    {
+      if ( mySelector->itemText( i ) == txt )
+        idx = i;
+    }
+  }
+
+  if ( idx != -1 )
+    mySelector->setCurrentIndex( idx );
+  else if ( mySelector->isEditable() )
+  {
+    int pos = 0;
+    if ( mySelector->validator() &&
+         mySelector->validator()->validate( txt, pos ) == QValidator::Invalid )
+      mySelector->setCleared( true );
+    else
+    {
+      mySelector->setCleared( false );
+      mySelector->addItem( txt );
+      mySelector->setCurrentIndex( mySelector->count() - 1 );
+    }
+  }
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefSelectItem::optionValue( const QString& name ) const
+{
+  if ( name == "input_type" || name == "type" )
+    return inputType();
+  else if ( name == "strings" || name == "labels" )
+    return strings();
+  else if ( name == "numbers" || name == "ids" || name == "indexes" )
+  {
+    QList<QVariant> lst;
+    QList<int> nums = numbers();
+    for ( QList<int>::const_iterator it = nums.begin(); it != nums.end(); ++it )
+      lst.append( *it );
+    return lst;
+  }
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefSelectItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "input_type" || name == "type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setInputType( val.toInt() );
+  }
+  else if ( name == "strings" || name == "labels" )
+    setStrings( val );
+  else if ( name == "numbers" || name == "ids" || name == "indexes" )
+    setNumbers( val );
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Set the list of the values from the resource manager.
+  \param var new values list
+  \internal
+*/
+void QtxPagePrefSelectItem::setStrings( const QVariant& var )
+{
+  if ( var.type() != QVariant::StringList )
+    return;
+
+  setStrings( var.toStringList() );
+}
+
+/*!
+  \brief Set the list of the values identifiers from the resource manager.
+  \param var new values IDs list
+  \internal
+*/
+void QtxPagePrefSelectItem::setNumbers( const QVariant& var )
+{
+  if ( var.type() != QVariant::List )
+    return;
+
+  QList<int> lst;
+  QList<QVariant> varList = var.toList();
+  for ( QList<QVariant>::const_iterator it = varList.begin(); it != varList.end(); ++it )
+  {
+    if ( (*it).canConvert( QVariant::Int ) )
+      lst.append( (*it).toInt() );
+  }
+  setNumbers( lst );
+}
+
+/*!
+  \brief Update selector widget.
+*/
+void QtxPagePrefSelectItem::updateSelector()
+{
+  QValidator* val = 0;
+  switch ( inputType() )
+  {
+  case Integer:
+    val = new QIntValidator( mySelector );
+    break;
+  case Double:
+    val = new QDoubleValidator( mySelector );
+    break;
+  default:
+    break;
+  }
+
+  mySelector->setEditable( inputType() != NoInput );
+
+  if ( mySelector->isEditable() && !mySelector->currentText().isEmpty() && val )
+  {
+    int pos = 0;
+    QString str = mySelector->currentText();
+    if ( val->validate( str, pos ) == QValidator::Invalid )
+      mySelector->clearEditText();
+  }
+
+  delete mySelector->validator();
+  mySelector->setValidator( val );
+}
+
+/*!
+  \class QtxPagePrefSpinItem
+  \brief GUI implementation of the resources spin box item
+  (for integer or double value).
+*/
+
+/*!
+  \brief Constructor.
+
+  Creates spin box preference item for the entering integer values.
+
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefSpinItem::QtxPagePrefSpinItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( Integer )
+{
+  updateSpinBox();
+}
+
+/*!
+  \brief Constructor.
+
+  Creates spin box preference item for the entering values which type
+  is specified by the parameter \a type.
+
+  \param type input type (QtxPagePrefSpinItem::InputType).
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefSpinItem::QtxPagePrefSpinItem( const int type, const QString& title,
+                                          QtxPreferenceItem* parent, const QString& sect, 
+                                         const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+  myType( type )
+{
+  updateSpinBox();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefSpinItem::~QtxPagePrefSpinItem()
+{
+}
+
+/*!
+  \brief Get spin box preference item input type.
+  \return preference item input type (QtxPagePrefSpinItem::InputType)
+  \sa setInputType()
+*/
+int QtxPagePrefSpinItem::inputType() const
+{
+  return myType;
+}
+
+/*!
+  \brief Set spin box preference item input type.
+  \param type new preference item input type (QtxPagePrefSpinItem::InputType)
+  \sa inputType()
+*/
+void QtxPagePrefSpinItem::setInputType( const int type )
+{
+  if ( myType == type )
+    return;
+
+  myType = type;
+  updateSpinBox();
+}
+
+/*!
+  \brief Get spin box preference item step value.
+  \return spin box single step value
+  \sa setStep()
+*/
+QVariant QtxPagePrefSpinItem::step() const
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    return isb->singleStep();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    return dsb->singleStep();
+  else
+    return QVariant();
+}
+
+/*!
+  \brief Get spin box preference item minimum value.
+  \return spin box minimum value
+  \sa setMinimum()
+*/
+QVariant QtxPagePrefSpinItem::minimum() const
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    return isb->minimum();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    return dsb->minimum();
+  else
+    return QVariant();
+}
+
+/*!
+  \brief Get spin box preference item maximum value.
+  \return spin box maximum value
+  \sa setMaximum()
+*/
+QVariant QtxPagePrefSpinItem::maximum() const
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    return isb->maximum();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    return dsb->maximum();
+  else
+    return QVariant();
+}
+
+/*!
+  \brief Get spin box preference item prefix string.
+  \return spin box prefix string
+  \sa setPrefix()
+*/
+QString QtxPagePrefSpinItem::prefix() const
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    return isb->prefix();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    return dsb->prefix();
+  else
+    return QString();
+}
+
+/*!
+  \brief Get spin box preference item suffix string.
+  \return spin box suffix string
+  \sa setSuffix()
+*/
+QString QtxPagePrefSpinItem::suffix() const
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    return isb->suffix();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    return dsb->suffix();
+  else
+    return QString();
+}
+
+/*!
+  \brief Get spin box preference item special value text (which is shown 
+  when the spin box reaches minimum value).
+  \return spin box special value text
+  \sa setSpecialValueText()
+*/
+QString QtxPagePrefSpinItem::specialValueText() const
+{
+  QAbstractSpinBox* sb = ::qobject_cast<QAbstractSpinBox*>( control() );
+  if ( sb )
+    return sb->specialValueText();
+  else
+    return QString();
+}
+
+/*!
+  \brief Set spin box preference item step value.
+  \param step new spin box single step value
+  \sa step()
+*/
+void QtxPagePrefSpinItem::setStep( const QVariant& step )
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+  {
+    if ( step.canConvert( QVariant::Int ) )
+      isb->setSingleStep( step.toInt() );
+  }
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+  {
+    if ( step.canConvert( QVariant::Double ) )
+      dsb->setSingleStep( step.toDouble() );
+  }
+}
+
+/*!
+  \brief Set spin box preference item minimum value.
+  \param min new spin box minimum value
+  \sa minimum()
+*/
+void QtxPagePrefSpinItem::setMinimum( const QVariant& min )
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+  {
+    if ( min.canConvert( QVariant::Int ) )
+      isb->setMinimum( min.toInt() );
+  }
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+  {
+    if ( min.canConvert( QVariant::Double ) )
+      dsb->setMinimum( min.toDouble() );
+  }
+}
+
+/*!
+  \brief Set spin box preference item maximum value.
+  \param min new spin box maximum value
+  \sa maximum()
+*/
+void QtxPagePrefSpinItem::setMaximum( const QVariant& max )
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+  {
+    if ( max.canConvert( QVariant::Int ) )
+      isb->setMaximum( max.toInt() );
+  }
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+  {
+    if ( max.canConvert( QVariant::Double ) )
+      dsb->setMaximum( max.toDouble() );
+  }
+}
+
+/*!
+  \brief Set spin box preference item prefix string.
+  \param txt new spin box prefix string
+  \sa prefix()
+*/
+void QtxPagePrefSpinItem::setPrefix( const QString& txt )
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    isb->setPrefix( txt );
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    dsb->setPrefix( txt );
+}
+
+/*!
+  \brief Set spin box preference item suffix string.
+  \param txt new spin box suffix string
+  \sa suffix()
+*/
+void QtxPagePrefSpinItem::setSuffix( const QString& txt )
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    isb->setSuffix( txt );
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    dsb->setSuffix( txt );
+}
+
+/*!
+  \brief Set spin box preference item special value text (which is shown 
+  when the spin box reaches minimum value).
+  \param txt new spin box special value text
+  \sa specialValueText()
+*/
+void QtxPagePrefSpinItem::setSpecialValueText( const QString& txt )
+{
+  QAbstractSpinBox* sb = ::qobject_cast<QAbstractSpinBox*>( control() );
+  if ( sb )
+    sb->setSpecialValueText( txt );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefSpinItem::store()
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    setInteger( isb->value() );
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    setDouble( dsb->value() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefSpinItem::retrieve()
+{
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    isb->setValue( getInteger( isb->value() ) );
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    dsb->setValue( getDouble( dsb->value() ) );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefSpinItem::optionValue( const QString& name ) const
+{
+  if ( name == "input_type" || name == "type" )
+    return inputType();
+  else if ( name == "minimum" || name == "min" )
+    return minimum();
+  else if ( name == "maximum" || name == "max" )
+    return maximum();
+  else if ( name == "step" )
+    return step();
+  else if ( name == "prefix" )
+    return prefix();
+  else if ( name == "suffix" )
+    return suffix();
+  else if ( name == "special" )
+    return specialValueText();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefSpinItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "input_type" || name == "type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setInputType( val.toInt() );
+  }
+  else if ( name == "minimum" || name == "min" )
+    setMinimum( val );
+  else if ( name == "maximum" || name == "max" )
+    setMaximum( val );
+  else if ( name == "step" )
+    setStep( val );
+  else if ( name == "prefix" )
+  {
+    if ( val.canConvert( QVariant::String ) )
+      setPrefix( val.toString() );
+  }
+  else if ( name == "suffix" )
+  {
+    if ( val.canConvert( QVariant::String ) )
+      setSuffix( val.toString() );
+  }
+  else if ( name == "special" )
+  {
+    if ( val.canConvert( QVariant::String ) )
+      setSpecialValueText( val.toString() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \brief Update spin box widget.
+*/
+void QtxPagePrefSpinItem::updateSpinBox()
+{
+  QVariant val;
+  QVariant stp = step();
+  QVariant min = minimum();
+  QVariant max = maximum();
+
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+    val = isb->value();
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+    val = dsb->value();
+
+  switch ( inputType() )
+  {
+  case Integer:
+    setControl( new QtxIntSpinBox() );
+    break;
+  case Double:
+    setControl( new QtxDoubleSpinBox() );
+    break;
+  default:
+    break;
+  }
+
+  control()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+
+  setStep( stp );
+  setMinimum( min );
+  setMaximum( max );
+
+  if ( QtxIntSpinBox* isb = ::qobject_cast<QtxIntSpinBox*>( control() ) )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      isb->setValue( val.toInt() );
+  }
+  else if ( QtxDoubleSpinBox* dsb = ::qobject_cast<QtxDoubleSpinBox*>( control() ) )
+  {
+    if ( val.canConvert( QVariant::Double ) )
+      dsb->setValue( val.toDouble() );
+  }
+}
+
+/*!
+  \class  QtxPagePrefTextItem
+  \brief GUI implementation of the resources text box edit item
+  (for large text data).
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefTextItem::QtxPagePrefTextItem( QtxPreferenceItem* parent, const QString& sect, 
+                                         const QString& param )
+: QtxPageNamedPrefItem( QString(), parent, sect, param )
+{
+  myEditor = new QTextEdit();
+  myEditor->setAcceptRichText( false );
+
+  setControl( myEditor );
+}
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefTextItem::QtxPagePrefTextItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  myEditor = new QTextEdit();
+  myEditor->setAcceptRichText( false );
+
+  setControl( myEditor );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefTextItem::~QtxPagePrefTextItem()
+{
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefTextItem::store()
+{
+  setString( myEditor->toPlainText() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefTextItem::retrieve()
+{
+  myEditor->setPlainText( getString() );
+}
+
+/*!
+  \class QtxPagePrefColorItem
+  \brief GUI implementation of the resources color item.
+*/
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefColorItem::QtxPagePrefColorItem( const QString& title, QtxPreferenceItem* parent,
+                                            const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myColor = new QtxColorButton() );
+  myColor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefColorItem::~QtxPagePrefColorItem()
+{
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefColorItem::store()
+{
+  setColor( myColor->color() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefColorItem::retrieve()
+{
+  myColor->setColor( getColor() );
+}
+
+/*!
+  \class QtxPagePrefFontItem
+  \brief GUI implementation of the resources font item.
+*/
+
+/*!
+  \brief Constructor.
+  \param feat font editor widget features (QtxFontEdit::Features)
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefFontItem::QtxPagePrefFontItem( const int feat, const QString& title,
+                                          QtxPreferenceItem* parent, const QString& sect, 
+                                         const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myFont = new QtxFontEdit( feat ) );
+}
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefFontItem::QtxPagePrefFontItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myFont = new QtxFontEdit() );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefFontItem::~QtxPagePrefFontItem()
+{
+}
+
+/*!
+  \brief Get font widget features.
+  \return font widget features (ORed QtxFontEdit::Features flags)
+  \sa setFeatures()
+*/
+int QtxPagePrefFontItem::features() const
+{
+  return myFont->features();
+}
+
+/*!
+  \brief Set font widget features.
+  \param f new font widget features (ORed QtxFontEdit::Features flags)
+  \sa features()
+*/
+void QtxPagePrefFontItem::setFeatures( const int f )
+{
+  myFont->setFeatures( f );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefFontItem::store()
+{
+  setFont( myFont->currentFont() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefFontItem::retrieve()
+{
+  myFont->setCurrentFont( getFont() );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefFontItem::optionValue( const QString& name ) const
+{
+  if ( name == "features" )
+    return features();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefFontItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "features" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setFeatures( val.toInt() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \class  QtxPagePrefPathItem
+  \brief GUI implementation of the resources file/directory path item.
+*/
+
+/*!
+  \brief Constructor.
+  \param type path widget mode (Qtx::PathType )
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefPathItem::QtxPagePrefPathItem( const Qtx::PathType type, const QString& title,
+                                          QtxPreferenceItem* parent, const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myPath = new QtxPathEdit( type ) );
+}
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefPathItem::QtxPagePrefPathItem( const QString& title, QtxPreferenceItem* parent,
+                                          const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myPath = new QtxPathEdit() );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefPathItem::~QtxPagePrefPathItem()
+{
+}
+
+/*!
+  \brief Get path widget mode.
+  \return current path widget mode (Qtx::PathType)
+  \sa setPathType()
+*/
+Qtx::PathType QtxPagePrefPathItem::pathType() const
+{
+  return myPath->pathType();
+}
+
+/*!
+  \brief Set path widget mode.
+  \param type new path widget mode (Qtx::PathType)
+  \sa pathType()
+*/
+void QtxPagePrefPathItem::setPathType( const Qtx::PathType type )
+{
+  myPath->setPathType( type );
+}
+
+/*!
+  \brief Get currently used path widget filters.
+  \return file or directory path filters
+  \sa setPathFilter()
+*/
+QString QtxPagePrefPathItem::pathFilter() const
+{
+  return myPath->pathFilter();
+}
+
+/*!
+  \brief Set path widget filters.
+  \param f new file or directory path filters
+  \sa pathFilter()
+*/
+void QtxPagePrefPathItem::setPathFilter( const QString& f )
+{
+  myPath->setPathFilter( f );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefPathItem::store()
+{
+  setString( myPath->path() );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefPathItem::retrieve()
+{
+  myPath->setPath( getString() );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefPathItem::optionValue( const QString& name ) const
+{
+  if ( name == "path_type" )
+    return pathType();
+  else if ( name == "path_filter" )
+    return pathFilter();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefPathItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "path_type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setPathType( (Qtx::PathType)val.toInt() );
+  }
+  else if ( name == "path_filter" )
+  {
+    if ( val.canConvert( QVariant::String ) )
+      setPathFilter( val.toString() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \class  QtxPagePrefPathListItem
+  \brief GUI implementation of resources directory list item.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefPathListItem::QtxPagePrefPathListItem( QtxPreferenceItem* parent,
+                                                  const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( QString(), parent, sect, param )
+{
+  setControl( myPaths = new QtxPathListEdit() );
+}
+
+/*!
+  \brief Constructor.
+  \param type path list widget mode (Qtx::PathType)
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefPathListItem::QtxPagePrefPathListItem( const Qtx::PathType type, const QString& title,
+                                                  QtxPreferenceItem* parent, const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myPaths = new QtxPathListEdit( type ) );
+}
+
+/*!
+  \brief Constructor.
+  \param title preference item title
+  \param parent parent preference item
+  \param sect resource file section associated with the preference item
+  \param param resource file parameter associated with the preference item
+*/
+QtxPagePrefPathListItem::QtxPagePrefPathListItem( const QString& title, QtxPreferenceItem* parent,
+                                                  const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param )
+{
+  setControl( myPaths = new QtxPathListEdit() );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPagePrefPathListItem::~QtxPagePrefPathListItem()
+{
+}
+
+/*!
+  \brief Get path list widget mode.
+  \return currently used path list widget mode (Qtx::PathType)
+  \sa setPathType()
+*/
+Qtx::PathType QtxPagePrefPathListItem::pathType() const
+{
+  return myPaths->pathType();
+}
+
+/*!
+  \brief Set path list widget mode.
+  \param type new path list widget mode (Qtx::PathType)
+  \sa pathType()
+*/
+void QtxPagePrefPathListItem::setPathType( const Qtx::PathType type )
+{
+  myPaths->setPathType( type );
+}
+
+/*!
+  \brief Store preference item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPagePrefPathListItem::store()
+{
+  setString( myPaths->pathList().join( ";" ) );
+}
+
+/*!
+  \brief Retrieve preference item from the resource manager.
+  \sa store()
+*/
+void QtxPagePrefPathListItem::retrieve()
+{
+  myPaths->setPathList( getString().split( ";" ) );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPagePrefPathListItem::optionValue( const QString& name ) const
+{
+  if ( name == "path_type" )
+    return pathType();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPagePrefPathListItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "path_type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setPathType( (Qtx::PathType)val.toInt() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+/*!
+  \class  QtxPagePrefDateTimeItem
+  \brief GUI implementation of resources date/time item.
+*/
+
+QtxPagePrefDateTimeItem::QtxPagePrefDateTimeItem( const QString& title, QtxPreferenceItem* parent,
+                                                  const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+myType( DateTime )
+{
+  setControl( myDateTime = new QDateTimeEdit() );
+  myDateTime->setCalendarPopup( true );
+  myDateTime->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  updateDateTime();
+}
+
+QtxPagePrefDateTimeItem::QtxPagePrefDateTimeItem( const int type, const QString& title, QtxPreferenceItem* parent,
+                                                  const QString& sect, const QString& param )
+: QtxPageNamedPrefItem( title, parent, sect, param ),
+myType( type )
+{
+  setControl( myDateTime = new QDateTimeEdit() );
+  myDateTime->setCalendarPopup( true );
+  myDateTime->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  updateDateTime();
+}
+
+QtxPagePrefDateTimeItem::~QtxPagePrefDateTimeItem()
+{
+}
+
+int QtxPagePrefDateTimeItem::inputType() const
+{
+  return myType;
+}
+
+void QtxPagePrefDateTimeItem::setInputType( const int type )
+{
+  if ( myType == type )
+    return;
+
+  myType = type;
+  updateDateTime();
+}
+
+bool QtxPagePrefDateTimeItem::calendar() const
+{
+  return myDateTime->calendarPopup();
+}
+
+void QtxPagePrefDateTimeItem::setCalendar( const bool on )
+{
+  myDateTime->setCalendarPopup( on );
+}
+
+QDate QtxPagePrefDateTimeItem::maximumDate() const
+{
+  return myDateTime->maximumDate();
+}
+
+QTime QtxPagePrefDateTimeItem::maximumTime() const
+{
+  return myDateTime->maximumTime();
+}
+
+QDate QtxPagePrefDateTimeItem::minimumDate() const
+{
+  return myDateTime->minimumDate();
+}
+
+QTime QtxPagePrefDateTimeItem::minimumTime() const
+{
+  return myDateTime->minimumTime();
+}
+
+void QtxPagePrefDateTimeItem::setMaximumDate( const QDate& d )
+{
+  if ( d.isValid() )
+    myDateTime->setMaximumDate( d );
+  else
+    myDateTime->clearMaximumDate();
+}
+
+void QtxPagePrefDateTimeItem::setMaximumTime( const QTime& t )
+{
+  if ( t.isValid() )
+    myDateTime->setMaximumTime( t );
+  else
+    myDateTime->clearMaximumTime();
+}
+
+void QtxPagePrefDateTimeItem::setMinimumDate( const QDate& d )
+{
+  if ( d.isValid() )
+    myDateTime->setMinimumDate( d );
+  else
+    myDateTime->clearMinimumDate();
+}
+
+void QtxPagePrefDateTimeItem::setMinimumTime( const QTime& t )
+{
+  if ( t.isValid() )
+    myDateTime->setMinimumTime( t );
+  else
+    myDateTime->clearMinimumTime();
+}
+
+void QtxPagePrefDateTimeItem::store()
+{
+  QString str;
+  switch ( inputType() )
+  {
+  case Date:
+    str = myDateTime->date().toString( Qt::ISODate );
+    break;
+  case Time:
+    str = myDateTime->time().toString( Qt::ISODate );
+    break;
+  case DateTime:
+    str = myDateTime->dateTime().toString( Qt::ISODate );
+    break;
+  }
+
+  setString( str );
+}
+
+void QtxPagePrefDateTimeItem::retrieve()
+{
+  QString str = getString();
+  switch ( inputType() )
+  {
+  case Date:
+    myDateTime->setDate( QDate::fromString( str, Qt::ISODate ) );
+    break;
+  case Time:
+    myDateTime->setTime( QTime::fromString( str, Qt::ISODate ) );
+    break;
+  case DateTime:
+    myDateTime->setDateTime( QDateTime::fromString( str, Qt::ISODate ) );
+    break;
+  }
+}
+
+QVariant QtxPagePrefDateTimeItem::optionValue( const QString& name ) const
+{
+  if ( name == "input_type" || name == "type" )
+    return inputType();
+  else if ( name == "minimum_date" || name == "min_date" )
+    return minimumDate();
+  else if ( name == "maximum_date" || name == "max_date" )
+    return maximumDate();
+  else if ( name == "minimum_time" || name == "min_time" )
+    return minimumTime();
+  else if ( name == "maximum_time" || name == "max_time" )
+    return maximumTime();
+  else
+    return QtxPageNamedPrefItem::optionValue( name );
+}
+
+void QtxPagePrefDateTimeItem::setOptionValue( const QString& name, const QVariant& val )
+{
+  if ( name == "input_type" || name == "type" )
+  {
+    if ( val.canConvert( QVariant::Int ) )
+      setInputType( val.toInt() );
+  }
+  else if ( name == "minimum_date" || name == "min_date" )
+  {
+    if ( val.canConvert( QVariant::Date ) )
+      setMinimumDate( val.toDate() );
+  }
+  else if ( name == "maximum_date" || name == "max_date" )
+  {
+    if ( val.canConvert( QVariant::Date ) )
+      setMaximumDate( val.toDate() );
+  }
+  else if ( name == "minimum_time" || name == "min_time" )
+  {
+    if ( val.canConvert( QVariant::Time ) )
+      setMinimumTime( val.toTime() );
+  }
+  else if ( name == "maximum_time" || name == "max_time" )
+  {
+    if ( val.canConvert( QVariant::Time ) )
+      setMaximumTime( val.toTime() );
+  }
+  else
+    QtxPageNamedPrefItem::setOptionValue( name, val );
+}
+
+void QtxPagePrefDateTimeItem::updateDateTime()
+{
+  QString dispFmt;
+  switch ( inputType() )
+  {
+  case Date:
+    dispFmt = QDateEdit().displayFormat();
+    break;
+  case Time:
+    dispFmt = QTimeEdit().displayFormat();
+    break;
+  case DateTime:
+    dispFmt = QDateTimeEdit().displayFormat();
+    break;
+  }
+
+  myDateTime->setDisplayFormat( dispFmt );
+}
diff --git a/src/Qtx/QtxPagePrefMgr.h b/src/Qtx/QtxPagePrefMgr.h
new file mode 100644 (file)
index 0000000..67ceee7
--- /dev/null
@@ -0,0 +1,607 @@
+// 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
+//
+// File:      QtxPagePrefMgr.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXPAGEPREFMGR_H
+#define QTXPAGEPREFMGR_H
+
+#include "QtxPreferenceMgr.h"
+
+#include "QtxPathEdit.h"
+#include "QtxPathListEdit.h"
+
+#include <QFrame>
+#include <QLabel>
+#include <QPointer>
+
+class QtxGridBox;
+class QtxFontEdit;
+class QtxGroupBox;
+class QtxComboBox;
+class QtxColorButton;
+
+class QToolBox;
+class QLineEdit;
+class QTextEdit;
+class QCheckBox;
+class QTabWidget;
+class QToolButton;
+class QListWidget;
+class QFileDialog;
+class QDateTimeEdit;
+class QStackedWidget;
+
+class QTX_EXPORT QtxPagePrefMgr : public QFrame, public QtxPreferenceMgr
+{
+  Q_OBJECT
+
+public:
+  QtxPagePrefMgr( QtxResourceMgr*, QWidget* = 0 );
+  virtual ~QtxPagePrefMgr();
+
+  virtual QSize    sizeHint() const;
+  virtual QSize    minimumSizeHint() const;
+
+  virtual void     updateContents();
+
+signals:
+  void             resourceChanged( int );
+  void             resourceChanged( QString&, QString& );
+  void             resourcesChanged( const QMap<int, QString>& );
+
+public slots:
+  virtual void     setVisible( bool );
+
+protected:
+  virtual void     itemAdded( QtxPreferenceItem* );
+  virtual void     itemRemoved( QtxPreferenceItem* );
+  virtual void     itemChanged( QtxPreferenceItem* );
+
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             initialize() const;
+
+private:
+  QtxGridBox*      myBox;
+  bool             myInit;
+};
+
+class QTX_EXPORT QtxPagePrefItem : public QtxPreferenceItem
+{
+public:
+  QtxPagePrefItem( const QString&, QtxPreferenceItem* = 0,
+                   const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefItem();
+
+  virtual int       rtti() const;
+
+  QWidget*          widget() const;
+
+  static int        RTTI();
+
+protected:
+  void              setWidget( QWidget* );
+
+  virtual void      itemAdded( QtxPreferenceItem* );
+  virtual void      itemRemoved( QtxPreferenceItem* );
+  virtual void      itemChanged( QtxPreferenceItem* );
+
+  void              pageChildItems( QList<QtxPagePrefItem*>&, const bool = false ) const;
+
+  virtual void      store();
+  virtual void      retrieve();
+
+private:
+  virtual void      contentChanged();
+
+private:
+  QPointer<QWidget> myWidget;
+};
+
+class QTX_EXPORT QtxPageNamedPrefItem : public QtxPagePrefItem
+{
+public:
+  QtxPageNamedPrefItem( const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPageNamedPrefItem();
+
+  virtual void      setTitle( const QString& );
+
+protected:
+  QLabel*           label() const;
+  QWidget*          control() const;
+
+  void              setControl( QWidget* );
+
+private:
+  QPointer<QLabel>  myLabel;
+  QPointer<QWidget> myControl;
+};
+
+class QTX_EXPORT QtxPagePrefListItem : public QObject, public QtxPagePrefItem
+{
+  Q_OBJECT
+
+public:
+  QtxPagePrefListItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefListItem();
+
+  virtual void     updateContents();
+
+  QString          emptyInfo() const;
+  void             setEmptyInfo( const QString& );
+
+  bool             isFixedSize() const;
+  void             setFixedSize( const bool );
+
+private slots:
+  void             onItemSelectionChanged();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateInfo();
+  void             updateGeom();
+  void             updateState();
+  void             updateVisible();
+
+  int              selected() const;
+  QtxPagePrefItem* selectedItem() const;
+  void             setSelected( const int );
+
+private:
+  bool             myFix;
+  QListWidget*     myList;
+  QStackedWidget*  myStack;
+
+  QString          myInfText;
+  QLabel*          myInfLabel;
+};
+
+class QTX_EXPORT QtxPagePrefToolBoxItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefToolBoxItem( const QString&, QtxPreferenceItem* = 0,
+                          const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefToolBoxItem();
+
+  virtual void     updateContents();
+
+private:
+  void             updateToolBox();
+
+private:
+  QToolBox*        myToolBox;
+};
+
+class QTX_EXPORT QtxPagePrefTabsItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefTabsItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefTabsItem();
+
+  virtual void     updateContents();
+
+  int              tabPosition() const;
+  void             setTabPosition( const int );
+
+  int              tabShape() const;
+  void             setTabShape( const int );
+
+  QSize            tabIconSize() const;
+  void             setTabIconSize( const QSize& );
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateTabs();
+
+private:
+  QTabWidget*      myTabs;
+};
+
+class QTX_EXPORT QtxPagePrefFrameItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefFrameItem( const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefFrameItem();
+
+  virtual void     updateContents();
+
+  bool             stretch() const;
+  void             setStretch( const bool );
+
+  int              margin() const;
+  void             setMargin( const int );
+
+  int              spacing() const;
+  void             setSpacing( const int );
+
+  int              columns() const;
+  void             setColumns( const int );
+
+  Qt::Orientation  orientation() const;
+  void             setOrientation( const Qt::Orientation );
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateFrame();
+
+private:
+  QtxGridBox*      myBox;
+};
+
+class QTX_EXPORT QtxPagePrefGroupItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefGroupItem( const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  QtxPagePrefGroupItem( const int, const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefGroupItem();
+
+  virtual void     updateContents();
+
+  int              margin() const;
+  void             setMargin( const int );
+
+  int              spacing() const;
+  void             setSpacing( const int );
+
+  int              columns() const;
+  void             setColumns( const int );
+
+  Qt::Orientation  orientation() const;
+  void             setOrientation( const Qt::Orientation );
+
+  bool             isFlat() const;
+  void             setFlat( const bool );
+
+  virtual void     setResource( const QString&, const QString& );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateState();
+  void             updateGroup();
+
+private:
+  QtxGridBox*      myBox;
+  QtxGroupBox*     myGroup;
+};
+
+class QTX_EXPORT QtxPagePrefSpaceItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefSpaceItem( QtxPreferenceItem* = 0 );
+  QtxPagePrefSpaceItem( Qt::Orientation, QtxPreferenceItem* = 0 );
+  QtxPagePrefSpaceItem( const int, const int, QtxPreferenceItem* = 0 );
+  virtual ~QtxPagePrefSpaceItem();
+
+  int              size( Qt::Orientation ) const;
+  void             setSize( Qt::Orientation, const int );
+
+  int              stretch( Qt::Orientation ) const;
+  void             setStretch( Qt::Orientation, const int );
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             initialize( const int, const int, const int, const int );
+};
+
+class QTX_EXPORT QtxPagePrefCheckItem : public QtxPagePrefItem
+{
+public:
+  QtxPagePrefCheckItem( const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefCheckItem();
+
+  virtual void     setTitle( const QString& );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+private:
+  QCheckBox*       myCheck;
+};
+
+class QTX_EXPORT QtxPagePrefEditItem : public QtxPageNamedPrefItem
+{
+public:
+  typedef enum { String, Integer, Double } InputType;
+
+public:
+  QtxPagePrefEditItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  QtxPagePrefEditItem( const int, const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefEditItem();
+
+  int              inputType() const;
+  void             setInputType( const int );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateEditor();
+
+private:
+  int              myType;
+  QLineEdit*       myEditor;
+};
+
+class QTX_EXPORT QtxPagePrefSelectItem : public QtxPageNamedPrefItem
+{
+public:
+  typedef enum { NoInput, String, Integer, Double } InputType;
+
+public:
+  QtxPagePrefSelectItem( const QString&, QtxPreferenceItem* = 0,
+                         const QString& = QString(), const QString& = QString() );
+  QtxPagePrefSelectItem( const int, const QString&, QtxPreferenceItem* = 0,
+                         const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefSelectItem();
+
+  int              inputType() const;
+  void             setInputType( const int );
+
+  QStringList      strings() const;
+  QList<int>       numbers() const;
+
+  void             setStrings( const QStringList& );
+  void             setNumbers( const QList<int>& );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateSelector();
+  void             setStrings( const QVariant& );
+  void             setNumbers( const QVariant& );
+
+private:
+  int              myType;
+  QtxComboBox*     mySelector;
+};
+
+class QTX_EXPORT QtxPagePrefSpinItem : public QtxPageNamedPrefItem
+{
+public:
+  typedef enum { Integer, Double } InputType;
+
+public:
+  QtxPagePrefSpinItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  QtxPagePrefSpinItem( const int, const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefSpinItem();
+
+  QVariant         step() const;
+  QVariant         minimum() const;
+  QVariant         maximum() const;
+
+  QString          prefix() const;
+  QString          suffix() const;
+  QString          specialValueText() const;
+
+  void             setStep( const QVariant& );
+  void             setMinimum( const QVariant& );
+  void             setMaximum( const QVariant& );
+
+  void             setPrefix( const QString& );
+  void             setSuffix( const QString& );
+  void             setSpecialValueText( const QString& );
+
+  int              inputType() const;
+  void             setInputType( const int );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateSpinBox();
+
+private:
+  int              myType;
+};
+
+class QTX_EXPORT QtxPagePrefTextItem : public QtxPageNamedPrefItem
+{
+public:
+  QtxPagePrefTextItem( QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  QtxPagePrefTextItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefTextItem();
+
+  virtual void     store();
+  virtual void     retrieve();
+
+private:
+  QTextEdit*       myEditor;
+};
+
+class QTX_EXPORT QtxPagePrefColorItem : public QtxPageNamedPrefItem
+{
+public:
+  QtxPagePrefColorItem( const QString&, QtxPreferenceItem* = 0,
+                        const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefColorItem();
+
+  virtual void     store();
+  virtual void     retrieve();
+
+private:
+  QtxColorButton*  myColor;
+};
+
+class QTX_EXPORT QtxPagePrefFontItem : public QObject, public QtxPageNamedPrefItem
+{
+  Q_OBJECT
+
+public:
+  QtxPagePrefFontItem( const int, const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  QtxPagePrefFontItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefFontItem();
+
+  int              features() const;
+  void             setFeatures( const int );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  QtxFontEdit*     myFont;
+};
+
+class QTX_EXPORT QtxPagePrefPathItem : public QtxPageNamedPrefItem
+{
+public:
+  QtxPagePrefPathItem( const Qtx::PathType, const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  QtxPagePrefPathItem( const QString&, QtxPreferenceItem* = 0,
+                       const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefPathItem();
+
+  Qtx::PathType    pathType() const;
+  void             setPathType( const Qtx::PathType );
+
+  QString          pathFilter() const;
+  void             setPathFilter( const QString& );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+  
+private:
+  QtxPathEdit*     myPath;
+};
+
+class QTX_EXPORT QtxPagePrefPathListItem : public QtxPageNamedPrefItem
+{
+public:
+  QtxPagePrefPathListItem( QtxPreferenceItem* = 0,
+                           const QString& = QString(), const QString& = QString() );
+  QtxPagePrefPathListItem( const QString&, QtxPreferenceItem* = 0,
+                           const QString& = QString(), const QString& = QString() );
+  QtxPagePrefPathListItem( const Qtx::PathType, const QString&, QtxPreferenceItem* = 0,
+                           const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefPathListItem();
+
+  Qtx::PathType    pathType() const;
+  void             setPathType( const Qtx::PathType );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  QtxPathListEdit* myPaths;
+};
+
+class QTX_EXPORT QtxPagePrefDateTimeItem : public QtxPageNamedPrefItem
+{
+public:
+  typedef enum { Date, Time, DateTime } InputType;
+
+public:
+  QtxPagePrefDateTimeItem( const QString&, QtxPreferenceItem* = 0,
+                           const QString& = QString(), const QString& = QString() );
+  QtxPagePrefDateTimeItem( const int, const QString&, QtxPreferenceItem* = 0,
+                           const QString& = QString(), const QString& = QString() );
+  virtual ~QtxPagePrefDateTimeItem();
+
+  int              inputType() const;
+  void             setInputType( const int );
+
+  bool             calendar() const;
+  void             setCalendar( const bool );
+
+  QDate            maximumDate() const;
+  QTime            maximumTime() const;
+  QDate            minimumDate() const;
+  QTime            minimumTime() const;
+
+  void             setMaximumDate( const QDate& );
+  void             setMaximumTime( const QTime& );
+  void             setMinimumDate( const QDate& );
+  void             setMinimumTime( const QTime& );
+
+  virtual void     store();
+  virtual void     retrieve();
+
+protected:
+  virtual QVariant optionValue( const QString& ) const;
+  virtual void     setOptionValue( const QString&, const QVariant& );
+
+private:
+  void             updateDateTime();
+
+private:
+  int              myType;
+  QDateTimeEdit*   myDateTime;
+};
+
+#endif
diff --git a/src/Qtx/QtxPathDialog.cxx b/src/Qtx/QtxPathDialog.cxx
new file mode 100755 (executable)
index 0000000..d6989e6
--- /dev/null
@@ -0,0 +1,740 @@
+// 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
+//
+// File:      QtxPathDialog.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxPathDialog.h"
+
+#include "QtxGridBox.h"
+#include "QtxGroupBox.h"
+
+#include <QDir>
+#include <QLabel>
+#include <QPixmap>
+#include <QLayout>
+#include <QLineEdit>
+#include <QObjectList>
+#include <QStringList>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QPushButton>
+
+static const char* open_icon[] = {
+"16 16 5 1",
+"  c none",
+". c #ffff00",
+"# c #848200",
+"a c #ffffff",
+"b c #000000",
+"                ",
+"          bbb   ",
+"         b   b b",
+"              bb",
+"  bbb        bbb",
+" ba.abbbbbbb    ",
+" b.a.a.a.a.b    ",
+" ba.a.a.a.ab    ",
+" b.a.abbbbbbbbbb",
+" ba.ab#########b",
+" b.ab#########b ",
+" bab#########b  ",
+" bb#########b   ",
+" bbbbbbbbbbb    ",
+"                ",
+"                "
+};
+
+/*!
+  \class QtxPathDialog
+  \brief The QtxPathDialog class provides a simple convenience dialog to
+         enter a path to the file or to the directory.
+
+  The QtxPathDialog class adds possibility to browse the file system 
+  with help of standard Open/Save dialog boxes or enter the file/directory
+  path manually.
+
+  Default implementation provides only one "standard" file entry.
+  Sometimes it is necessary to select several different files/directories
+  from the same dialog box. In this case it is possible to derive from the
+  QtxPathDialog class and use createFileEntry() method to add required
+  number of file entries.
+*/
+
+/*!
+  \brief Constructor.
+  \param import if \c true, the dialog box is shown for "open" mode, 
+         otherwise, it is shown in the "save" mode
+  \param parent parent widget
+  \param modal if \c true, the dialog box should be modal
+  \param resize if \c true, the dialog box is resizable
+  \param buttons required buttons (QtxDialog::ButtonFlags)
+  \param f window flags
+*/
+QtxPathDialog::QtxPathDialog( const bool import, QWidget* parent, const bool modal,
+                              const bool resize, const int buttons, Qt::WindowFlags f )
+: QtxDialog( parent, modal, resize, buttons, f ),
+  myDefault( -1 ),
+  myEntriesFrame( 0 ),
+  myOptionsFrame( 0 )
+{
+  initialize();
+  
+  setWindowTitle( tr( import ? "Open file" : "Save file" ) );
+  
+  setDefaultEntry( createFileEntry( tr( "File name" ), import ? OpenFile : SaveFile ) );
+  QLineEdit* le = fileEntry( defaultEntry() );
+  if ( le )
+    le->setMinimumWidth( 200 );
+  
+  validate();
+
+  setFocusProxy( le );
+
+  updateVisibility();
+}
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+  \param modal if \c true, the dialog box should be modal
+  \param resize if \c true, the dialog box is resizable
+  \param buttons required buttons (QtxDialog::ButtonFlags)
+  \param f window flags
+*/
+QtxPathDialog::QtxPathDialog( QWidget* parent, const bool modal,
+                              const bool resize, const int buttons, Qt::WindowFlags f )
+: QtxDialog( parent, modal, resize, buttons, f ),
+  myDefault( -1 ),
+  myEntriesFrame( 0 ),
+  myOptionsFrame( 0 )
+{
+  initialize();
+
+  updateVisibility();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPathDialog::~QtxPathDialog()
+{
+}
+
+/*!
+  \brief Get selected file name.
+  \return file name
+*/
+QString QtxPathDialog::fileName() const
+{
+  return fileName( defaultEntry() );
+}
+
+/*!
+  \brief Set the file name.
+  \param txt new file name
+  \param autoExtension if \c true an extension is determined automatically by file
+*/
+void QtxPathDialog::setFileName( const QString& txt, const bool autoExtension )
+{
+  setFileName( defaultEntry(), txt, autoExtension );
+}
+
+/*!
+  \brief Get current file filter.
+  \return file filter
+*/
+QString QtxPathDialog::filter() const
+{
+  return filter( defaultEntry() );
+}
+
+/*!
+  \brief Change file filter.
+  
+  Filter is a list of file masks, separated by ';;'. For example, 
+  "*.h;;*.cxx"
+
+  \param fltr new file filter
+*/
+void QtxPathDialog::setFilter( const QString& fltr )
+{
+  setFilter( defaultEntry(), fltr );
+}
+
+/*!
+  \brief Show/hide the path dialog box/
+  \param on new visibility state
+*/
+void QtxPathDialog::setVisible( bool on )
+{
+  if ( on )
+    updateVisibility();
+
+  QtxDialog::setVisible( on );
+}
+
+/*!
+  \brief Called when user clicks a "browse" button 
+         to open standard file dialog.
+*/
+void QtxPathDialog::onBrowse()
+{
+  const QObject* obj = sender();
+
+  int id = -1;
+  
+  for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
+  {
+    if ( it.value().btn == obj )
+      id = it.key();
+  }
+  
+  if ( id == -1 )
+    return;
+  
+  FileEntry& entry = myEntries[id];
+  
+  bool isDir = entry.mode != OpenFile && entry.mode != SaveFile;
+  
+  if ( !entry.dlg )
+  {
+    entry.dlg = new QFileDialog( this, windowTitle(), QDir::current().path() );
+    switch ( entry.mode )
+    {
+    case NewDir:
+    case OpenDir:
+    case SaveDir:
+      isDir = true;
+      entry.dlg->setFileMode( QFileDialog::DirectoryOnly );
+      break;
+    case SaveFile:
+      entry.dlg->setFileMode( QFileDialog::AnyFile );
+      break;
+    case OpenFile:
+    default:
+      entry.dlg->setFileMode( QFileDialog::ExistingFiles );
+      break;
+    }
+  }
+  
+  if ( !isDir )
+  {
+    QStringList fList = prepareFilters( entry.filter );
+    if ( !fList.isEmpty() )
+      entry.dlg->setFilters( fList );
+  }
+  entry.dlg->selectFile( fileName( id ) );
+
+  if ( entry.dlg->exec() != Accepted )
+    return;
+  
+  QStringList fileList = entry.dlg->selectedFiles();
+  QString fName = !fileList.isEmpty() ? fileList.first() : QString();
+  
+  if ( fName.isEmpty() )
+    return;
+  
+  if ( Qtx::extension( fName ).isEmpty() && !isDir )
+    fName = autoExtension( fName, entry.dlg->selectedFilter() );
+
+  fName = QDir::convertSeparators( fName );
+  QString prev = QDir::convertSeparators( fileName( id ) );
+  if ( isDir )
+  {
+    while ( prev.length() && prev.at( prev.length() - 1 ) == QDir::separator() )
+      prev.remove( prev.length() - 1, 1 );
+    while ( fName.length() && fName.at( fName.length() - 1 ) == QDir::separator() )
+      fName.remove( fName.length() - 1, 1 );
+  }
+  
+  if ( prev == fName )
+    return;
+  
+  setFileName( id, fName );
+  fileNameChanged( id, fName );
+  
+  if ( id == defaultEntry() )
+    emit fileNameChanged( fName );
+}
+
+/*!
+  \brief Called when user presses \c Return key being in the line edit.
+*/
+void QtxPathDialog::onReturnPressed()
+{
+  const QObject* obj = sender();
+  
+  int id = -1;
+  for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
+  {
+    if ( it.value().edit == obj )
+      id = it.key();
+  }
+
+  if ( id == -1 )
+    return;
+  
+  fileNameChanged( id, fileName( id ) );
+  
+  if ( id == defaultEntry() )
+    emit fileNameChanged( fileName() );
+}
+
+/*!
+ \brief Called when the text in the line edit is changed by the user.
+ \param txt current text (not used)
+*/
+void QtxPathDialog::onTextChanged( const QString& /*txt*/ )
+{
+  validate();
+}
+
+/*!
+  \brief Check validity of the entered text and enable/disable standard
+  \c OK, \c Yes buttons.
+*/
+void QtxPathDialog::validate()
+{
+  setButtonEnabled( isValid(), OK | Yes );
+}
+
+/*!
+  \brief Check if the entered file/directory name is valid.
+  \return \c true if selected file name is valid
+*/
+bool QtxPathDialog::isValid()
+{
+  bool ok = true;
+  for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && ok; ++it )
+  {
+    if ( it.value().edit->isEnabled() )
+      ok = !it.value().edit->text().trimmed().isEmpty();
+  }
+  
+  return ok;
+}
+
+/*!
+  \brief Check if the entered data is acceptable.
+  \return \c true if entered data is acceptable
+*/
+bool QtxPathDialog::acceptData() const
+{
+  bool ok = true;
+       
+  QWidget* parent = (QWidget*)this;
+
+  FileEntryMap::ConstIterator it;
+  for ( it = myEntries.begin(); it != myEntries.end() && ok; ++it )
+  {
+    const FileEntry& entry = it.value();
+    QFileInfo fileInfo( entry.edit->text() );
+    if ( entry.edit->text().isEmpty() )
+    {
+      QMessageBox::critical( parent, windowTitle(), tr( "File name not specified" ),
+                            QMessageBox::Ok, QMessageBox::NoButton );
+      ok = false;
+    }
+    else switch ( entry.mode )
+    {
+    case OpenFile:
+      if ( !fileInfo.exists() )
+      {
+       QMessageBox::critical( parent, windowTitle(), tr( "File \"%1\" does not exist" ).arg( fileInfo.filePath() ),
+                              QMessageBox::Ok, QMessageBox::NoButton );
+       ok = false;
+      }
+      break;
+    case SaveFile:
+      if ( fileInfo.exists() )
+       ok = QMessageBox::warning( parent, windowTitle(), tr( "File \"%1\" already exist. Do you want to overwrite it?" ).arg( fileInfo.filePath() ),
+                                  QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
+      break;
+    case OpenDir:
+      if ( !fileInfo.exists() || !fileInfo.isDir() )
+      {
+       QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" does not exist" ).arg( fileInfo.filePath() ),
+                              QMessageBox::Ok, QMessageBox::NoButton );
+       ok = false;
+      }
+      break;
+    case SaveDir:
+      if ( fileInfo.exists() && !fileInfo.isDir() )
+      {
+       QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
+                              QMessageBox::Ok, QMessageBox::NoButton );
+       ok = false;
+      }
+      break;
+    case NewDir:
+      if ( fileInfo.exists() )
+      {
+       if ( !fileInfo.isDir() )
+       {
+         QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
+                                QMessageBox::Ok, QMessageBox::NoButton );
+         ok = false;
+       }
+       else if ( QDir( fileInfo.filePath() ).count() > 2 )
+         ok = QMessageBox::warning( parent, windowTitle(), tr( "Directory \"%1\" not empty. Do you want to remove all files in this directory?" ).arg( fileInfo.filePath() ),
+                                    QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
+      }
+      break;
+    default:
+      break;
+    }
+    
+    if ( !ok )
+      entry.edit->setFocus();
+  }
+  
+  return ok;
+}
+
+/*!
+  \brief Perform custom actions when the file name is changed.
+
+  This method can be redefined in the successor classes.
+  Default implementation does nothing.
+
+  \param id file entry
+  \param fileName file name
+*/
+void QtxPathDialog::fileNameChanged( int /*id*/, QString /*fileName*/ )
+{
+}
+
+/*!
+  \fn void QtxPathDialog::fileNameChanged( QString fileName );
+  \brief Emitted when the file name is changed.
+  \param fileName file name
+*/
+
+/*!
+  \brief Get options grame widget.
+  \return options frame widget
+*/
+QFrame* QtxPathDialog::optionsFrame()
+{
+  return myOptionsFrame;
+}
+
+/*!
+  \brief Get file name from specified entry.
+  \param id file entry ID
+  \return file name or null string if \a id is invalid
+*/
+QString QtxPathDialog::fileName( const int id ) const
+{
+  QString res;
+  if ( myEntries.contains( id ) )
+    res = myEntries[id].edit->text();
+  return res;
+}
+
+/*!
+  \brief Change file name by specified file entry.
+  \param id file entry ID
+  \param txt new file name
+  \param autoExt if \c true, assign extension automatically
+*/
+void QtxPathDialog::setFileName( const int id, const QString& txt, const bool autoExt )
+{
+  int mode;
+  QLineEdit* le = fileEntry( id, mode );
+       
+  if ( le )
+  {
+    if ( autoExt && ( mode == OpenFile || mode == SaveFile ) )
+      le->setText( autoExtension( txt, filter( id ) ) );
+    else
+      le->setText( txt );
+  }
+}
+
+/*!
+  \brief Get file filter from the specified file entry.
+  \param id file entry ID
+  \return file filter or null string if \a id is invalid
+*/
+QString QtxPathDialog::filter( const int id ) const
+{
+  QString res;
+  if ( myEntries.contains( id ) )
+    res = myEntries[id].filter;
+  return res;
+}
+
+/*!
+  \brief Set file filter to the specified file entry.
+  \param id file entry ID
+  \param filter file filter or null string if \a id is invalid
+*/
+void QtxPathDialog::setFilter( const int id, const QString& filter )
+{
+  if ( myEntries.contains( id ) )
+    myEntries[id].filter = filter;
+}
+
+/*!
+  \brief Get line edit widget for the specified file entry.
+  \param id file entry ID
+  \return line edit widget or 0 if \a id is invalid
+*/
+QLineEdit* QtxPathDialog::fileEntry( const int id ) const
+{
+  QLineEdit* le = 0;
+  if ( myEntries.contains( id ) )
+    le = myEntries[id].edit;
+  
+  return le;
+}
+
+/*!
+  \brief Get line edit widget and file mode for the specified file entry.
+  \param id file entry ID
+  \param theMode to return file entry mode
+  \return line edit widget or 0 if \a id is invalid
+*/
+QLineEdit* QtxPathDialog::fileEntry( const int theId, int& theMode ) const
+{
+  QLineEdit* le = 0;
+  if ( myEntries.contains( theId ) )
+  {
+    le = myEntries[theId].edit;
+    theMode = myEntries[theId].mode;
+  }
+  
+  return le;
+}
+
+/*!
+  \brief Create new file entry.
+
+  If required file entry is already in use or if specified \a id is < 0,
+  new ID is generated and returned.
+
+  \param lab file entry title
+  \param mode file entry mode
+  \param id required file entry ID
+  \return created file entry ID
+*/
+int QtxPathDialog::createFileEntry( const QString& lab, const int mode, 
+                                                           const QString& filter, const int id )
+{
+  int num = id;
+  if ( num == -1 )
+  {
+    num--;
+    while ( myEntries.contains( num ) )
+      num--;
+  }
+  
+  FileEntry entry;
+  entry.dlg = 0;
+  entry.mode = mode;
+  entry.filter = filter;
+  
+  new QLabel( lab, myEntriesFrame );
+  entry.edit = new QLineEdit( myEntriesFrame );
+
+  entry.btn = new QPushButton( myEntriesFrame );
+  entry.btn->setAutoDefault( false );
+  entry.btn->setIcon( QPixmap( open_icon ) );
+
+  Qtx::PathType type = Qtx::PT_OpenFile;
+  switch ( mode )
+  {
+  case OpenFile:
+    type = Qtx::PT_OpenFile;
+    break;
+  case SaveFile:
+    type = Qtx::PT_SaveFile;
+    break;
+  case OpenDir:
+  case SaveDir:
+  case NewDir:
+    type = Qtx::PT_Directory;
+    break;
+  }
+  entry.edit->setCompleter( Qtx::pathCompleter( type, filter ) );
+
+  connect( entry.btn, SIGNAL( clicked() ), this, SLOT( onBrowse() ) );
+  connect( entry.edit, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) );
+  connect( entry.edit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
+  
+  myEntries.insert( num, entry );
+  
+  return num;
+}
+
+/*!
+  \brief Get default file entry ID.
+  \return default entry ID
+*/
+int QtxPathDialog::defaultEntry() const
+{
+  return myDefault;
+}
+
+/*!
+  \brief Set default entry.
+  \param id new default entry ID
+*/
+void QtxPathDialog::setDefaultEntry( const int id )
+{
+  myDefault = id;
+}
+
+/*!
+  \brief Initialize dialog layout.
+*/
+void QtxPathDialog::initialize()
+{
+  setWindowTitle( tr( "File dialog" ) );
+
+  QVBoxLayout* main = new QVBoxLayout( mainFrame() );
+  main->setMargin( 0 );
+
+  QtxGroupBox* base = new QtxGroupBox( "", mainFrame() );
+  main->addWidget( base );
+  
+  QtxGridBox*  mainGroup = new QtxGridBox( 1, Qt::Horizontal, base, 0 );
+  base->setWidget( mainGroup );
+  
+  myEntriesFrame = new QtxGridBox( 3, Qt::Horizontal, mainGroup );
+  myOptionsFrame = new QFrame( mainGroup );
+}
+
+/*!
+  \brief Prepare file filters.
+  \param list of file masks, separated by ';;', for example, "*.h;;*.cxx"
+  \return list of processed file filters
+*/
+QStringList QtxPathDialog::prepareFilters( const QString& filter ) const
+{
+  QStringList res;
+  bool allFilter = false;
+  if ( !filter.isEmpty() )
+  {
+    res = filter.split( ";;" );
+    for ( QStringList::ConstIterator it = res.begin(); it != res.end() && !allFilter; ++it )
+    {
+      QStringList wildCards = filterWildCards( *it );
+      allFilter = wildCards.indexOf( "*.*" ) != -1;
+    }
+  }
+  
+  if ( !allFilter )
+    res.append( tr( "All files (*.*)" ) );
+  
+  return res;
+}
+
+/*!
+  \brief Get wildcards from the specified file filter.
+  \param theFilter file filter being processed
+  \return list of filters with filtered wild cards
+*/
+QStringList QtxPathDialog::filterWildCards( const QString& theFilter ) const
+{
+  QStringList res;
+
+  int b = theFilter.lastIndexOf( "(" );
+  int e = theFilter.lastIndexOf( ")" );
+  if ( b != -1 && e != -1 )
+  {
+    QString content = theFilter.mid( b + 1, e - b - 1 ).trimmed();
+    QStringList lst = content.split( " " );
+    for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
+    {
+      if ( (*it).indexOf( "." ) != -1 )
+       res.append( (*it).trimmed() );
+    }
+  }
+  return res;
+}
+
+/*!
+  \brief Get file file name with automatically assigned extension.
+  \param theFileName file name being processed
+  \param theFilter list of file filters
+  \return file name with assigned extension
+*/
+QString QtxPathDialog::autoExtension( const QString& theFileName, const QString& theFilter ) const
+{
+  QString fName = theFileName;
+
+  if ( fName.isEmpty() )
+    return fName;
+  
+  QString filter;
+  QStringList filters = prepareFilters( theFilter );
+  if ( !filters.isEmpty() )
+    filter = filters.first();
+
+  QStringList wildCards = filterWildCards( filter );
+  if ( !wildCards.isEmpty() )
+  {
+    QString ext = wildCards.first();
+    if ( ext.indexOf( "." ) != -1 )
+      ext = ext.mid( ext.indexOf( "." ) + 1 );
+    
+    if ( !ext.isEmpty() && !ext.contains( "*" ) )
+      fName = QDir::convertSeparators( fName ) + QString( "." ) + ext;
+  }
+  
+  return fName;
+}
+
+/*!
+  \brief Check if there are visible child widgets.
+  \param wid parent widget being checked
+  \return \c true if widget \a wid has visible children
+*/
+bool QtxPathDialog::hasVisibleChildren( QWidget* wid ) const
+{
+  bool res = false;
+  if ( wid )
+  {
+    const QObjectList& aChildren = wid->children();
+    for ( QObjectList::const_iterator it = aChildren.begin(); it != aChildren.end() && !res; ++it )
+    {
+      if ( (*it)->isWidgetType() )
+       res = ((QWidget*)(*it))->isVisibleTo( wid );
+    }
+  }
+  return res;
+}
+
+/*!
+  \brief Upadte dialof box's child widgets visibility state.
+*/
+void QtxPathDialog::updateVisibility()
+{
+  if ( hasVisibleChildren( myEntriesFrame ) )
+    myEntriesFrame->show();
+  else
+    myEntriesFrame->hide();
+  
+  if ( hasVisibleChildren( myOptionsFrame ) )
+    myOptionsFrame->show();
+  else
+    myOptionsFrame->hide();
+}
diff --git a/src/Qtx/QtxPathDialog.h b/src/Qtx/QtxPathDialog.h
new file mode 100755 (executable)
index 0000000..57b8877
--- /dev/null
@@ -0,0 +1,118 @@
+// 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
+//
+// File:      QtxPathDialog.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXPATHDIALOG_H
+#define QTXPATHDIALOG_H
+
+#include "QtxDialog.h"
+
+#include <QMap>
+
+class QFrame;
+class QLineEdit;
+class QPushButton;
+class QFileDialog;
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxPathDialog : public QtxDialog
+{
+  Q_OBJECT
+
+protected:
+  QtxPathDialog( QWidget* = 0, const bool = true, const bool = false,
+                 const int = Standard, Qt::WindowFlags = 0 );
+
+public:
+  QtxPathDialog( const bool, QWidget* = 0, const bool = true,
+                 const bool = false, const int = Standard, Qt::WindowFlags = 0 );
+  virtual ~QtxPathDialog();
+
+  QString            fileName() const;
+  void               setFileName( const QString&, const bool = false );
+
+  QString            filter() const;
+  void               setFilter( const QString& );
+
+signals:
+  void               fileNameChanged( QString );
+
+public slots:
+  virtual void       setVisible( bool );
+
+protected slots:
+  void               validate();
+
+private slots:
+  void               onBrowse();
+  void               onReturnPressed();
+  void               onTextChanged( const QString& );
+
+protected:
+  virtual bool       isValid();
+  virtual bool       acceptData() const;
+  virtual void       fileNameChanged( int, QString );
+
+  QFrame*            optionsFrame();
+  QString            fileName( const int ) const;
+  void               setFileName( const int, const QString&, const bool = false );
+
+  QString            filter( const int ) const;
+  void               setFilter( const int, const QString& );
+
+  QLineEdit*         fileEntry( const int ) const;
+  QLineEdit*         fileEntry( const int, int& ) const;
+  int                createFileEntry( const QString&, const int,
+                                      const QString& = QString(), const int = -1 );
+
+  int                defaultEntry() const;
+  void               setDefaultEntry( const int );
+
+private:
+  void               initialize();
+  void               updateVisibility();
+  QStringList        prepareFilters( const QString& ) const;
+       bool               hasVisibleChildren( QWidget* ) const;
+  QStringList        filterWildCards( const QString& ) const;
+  QString            autoExtension( const QString&, const QString& = QString::null ) const;
+
+protected:
+  enum { OpenFile, SaveFile, OpenDir, SaveDir, NewDir };
+
+private:
+  typedef struct { int mode; QLineEdit* edit; QString filter;
+                   QPushButton* btn; QFileDialog* dlg; } FileEntry;
+  typedef QMap<int, FileEntry> FileEntryMap;
+
+private:
+  FileEntryMap       myEntries;
+  int                myDefault;
+  QWidget*           myEntriesFrame;
+  QFrame*            myOptionsFrame;
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
diff --git a/src/Qtx/QtxPathEdit.cxx b/src/Qtx/QtxPathEdit.cxx
new file mode 100644 (file)
index 0000000..3e0c37f
--- /dev/null
@@ -0,0 +1,248 @@
+// 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
+//
+// File:      QtxPathEdit.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxPathEdit.h"
+
+#include <QLayout>
+#include <QDirModel>
+#include <QLineEdit>
+#include <QCompleter>
+#include <QToolButton>
+#include <QFileDialog>
+#include <QRegExpValidator>
+
+static const char* browse_icon[] = {
+"16 16 5 1",
+"  c none",
+". c #ffff00",
+"# c #848200",
+"a c #ffffff",
+"b c #000000",
+"                ",
+"          bbb   ",
+"         b   b b",
+"              bb",
+"  bbb        bbb",
+" ba.abbbbbbb    ",
+" b.a.a.a.a.b    ",
+" ba.a.a.a.ab    ",
+" b.a.abbbbbbbbbb",
+" ba.ab#########b",
+" b.ab#########b ",
+" bab#########b  ",
+" bb#########b   ",
+" bbbbbbbbbbb    ",
+"                ",
+"                "
+};
+
+/*!
+  \class QtxPathEdit
+  \brief The QtxPathEdit class represents a widget for file or directory
+  path preference items editing.
+
+  The path preference item is represented as the line edit box for the 
+  direct path editing and small button clicking on which invokes browse
+  dialog box. The widget can be used in different modes: "Open File", 
+  "Save File", "Select Directory". The mode defines the type of the
+  standard browse dialog box which is invoked on the button clicking.
+
+  Initial path value can be set with setPath() method. Chosen path
+  can be retrieved with the path() method. The widget mode can be set 
+  with setPathType() and retrieved with pathType() method.
+
+  In addition, file/direcrory filters (wildcards) can be set with the
+  setPathFilter() method and retrieved with pathFilter() method.
+*/
+
+/*!
+  \brief Constructor
+  \param type widget mode (Qtx::PathType)
+  \param parent parent widget
+  \sa pathType(), setPathType()
+*/
+QtxPathEdit::QtxPathEdit( const Qtx::PathType type, QWidget* parent )
+: QFrame( parent ),
+  myType( type )
+{
+  initialize();
+}
+
+/*!
+  \brief Constructor
+
+  Qtx::PT_OpenFile mode is used by default.
+
+  \param parent parent widget
+  \sa pathType(), setPathType()
+*/
+QtxPathEdit::QtxPathEdit( QWidget* parent )
+: QFrame( parent ),
+  myType( Qtx::PT_OpenFile )
+{
+  initialize();
+}
+
+/*!
+  \brief Destructor
+*/
+QtxPathEdit::~QtxPathEdit()
+{
+}
+
+/*!
+  \brief Get widget mode.
+  \return currently used widget mode (Qtx::PathType)
+  \sa setPathType()
+*/
+Qtx::PathType QtxPathEdit::pathType() const
+{
+  return myType;
+}
+
+/*!
+  \brief Set widget mode.
+  \param type new widget mode (Qtx::PathType)
+  \sa pathType()
+*/
+void QtxPathEdit::setPathType( const Qtx::PathType type )
+{
+  if ( myType == type )
+    return;
+
+  myType = type;
+  updateState();
+}
+
+/*!
+  \brief Get currently selected path.
+  \return file or directory path entered by the user
+  \sa setPath()
+*/
+QString QtxPathEdit::path() const
+{
+  return myPath->text();
+}
+
+/*!
+  \brief Set path.
+  \param txt file or directory path 
+  \sa path()
+*/
+void QtxPathEdit::setPath( const QString& txt )
+{
+  myPath->setText( txt );
+}
+
+/*!
+  \brief Get currently used path filters.
+  \return file or directory path filters
+  \sa setPathFilter()
+*/
+QString QtxPathEdit::pathFilter() const
+{
+  return myFilter;
+}
+
+/*!
+  \brief Set path filters.
+  \param f new file or directory path filters
+  \sa pathFilter()
+*/
+void QtxPathEdit::setPathFilter( const QString& f )
+{
+  if ( myFilter == f )
+    return;
+
+  myFilter = f;
+  updateState();
+}
+
+/*!
+  \brief Called when user clicks "Browse" button. 
+
+  Invokes standard browsng dialog box depending on the used widget mode.
+
+  \param on (not used)
+  \sa mode(), setMode()
+*/
+void QtxPathEdit::onBrowse( bool /*on*/ )
+{
+  QString path;
+  QString initial = QFileInfo( myPath->text() ).path();
+  switch ( pathType() )
+  {
+  case Qtx::PT_OpenFile:
+    path = QFileDialog::getOpenFileName( myPath, QString(), initial, pathFilter() );
+    break;
+  case Qtx::PT_SaveFile:
+    path = QFileDialog::getSaveFileName( myPath, QString(), initial, pathFilter() );
+    break;
+  case Qtx::PT_Directory:
+    path = QFileDialog::getExistingDirectory( myPath, QString(), initial );
+    break;
+  }
+
+  if ( !path.isEmpty() )
+    myPath->setText( QDir::convertSeparators( path ) ); 
+
+  myPath->setFocus();
+}
+
+/*!
+  \brief Get internal line edit widget.
+  \return line edit box widget
+*/
+QLineEdit* QtxPathEdit::lineEdit() const
+{
+  return myPath;
+}
+
+/*!
+  \brief Perform internal widget intialization.
+*/
+void QtxPathEdit::initialize()
+{
+  QHBoxLayout* base = new QHBoxLayout( this );
+  base->setMargin( 0 );
+  base->setSpacing( 5 );
+
+  base->addWidget( myPath = new QLineEdit( this ) );
+  myPath->setValidator( new QRegExpValidator( QRegExp( "^([\\w/]{2}|[A-Z]:)[^:;\\*\\?]*[\\w\\\\/\\.]$" ), myPath ) );
+
+  QToolButton* browse = new QToolButton( this );
+  browse->setIcon( QPixmap( browse_icon ) );
+  base->addWidget( browse );
+
+  connect( browse, SIGNAL( clicked( bool ) ), this, SLOT( onBrowse( bool ) ) );
+
+  setFocusProxy( myPath );
+
+  updateState();
+}
+
+/*!
+  \brief Update widget state.
+*/
+void QtxPathEdit::updateState()
+{
+  myPath->setCompleter( Qtx::pathCompleter( pathType(), pathFilter() ) );
+}
diff --git a/src/Qtx/QtxPathEdit.h b/src/Qtx/QtxPathEdit.h
new file mode 100644 (file)
index 0000000..c4fe189
--- /dev/null
@@ -0,0 +1,65 @@
+// 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
+//
+// File:      QtxPathEdit.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXPATHEDIT_H
+#define QTXPATHEDIT_H
+
+#include "Qtx.h"
+
+#include <QFrame>
+
+class QLineEdit;
+
+class QTX_EXPORT QtxPathEdit : public QFrame
+{
+  Q_OBJECT
+
+public:
+  QtxPathEdit( const Qtx::PathType, QWidget* = 0 );
+  QtxPathEdit( QWidget* = 0 );
+  virtual ~QtxPathEdit();
+
+  QString       path() const;
+  void          setPath( const QString& );
+
+  Qtx::PathType pathType() const;
+  void          setPathType( const Qtx::PathType );
+
+  QString       pathFilter() const;
+  void          setPathFilter( const QString& );
+
+private slots:
+  void          onBrowse( bool = false );
+
+protected:
+  QLineEdit*    lineEdit() const;
+
+private:
+  void          initialize();
+  void          updateState();
+
+private:
+  QLineEdit*    myPath;
+  Qtx::PathType myType;
+  QString       myFilter;
+};
+
+#endif
diff --git a/src/Qtx/QtxPathListEdit.cxx b/src/Qtx/QtxPathListEdit.cxx
new file mode 100644 (file)
index 0000000..dee61a3
--- /dev/null
@@ -0,0 +1,811 @@
+// 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
+//
+// File:      QtxPathListEdit.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxPathListEdit.h"
+
+#include "QtxPathEdit.h"
+
+#include <QLayout>
+#include <QPainter>
+#include <QListView>
+#include <QLineEdit>
+#include <QKeyEvent>
+#include <QDirModel>
+#include <QCompleter>
+#include <QToolButton>
+#include <QMessageBox>
+#include <QFileDialog>
+#include <QItemDelegate>
+#include <QStringListModel>
+
+static const char* delete_icon[] = {
+"16 16 3 1",
+"` c #810000",
+"  c none",
+"# c #ffffff",
+"                ",
+"                ",
+" ``#        ``# ",
+" ````#     ``#  ",
+"  ````#   ``#   ",
+"    ```# `#     ",
+"     `````#     ",
+"      ```#      ",
+"     `````#     ",
+"    ```# ``#    ",
+"   ```#   ``#   ",
+"  ```#     `#   ",
+"  ```#      `#  ",
+"   `#        `# ",
+"                ",
+"                "
+};
+
+static const char* insert_icon[] = {
+"16 16 5 1",
+"` c #000000",
+". c #ffff00",
+"# c #9d9da1",
+"  c none",
+"b c #ffffff",
+"                ",
+"                ",
+" #  #b #.       ",
+"  # #.#.` ` `   ",
+"  .#.b####   `  ",
+" ### ..         ",
+"  . # .#     `  ",
+" #` #.          ",
+"    #        `  ",
+"  `             ",
+"             `  ",
+"  `             ",
+"             `  ",
+"  ` ` ` ` ` `   ",
+"                ",
+"                "
+};
+
+static const char* movedown_icon[] = {
+"16 16 2 1",
+"` c #000000",
+"  c none",
+"                ",
+"                ",
+"         ```    ",
+"        ```     ",
+"       ```      ",
+"       ```      ",
+"       ```      ",
+"       ```      ",
+"   ```````````  ",
+"    `````````   ",
+"     ```````    ",
+"      `````     ",
+"       ```      ",
+"        `       ",
+"                ",
+"                "
+};
+
+static const char* moveup_icon[] = {
+"16 16 2 1",
+"` c #000000",
+"  c none",
+"                ",
+"                ",
+"        `       ",
+"       ```      ",
+"      `````     ",
+"     ```````    ",
+"    `````````   ",
+"   ```````````  ",
+"       ```      ",
+"       ```      ",
+"       ```      ",
+"       ```      ",
+"      ```       ",
+"     ```        ",
+"                ",
+"                "
+};
+
+
+/*!
+  \class QtxPathListEdit::Editor
+  \brief Path editor widget
+  \internal
+*/
+
+class QtxPathListEdit::Editor : public QtxPathEdit
+{
+public:
+  /*!
+    \brief Constructor
+    \internal
+  */
+  Editor( QWidget* parent = 0 ) : QtxPathEdit( parent )
+  {
+    layout()->setSpacing( 0 );
+    lineEdit()->setFrame( false );
+  }
+
+  /*!
+    \brief Destructor
+    \internal
+  */
+  virtual ~Editor() {}
+};
+
+/*!
+  \class QtxPathListEdit::Delegate
+  \brief Custom item delegate for the paths list widget.
+  \internal
+*/
+
+class QtxPathListEdit::Delegate : public QItemDelegate
+{
+public:
+  Delegate( QtxPathListEdit*, QObject* = 0 );
+  virtual ~Delegate();
+
+  virtual QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
+  virtual void     setModelData( QWidget*, QAbstractItemModel*, const QModelIndex& ) const;
+  virtual void     setEditorData( QWidget*, const QModelIndex& ) const;
+  virtual void     paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
+
+protected:
+  virtual void     drawFocus( QPainter*, const QStyleOptionViewItem&, const QRect& ) const;
+
+private:
+  QtxPathListEdit* myPathEdit;
+};
+
+/*!
+  \brief Constructor.
+  \internal
+  \param pe path list editor
+  \param parent parent widget
+*/
+QtxPathListEdit::Delegate::Delegate( QtxPathListEdit* pe, QObject* parent )
+: QItemDelegate( parent ),
+  myPathEdit( pe )
+{
+}
+
+/*!
+  \brief Destructor.
+  \internal
+*/
+QtxPathListEdit::Delegate::~Delegate()
+{
+}
+
+/*!
+  \brief Create editor widget.
+  \internal
+  \param parent parent widget
+  \param option style option
+  \param index data model index
+*/
+QWidget* QtxPathListEdit::Delegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option,
+                                                  const QModelIndex& index ) const
+{
+  return myPathEdit->createEditor( parent );
+}
+
+/*!
+  \brief Set modified data back to the data model.
+  \internal
+  \param editor editor widget
+  \param model data model
+  \param index data model index
+*/
+void QtxPathListEdit::Delegate::setModelData( QWidget* editor, QAbstractItemModel* model,
+                                              const QModelIndex& index ) const
+{
+  myPathEdit->setModelData( editor, index );
+}
+
+/*!
+  \brief Set data from the data model to the editor.
+  \internal
+  \param editor editor widget
+  \param index data model index
+*/
+void QtxPathListEdit::Delegate::setEditorData( QWidget* editor, const QModelIndex& index ) const
+{
+  myPathEdit->setEditorData( editor, index );
+}
+
+/*!
+  \brief Customize paint operation.
+  \internal
+  \param painter painter
+  \param option style option
+  \param index data model index
+*/
+void QtxPathListEdit::Delegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
+                                       const QModelIndex& index ) const
+{
+  QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
+  if ( cg == QPalette::Normal && !( option.state & QStyle::State_Active ) )
+    cg = QPalette::Inactive;
+
+  if ( option.state & QStyle::State_Selected )
+  {
+    painter->fillRect( option.rect, option.palette.brush( cg, QPalette::Highlight ) );
+    painter->setPen( option.palette.color( cg, QPalette::HighlightedText ) );
+  }
+  else
+    painter->setPen( option.palette.color( cg, QPalette::Text ) );
+
+  QItemDelegate::paint( painter, option, index );
+}
+
+/*!
+  \brief Customize drawing selection focus operation.
+  \internal
+  \param painter painter
+  \param option style option
+  \param rect selection rectangle
+*/
+void QtxPathListEdit::Delegate::drawFocus( QPainter* painter, const QStyleOptionViewItem& option,
+                                           const QRect& rect ) const
+{
+  QItemDelegate::drawFocus( painter, option, option.rect );
+}
+
+/*!
+  \class QtxPathListEdit
+  \brief The QtxPathListEdit class represents a widget for files or 
+  directories paths list preference items editing.
+
+  The path list preference item is represented as the list box widget.
+  It provides such operations like adding new file/directory path to the
+  list, removing selected paths and modifying of already entered ones.
+
+  The widget can be used in two modes: list of files or list of directories.
+  The mode defines the type of the standard browse dialog box which is
+  invoked on the browse button clicking.
+
+  Initial path list value can be set with setPathList() method. Chosen path
+  list can be retrieved with the pathList() method. The widget mode can be set 
+  with setPathType() and retrieved with pathType() method.
+
+  In addition, it is possible to add path items to the list with the insert()
+  method, remove items with the remove() methods, clear all the widget contents
+  with the clear() method. To get the number of entered paths can be retrieved
+  with the count() method. To check if any path already exists in the paths list,
+  use contains() method.
+*/
+
+/*!
+  \brief Constructor.
+  \param type widget mode (Qtx::PathType)
+  \param parent parent widget
+  \sa pathType(), setPathType()
+*/
+QtxPathListEdit::QtxPathListEdit( const Qtx::PathType type, QWidget* parent )
+: QFrame( parent ),
+  myCompleter( 0 ),
+  myType( type ),
+  myDuplicate( false )
+{
+  initialize();
+}
+
+/*!
+  \brief Constructor.
+
+  Qtx::PT_OpenFile mode is used by default.
+
+  \param parent parent widget
+  \sa pathType(), setPathType()
+*/
+QtxPathListEdit::QtxPathListEdit( QWidget* parent )
+: QFrame( parent ),
+  myCompleter( 0 ),
+  myType( Qtx::PT_OpenFile ),
+  myDuplicate( false )
+{
+  initialize();
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPathListEdit::~QtxPathListEdit()
+{
+}
+
+/*!
+  \brief Get widget mode.
+  \return currently used widget mode (Qtx::PathType)
+  \sa setPathType()
+*/
+Qtx::PathType QtxPathListEdit::pathType() const
+{
+  return myType;
+}
+
+/*!
+  \brief Set widget mode.
+  \param t new widget mode (Qtx::PathType)
+  \sa pathType()
+*/
+void QtxPathListEdit::setPathType( const Qtx::PathType t )
+{
+  if ( myType == t )
+    return;
+
+  myType = t;
+
+  delete myCompleter;
+  myCompleter = 0;
+}
+
+/*!
+  \brief Get currently selected paths list.
+  \return files or directories paths list entered by the user
+  \sa setPathList()
+*/
+QStringList QtxPathListEdit::pathList() const
+{
+  return myModel->stringList();
+}
+
+/*!
+  \brief Set paths list.
+  \param lst files or directories paths list
+  \sa pathList()
+*/
+void QtxPathListEdit::setPathList( const QStringList& lst )
+{
+  myModel->setStringList( lst );
+}
+
+/*!
+  \brief Check if the duplication of paths is enabled.
+  \return \c true if the duplication is enabled
+*/
+bool QtxPathListEdit::isDuplicateEnabled() const
+{
+  return myDuplicate;
+}
+
+/*!
+  \brief Enable/disable paths duplication.
+  \param on new flag value
+*/
+void QtxPathListEdit::setDuplicateEnabled( const bool on )
+{
+  myDuplicate = on;
+}
+
+/*!
+  \brief Get number of currently entered paths.
+  \return current paths number
+*/
+int QtxPathListEdit::count() const
+{
+  return myModel->rowCount();
+}
+
+/*!
+  \brief Check if the specified \a path already exists in 
+  the paths list.
+  \param path path to be checked
+  \return \c true if the path is already selected by the user 
+  or \c false otherwise
+*/
+bool QtxPathListEdit::contains( const QString& path ) const
+{
+  return myModel->stringList().contains( path );
+}
+
+/*!
+  \brief Clear paths list.
+*/
+void QtxPathListEdit::clear()
+{
+  myModel->removeRows( 0, myModel->rowCount() );
+}
+
+/*!
+  \brief Remove path from the paths list.
+  \param idx path index in the list
+*/
+void QtxPathListEdit::remove( const int idx )
+{
+  if ( 0 <= idx && idx < myModel->rowCount() )
+    myModel->removeRow( idx );
+}
+
+/*!
+  \brief Remove path from the paths list.
+  \param path path to be removed
+*/
+void QtxPathListEdit::remove( const QString& path )
+{
+  QModelIndexList indexes = myModel->match( myModel->index( 0, 0 ), Qt::DisplayRole, path,
+                                            myModel->rowCount(), Qt::MatchExactly | Qt::MatchCaseSensitive );
+  while ( !indexes.isEmpty() )
+  {
+    myModel->removeRow( indexes.last().row() );
+    indexes.removeLast();
+  }
+}
+
+/*!
+  \brief Add path to the list of paths.
+
+  If the specified index is out of range, the path is added to 
+  the end of the list.
+
+  \param path path to be added
+  \param idx index in the list to which the path should be inserted.
+*/
+void QtxPathListEdit::insert( const QString& path, const int idx )
+{
+  int index = idx < 0 ? myModel->rowCount() : qMin( idx, myModel->rowCount() );
+  if ( myModel->insertRow( index ) )
+    myModel->setData( myModel->index( index, 0 ), path, Qt::EditRole );
+}
+
+/*
+bool QtxPathListEdit::validate( const bool quietMode )
+{
+  if ( myEdited )
+  {
+    QString dirPath = QFileInfo( myEdit->text().stripWhiteSpace() ).filePath();
+    QDir dir(dirPath);
+    QListBoxItem* found = 0;
+    for (unsigned i = 0; i < myList->count()-1; i++) {
+      QDir aDir(myList->text(i));
+      if ( aDir.canonicalPath().isNull() && myList->text(i) == dir.absPath() ||
+          !aDir.canonicalPath().isNull() && aDir.exists() && aDir.canonicalPath() == dir.canonicalPath()) {
+          found = myList->item(i);
+        break;
+      }
+    }
+    if (dirPath.isEmpty()) {
+      if (found) {
+        // it should be last (empty) item in the list - nothing to do
+        return true;
+      }
+      else {
+        // delete directory from the list
+        removeDir(myLastSelected);
+        return true;
+      }
+    }
+    else {
+      if (found) {
+        if (found != myLastSelected) {
+          // it is forbidden to add directory more then once
+         if ( !quietMode )
+           QMessageBox::critical(this, 
+                                 tr("Error"),
+                                 tr("Directory already specified."), 
+                                 tr("Ok"));
+         myEdit->setFocus();
+          return false;
+        }
+      }
+      else {
+        if (!dir.exists()) {
+         if ( !quietMode && QMessageBox::information(this, 
+                                                     tr("Warning"),
+                                                     tr("%1\n\nThe directory doesn't exist.\nAdd directory anyway?").arg(dir.absPath()),
+                                                     tr("Yes"), tr("No"), QString::null, 1, 1) == 1) {
+           myEdit->setFocus();
+            return false;
+         }
+        }
+        // append
+        appendDir(myLastSelected, dir.absPath());
+      }
+    }
+  }
+  return true;
+}
+*/
+
+/*!
+  \brief Customize child widget events processing.
+  \param o event receiver object
+  \param e event
+  \return \c true if the further event processing should be stopped.
+*/
+bool QtxPathListEdit::eventFilter( QObject* o, QEvent* e )
+{
+  if ( e->type() == QEvent::KeyPress )
+  {
+    QKeyEvent* ke = (QKeyEvent*)e;
+    if ( ke->key() == Qt::Key_Delete )
+      onDelete();
+    else if ( ke->key() == Qt::Key_Insert )
+      onInsert();
+    else if ( ke->key() == Qt::Key_Up && ke->modifiers() == Qt::CTRL )
+    {
+      onUp();
+      return true;
+    }
+    else if ( ke->key() == Qt::Key_Down && ke->modifiers() == Qt::CTRL )
+    {
+      onDown();
+      return true;
+    }
+  }
+
+  return QFrame::eventFilter( o, e );
+}
+
+/*!
+  \brief Called when <Insert> button is clicked.
+
+  Inserts new empty line to the list and sets input focus to it.
+
+  \param on (not used)
+*/
+void QtxPathListEdit::onInsert( bool /*on*/ )
+{
+  int empty = -1;
+  QStringList lst = myModel->stringList();
+  for ( int r = 0; r < lst.count() && empty == -1; r++ )
+  {
+    if ( lst.at( r ).isEmpty() )
+      empty = r;
+  }
+
+  if ( empty == -1 )
+    myModel->insertRows( empty = myModel->rowCount(), 1 );
+
+  QModelIndex idx = myModel->index( empty, 0 );
+  myList->setCurrentIndex( idx );
+  myList->edit( idx );
+}
+
+/*!
+  \brief Called when <Delete> button is clicked.
+
+  Removes currently selected path item.
+  
+  \param on (not used)
+*/
+void QtxPathListEdit::onDelete( bool )
+{
+  QModelIndex idx = myList->currentIndex();
+  if ( !idx.isValid() )
+    return;
+
+  myModel->removeRow( idx.row() );
+}
+
+/*!
+  \brief Called when <Up> button is clicked.
+
+  Move currently selected path item up to one row in the paths list.
+
+  \param on (not used)
+*/
+void QtxPathListEdit::onUp( bool )
+{
+  QModelIndex idx = myList->currentIndex();
+  if ( !idx.isValid() || idx.row() < 1 )
+    return;
+
+  QModelIndex toIdx = myModel->index( idx.row() - 1, 0 );
+
+  QVariant val = myModel->data( toIdx, Qt::DisplayRole );
+  myModel->setData( toIdx, myModel->data( idx, Qt::DisplayRole ), Qt::DisplayRole );
+  myModel->setData( idx, val, Qt::DisplayRole );
+
+  myList->setCurrentIndex( toIdx );
+}
+
+/*!
+  \brief Called when <Down> button is clicked.
+
+  Move currently selected path item down to one row in the paths list.
+
+  \param on (not used)
+*/
+void QtxPathListEdit::onDown( bool )
+{
+  QModelIndex idx = myList->currentIndex();
+  if ( !idx.isValid() || idx.row() >= myModel->rowCount() - 1 )
+    return;
+
+  QModelIndex toIdx = myModel->index( idx.row() + 1, 0 );
+
+  QVariant val = myModel->data( toIdx, Qt::DisplayRole );
+  myModel->setData( toIdx, myModel->data( idx, Qt::DisplayRole ), Qt::DisplayRole );
+  myModel->setData( idx, val, Qt::DisplayRole );
+
+  myList->setCurrentIndex( toIdx );
+}
+
+/*!
+  \brief Perform internal widget initialization.
+*/
+void QtxPathListEdit::initialize()
+{
+  QVBoxLayout* base = new QVBoxLayout( this );
+  base->setMargin( 0 );
+  base->setSpacing( 5 );
+
+  QWidget* cBox = new QWidget( this );
+  base->addWidget( cBox );
+  
+  QHBoxLayout* cLayout = new QHBoxLayout( cBox );
+  cLayout->setMargin( 0 );
+  cLayout->setSpacing( 0 );
+
+  cLayout->addStretch( 1 );
+
+  QToolButton* insertBtn = new QToolButton( cBox );
+  insertBtn->setIcon( QPixmap( insert_icon ) );
+  cLayout->addWidget( insertBtn );
+
+  QToolButton* deleteBtn = new QToolButton( cBox );
+  deleteBtn->setIcon( QPixmap( delete_icon ) );
+  cLayout->addWidget( deleteBtn );
+
+  QToolButton* upBtn = new QToolButton( cBox );
+  upBtn->setIcon( QPixmap( moveup_icon ) );
+  cLayout->addWidget( upBtn );
+
+  QToolButton* downBtn = new QToolButton( cBox );
+  downBtn->setIcon( QPixmap( movedown_icon ) );
+  cLayout->addWidget( downBtn );
+
+
+  myList = new QListView( this );
+  myList->setAlternatingRowColors( true );
+  myList->setItemDelegate( new Delegate( this, myList ) );
+  myList->setModel( myModel = new QStringListModel( myList ) );
+  myList->setSelectionMode( QListView::SingleSelection );
+  myList->setSelectionBehavior( QListView::SelectRows );
+  myList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+  myList->setEditTriggers( QListView::DoubleClicked );
+  myList->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
+  myList->installEventFilter( this );
+
+  base->addWidget( myList );
+
+  connect( insertBtn, SIGNAL( clicked( bool ) ), this, SLOT( onInsert( bool ) ) );
+  connect( deleteBtn, SIGNAL( clicked( bool ) ), this, SLOT( onDelete( bool ) ) );
+  connect( upBtn,     SIGNAL( clicked( bool ) ), this, SLOT( onUp( bool ) ) );
+  connect( downBtn,   SIGNAL( clicked( bool ) ), this, SLOT( onDown( bool ) ) );
+}
+
+/*!
+  \brief Create editor widget.
+  \param parent parent widget for the editor
+  \return created editor widget
+*/
+QWidget* QtxPathListEdit::createEditor( QWidget* parent )
+{
+  QtxPathEdit* edit = new Editor( parent );
+  edit->setPathType( pathType() );
+  return edit;
+}
+
+/*!
+  \brief Set modified data from the editor to the list widget.
+  \param editor editor widget
+  \param index data model index
+*/
+void QtxPathListEdit::setModelData( QWidget* editor, const QModelIndex& index )
+{
+  QtxPathEdit* edit = ::qobject_cast<QtxPathEdit*>( editor );
+  if ( !edit )
+    return;
+
+  QString path = edit->path().trimmed();
+
+  if ( !isDuplicateEnabled() && !checkDuplicate( path, index.row() ) )
+    return;
+
+  if ( !checkExistance( path ) )
+    return;
+
+  myModel->setData( index, path, Qt::EditRole );
+}
+
+/*!
+  \brief Set data to the editor from the list widget when 
+  user starts path edition.
+  \param editor editor widget
+  \param index data model index
+*/
+void QtxPathListEdit::setEditorData( QWidget* editor, const QModelIndex& index )
+{
+  QtxPathEdit* edit = ::qobject_cast<QtxPathEdit*>( editor );
+  if ( !edit )
+    return;
+
+  QVariant v = myModel->data( index, Qt::EditRole );
+  edit->setPath( v.toString() );
+}
+
+/*!
+  \brief Check if path is correct (exists) and optionally 
+  show the question message box.
+  \param str path to be checked
+  \param msg if \c true and path does not exist, question message box is shown
+  \return \c true if the user confirms the path adding
+*/
+bool QtxPathListEdit::checkExistance( const QString& str, const bool msg )
+{
+  if ( pathType() == Qtx::PT_SaveFile )
+    return true;
+
+  bool ok = QFileInfo( str ).exists();
+  if ( !ok && msg )
+    ok = QMessageBox::question( this, tr( "Warning" ), tr( "Path \"%1\" doesn't exist. Add it to list anyway?" ).arg( str ),
+                                QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
+
+  if ( ok && QFileInfo( str ).exists() )
+  {
+    switch ( pathType() )
+    {
+    case Qtx::PT_OpenFile:
+      ok = QFileInfo( str ).isFile();
+      if ( !ok && msg )
+        QMessageBox::warning( this, tr( "Error" ), tr( "Location \"%1\" doesn't point to file" ).arg( str ) );
+      break;
+    case Qtx::PT_Directory:
+      ok = QFileInfo( str ).isDir();
+      if ( !ok && msg )
+        QMessageBox::warning( this, tr( "Error" ), tr( "Location \"%1\" doesn't point to directory" ).arg( str ) );
+      break;
+    }
+  }
+
+  return ok;
+}
+
+/*!
+  \brief Check if path already exists in the list and optionally
+  show the warning message box.
+  \param str path to be checked
+  \param row row corresponding to the path checked
+  \param msg if \c true and path does not exist, warning message box is shown
+  \return \c true if the user confirms the path adding
+*/
+bool QtxPathListEdit::checkDuplicate( const QString& str, const int row, const bool msg )
+{
+  int cur = -1;
+  QStringList lst = myModel->stringList();
+  for ( int r = 0; r < lst.count() && cur == -1; r++ )
+  {
+    if ( r != row && lst.at( r ) == str )
+      cur = r;
+  }
+
+  if ( cur != -1 && msg )
+    QMessageBox::warning( this, tr( "Error" ), tr( "Path \"%1\" already exist in the list" ).arg( str ) );
+   
+  return cur == -1;
+}
diff --git a/src/Qtx/QtxPathListEdit.h b/src/Qtx/QtxPathListEdit.h
new file mode 100644 (file)
index 0000000..de24b82
--- /dev/null
@@ -0,0 +1,97 @@
+// 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
+//
+// File:      QtxPathListEdit.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXPATHLISTEDIT_H
+#define QTXPATHLISTEDIT_H
+
+#include "Qtx.h"
+
+#include <QFrame>
+#include <QPointer>
+
+class QLineEdit;
+class QListView;
+class QCompleter;
+class QModelIndex;
+class QToolButton;
+class QStringListModel;
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxPathListEdit : public QFrame
+{
+  Q_OBJECT
+
+  class Editor;
+  class Delegate;
+
+public:
+  QtxPathListEdit( const Qtx::PathType, QWidget* = 0 );
+  QtxPathListEdit( QWidget* = 0 );
+  virtual ~QtxPathListEdit();
+
+  Qtx::PathType     pathType() const;
+  void              setPathType( const Qtx::PathType );
+
+  QStringList       pathList() const;
+  void              setPathList( const QStringList& );
+
+  bool              isDuplicateEnabled() const;
+  void              setDuplicateEnabled( const bool );
+
+  int               count() const;
+  bool              contains( const QString& ) const;
+
+  void              clear();
+  void              remove( const int );
+  void              remove( const QString& );
+  void              insert( const QString&, const int = -1 );
+
+  bool              eventFilter( QObject*, QEvent* );
+
+protected slots:
+  void              onUp( bool = false );
+  void              onDown( bool = false );
+  void              onInsert( bool = false );
+  void              onDelete( bool = false );
+
+private:
+  void              initialize();
+  QWidget*          createEditor( QWidget* );
+  void              setModelData( QWidget*, const QModelIndex& );
+  void              setEditorData( QWidget*, const QModelIndex& );
+
+  bool              checkExistance( const QString&, const bool = true );
+  bool              checkDuplicate( const QString&, const int, const bool = true );
+
+private:
+  QListView*        myList;
+  Qtx::PathType     myType;
+  QStringListModel* myModel;
+  QCompleter*       myCompleter;
+  bool              myDuplicate;
+
+  friend class QtxPathListEdit::Delegate;
+};
+
+#endif
diff --git a/src/Qtx/QtxPopupMgr.cxx b/src/Qtx/QtxPopupMgr.cxx
new file mode 100644 (file)
index 0000000..3efd99a
--- /dev/null
@@ -0,0 +1,742 @@
+// 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
+//
+// File:      QtxPopupMgr.cxx
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
+
+#include "QtxPopupMgr.h"
+#include "QtxAction.h"
+#include "QtxEvalExpr.h"
+#include <QMenu>
+
+/*!
+  \brief Used for comparing of two QVariant values.
+  \param v1 first argument for comparison
+  \param v2 second argument for comparison
+  \return \c true if \a v1 less than \a v2
+*/
+bool operator<( const QVariant& v1, const QVariant& v2 )
+{
+  QVariant::Type t1 = v1.type(), t2 = v2.type();
+  if ( t1 == t2 )
+  {
+    switch( t1 )
+    {
+    case QVariant::Int:
+      return v1.toInt() < v2.toInt();
+      break;      
+    case QVariant::Double:
+      return v1.toDouble() < v2.toDouble();
+      break;      
+    case QVariant::String:
+      return v1.toString() < v2.toString();
+      break;      
+    case QVariant::StringList:
+    case QVariant::List:
+    {
+      const QList<QVariant>& aList1 = v1.toList(), aList2 = v2.toList();
+      QList<QVariant>::const_iterator anIt1 = aList1.begin(), aLast1 = aList1.end(),
+       anIt2 = aList2.begin(), aLast2 = aList2.end();
+      for ( ; anIt1 != aLast1 && anIt2 != aLast2;  anIt1++, anIt2++ )
+      {
+       if ( (*anIt1) != (*anIt2) )
+         return (*anIt1)<(*anIt2);
+      }
+      return anIt1 == aLast1 && anIt2 != aLast2;
+      break;      
+    }
+    default:
+      return v1.toString() < v2.toString();
+      break;      
+    }
+  }
+  else
+    return t1 < t2;
+}
+
+/*!
+  \class QtxPopupMgr::PopupCreator
+  \internal
+  \brief Popup menu actions creator.
+
+  Used by Reader to create actions by reading descriptions from the file
+  and fill in the action manager with the actions.
+*/
+
+class QtxPopupMgr::PopupCreator : public QtxActionMgr::Creator
+{
+public:
+  PopupCreator( QtxActionMgr::Reader*, QtxPopupMgr* );
+  virtual ~PopupCreator();
+
+  virtual int     append( const QString&, const bool,
+                          const ItemAttributes&, const int );
+
+  virtual QString rule( const ItemAttributes&, 
+                       const QtxPopupMgr::RuleType = VisibleRule ) const;
+
+private:
+  QtxPopupMgr*    myMgr;
+};
+
+/*!
+  \brief Constructor.
+  \param r menu action reader
+  \param mgr popup menu manager
+*/
+QtxPopupMgr::PopupCreator::PopupCreator( QtxActionMgr::Reader* r,
+                                         QtxPopupMgr* mgr )
+: QtxActionMgr::Creator( r ),
+  myMgr( mgr )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPopupMgr::PopupCreator::~PopupCreator()
+{
+}
+
+/*!
+  \brief Create and append new action to the action manager.
+  \param tag item tag name
+  \param subMenu \c true if this item is submenu
+  \param attr attributes map
+  \param pId parent action ID
+  \return menu action ID
+*/
+int QtxPopupMgr::PopupCreator::append( const QString& tag, const bool subMenu,
+                                       const ItemAttributes& attr, const int pId )
+{
+  if ( !myMgr || !reader() )
+    return -1;
+
+  QString label   = reader()->option( "label",     "label"     ),
+          id      = reader()->option( "id",        "id"        ),
+          pos     = reader()->option( "pos",       "pos"       ),
+          group   = reader()->option( "group",     "group"     ),
+          tooltip = reader()->option( "tooltip",   "tooltip"   ),
+          sep     = reader()->option( "separator", "separator" ),
+          accel   = reader()->option( "accel",     "accel"     ),
+          icon    = reader()->option( "icon",      "icon"      ),
+          toggle  = reader()->option( "toggle",    "toggle"    );
+
+  QtxActionMenuMgr* mgr = myMgr;
+
+  int res = -1, actId = intValue( attr, id, -1 );;
+  if ( subMenu )
+    res = mgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+  else if ( tag == sep )
+    res = mgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+  else
+  {
+    QIcon set;
+    QPixmap pix;
+    QString name = strValue( attr, icon );
+    if( !name.isEmpty() )
+    {
+      if ( loadPixmap( name, pix ) )
+        set = QIcon( pix );
+    }
+
+    QString actLabel = strValue( attr, label );
+    QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, actLabel,
+                                       QKeySequence( strValue( attr, accel ) ),
+                                       myMgr );
+    newAct->setToolTip( strValue( attr, tooltip ) );
+    QString toggleact = strValue( attr, toggle );
+    bool isToggle = !toggleact.isEmpty();
+    newAct->setCheckable( isToggle );
+    newAct->setChecked( toggleact.toLower() == "true" );
+        
+    connect( newAct );
+    int aid = mgr->registerAction( newAct, actId ); 
+    QString arule = rule( attr, QtxPopupMgr::VisibleRule );
+    if ( !arule.isEmpty() )
+      myMgr->setRule( newAct, arule, QtxPopupMgr::VisibleRule );
+    arule = rule( attr, QtxPopupMgr::EnableRule );
+    if ( !arule.isEmpty() )
+      myMgr->setRule( newAct, arule, QtxPopupMgr::EnableRule );
+    arule = rule( attr, QtxPopupMgr::ToggleRule );
+    if ( isToggle && !arule.isEmpty() )
+      myMgr->setRule( newAct, arule, QtxPopupMgr::ToggleRule );
+    res = mgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+  }
+
+  return res;
+}
+
+/*!
+  \brief Get the rule for the menu item.
+
+  Default implementation returns empty rule.
+
+  \param attr attributes map
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return rule for the menu item corresponding to the rule type
+*/
+QString QtxPopupMgr::PopupCreator::rule( const ItemAttributes& /*attr*/, 
+                                        const QtxPopupMgr::RuleType /*ruleType*/ ) const
+{
+  return QString();
+}
+
+/*!
+  \class QtxPopupMgr
+  \brief Popup menu manager.
+
+  Menu manager allows using of set of action for automatic generating of
+  application context popup menu by reuquest and dynamic update of its
+  contents.
+
+  Use insert() methods to add menu items to the popup menu.
+
+  The visibility, enable and toggle state of the menu item is controlled
+  by the syntaxic rules, which can be set with setRule() methods.
+  The rules are parsed automatically with help of QtxEvalParser class.
+
+  QtxPopupSelection class is used as back-end for getting value of each
+  parameter found in the rule by the expression parser.
+  Use setSelection() and selection() to set/get the selection instance
+  for the popup menu manager.
+  
+  Popup menu manager automatically optimizes the menu by removing 
+  extra separators, hiding empty popup submenus etc.
+*/
+
+/*!
+  \brief Constructor.
+  \param object parent object
+*/
+QtxPopupMgr::QtxPopupMgr( QObject* parent )
+: QtxActionMenuMgr( 0, parent ),
+  mySelection( 0 )
+{
+}
+
+/*!
+  \brief Constructor.
+  \param popup popup menu
+  \param object parent object
+*/
+QtxPopupMgr::QtxPopupMgr( QMenu* popup, QObject* parent )
+: QtxActionMenuMgr( popup, parent ),
+  mySelection( 0 )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPopupMgr::~QtxPopupMgr()
+{
+}
+
+/*!
+  \brief Get popup menu.
+  \return popup menu
+*/
+QMenu* QtxPopupMgr::menu() const
+{
+  return ::qobject_cast<QMenu*>( menuWidget() );
+}
+
+/*!
+  \brief Get popup menu.
+  \param menu popup menu
+*/
+void QtxPopupMgr::setMenu( QMenu* menu )
+{
+  setMenuWidget( menu );
+}
+
+/*!
+  \brief Get selection.
+  \return current selection object
+*/
+QtxPopupSelection* QtxPopupMgr::selection() const
+{
+  return mySelection;
+}
+
+/*!
+  \brief Set selection.
+  \param sel new selection object
+*/
+void QtxPopupMgr::setSelection( QtxPopupSelection* sel )
+{
+  if ( mySelection == sel )
+    return;
+
+  delete mySelection;
+
+  mySelection = sel;
+
+  if ( mySelection )
+    mySelection->setParent( this );
+
+  QtxActionMgr::triggerUpdate();
+}
+
+/*!
+  \brief Register an action and return its identifier.
+
+  If \a id is less than 0, the identifier for the action is generated automatically.
+  If action with given \a id is already registered, it will be re-registered.
+  If required \a id is already in use, new identifier is generatied; in this case
+  returning value will different from required one.
+
+  \param act action to be registered
+  \param id action ID
+  \param rule syntax rule
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return action ID (the same as \a id or generated one)
+*/
+int QtxPopupMgr::registerAction( QAction* act, const int id, const QString& rule, const QtxPopupMgr::RuleType ruleType )
+{
+  int _id = QtxActionMenuMgr::registerAction( act, id );
+  setRule( act, rule, ruleType );
+  return _id;
+}
+
+/*!
+  \brief Unregister action from internal map.
+  \param id action ID
+*/
+void QtxPopupMgr::unRegisterAction( const int id )
+{
+  QAction* a = action( id );
+  if ( myRules.contains( a ) )
+  {
+    for ( ExprMap::iterator it = myRules[a].begin(); it != myRules[a].end(); ++it )
+      delete it.value();
+  }
+  myRules.remove( a );
+
+  remove( id );
+
+  QtxActionMenuMgr::unRegisterAction( id );
+}
+
+/*!
+  \brief Insert action to the popup menu manager.
+  \param id action ID
+  \param pId parent menu action ID
+  \param rule syntax rule
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return action ID
+*/
+int QtxPopupMgr::insertAction( const int id, const int pId, const QString& rule, const RuleType ruleType )
+{
+  int res = QtxActionMenuMgr::insert( id, pId, -1 );
+  setRule( action( id ), rule, ruleType );
+  return res;
+}
+
+/*!
+  \brief Insert action to the popup menu manager.
+  \param a action
+  \param pId parent menu action ID
+  \param rule syntax rule
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return action ID
+*/
+int QtxPopupMgr::insertAction( QAction* a, const int pId, const QString& rule, const RuleType ruleType )
+{
+  int res = QtxActionMenuMgr::insert( a, pId, -1 );
+  setRule( a, rule, ruleType );
+  return res;
+}
+
+/*!
+  \brief Get rule of type \a type for the action \a a.
+  \param a action
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return rule of required type
+*/
+QString QtxPopupMgr::rule( QAction* a, const RuleType ruleType ) const
+{
+  QString rule;
+  QtxEvalExpr* expr = expression( a, ruleType );
+  if ( expr )
+    rule = expr->expression();
+  return rule;
+}
+
+/*!
+  \brief Get rule of type \a type for the action \a id.
+  \param id action ID
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return rule of required type
+*/
+QString QtxPopupMgr::rule( const int id, const RuleType ruleType ) const
+{
+  return rule( action( id ), ruleType );
+}
+
+/*!
+  \brief Set rule of type \a type for the action \a a.
+  \param a action
+  \param rule rule
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return rule of required type
+*/
+void QtxPopupMgr::setRule( QAction* a, const QString& rule, const RuleType ruleType )
+{
+  if ( !a )
+    return;
+
+  QtxEvalExpr* expr = expression( a, ruleType, true );
+
+  expr->setExpression( rule );
+}
+
+/*!
+  \brief Set rule of type \a type for the action \a id.
+  \param id action ID
+  \param rule rule
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return rule of required type
+*/
+void QtxPopupMgr::setRule( const int id, const QString& rule, const RuleType ruleType )
+{
+  setRule( action( id ), rule, ruleType );
+}
+
+/*!
+  \brief Calculate an expression.
+  \param p expression parser
+  \return \c true if parser has finished work without errors
+*/
+bool QtxPopupMgr::result( QtxEvalParser* p ) const
+{
+  bool res = false;
+  if ( p )
+  {
+    QVariant vv = p->calculate();
+    res = p->error() == QtxEvalExpr::OK &&
+          ( ( vv.type() == QVariant::Int && vv.toInt() != 0 ) ||
+            ( vv.type() == QVariant::Bool && vv.toBool() ) );
+  }
+  return res;
+}
+
+/*!
+  \brief Fill the parser with parameters of the expression.
+
+  The values of the parameters are given from the selection object
+  (QtxPopupSelection).
+  
+  \param p expression parser
+  \param returning list of parameters names which are not retrieved from the selection
+  \sa selection()
+*/
+void QtxPopupMgr::setParameters( QtxEvalParser* p, QStringList& specific ) const
+{
+  if ( !p || !mySelection )
+    return;
+
+  QStringList params = p->parameters();
+  for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it )
+  {
+    QVariant v = parameter( *it );
+    if ( v.isValid() )
+      p->setParameter( *it, v );
+    else
+      specific.append( *it );
+  }
+}
+
+/*!
+  \brief Check the rule for the action.
+  \param act action
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \return \c true if current selection satisfies the action rule
+*/
+bool QtxPopupMgr::isSatisfied( QAction* act, const RuleType ruleType ) const
+{
+  if ( !act )
+    return false;
+
+  QtxEvalExpr* exp = expression( act, ruleType );
+  if ( !exp )
+    return true;
+
+  bool res = false;
+
+  QtxEvalParser* p = exp->parser();
+
+  QStringList specific;
+  p->clearParameters();
+  setParameters( p, specific );
+
+  QMap<QList<QVariant>, int> aCorteges;
+  if ( !specific.isEmpty() )
+  {
+    if ( mySelection )
+    {
+      res = false;
+      for ( int i = 0; i < mySelection->count() && !res; i++ )
+      {
+        QList<QVariant> c;
+       for ( QStringList::const_iterator anIt1 = specific.begin(); anIt1 != specific.end(); ++anIt1 )
+          c.append( parameter( *anIt1, i ) );
+        aCorteges.insert( c, 0 );
+      }
+      for ( QMap<QList<QVariant>, int>::const_iterator anIt = aCorteges.begin(); anIt  != aCorteges.end(); ++anIt )
+      {
+       const QList<QVariant>& aCortege = anIt.key();
+       QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
+       QList<QVariant>::const_iterator anIt2 = aCortege.begin();
+       for ( ; anIt1 != aLast1; anIt1++, anIt2++ )
+         p->setParameter( *anIt1, *anIt2 );
+       res = res || result( p );
+      }
+    }
+    else
+      res = false;
+  }
+  else
+    res = result( p );
+
+  return res;
+}
+
+/*!
+  \brief Check if the menu item is visible.
+  \param id action ID
+  \param place some parent action ID
+  \return \c true if the action is visible
+*/
+bool QtxPopupMgr::isVisible( const int id, const int place ) const
+{
+  return QtxActionMenuMgr::isVisible( id, place ) && isSatisfied( action( id ) );
+}
+
+/*!
+  \brief Perform internal update of the popup menu according 
+  to the current selection.
+*/
+void QtxPopupMgr::internalUpdate()
+{
+  myCache.clear();
+
+  for ( RuleMap::iterator it = myRules.begin(); it != myRules.end(); ++it )
+  {
+    ExprMap& map = it.value();
+    if ( it.key()->isCheckable() && map.contains( ToggleRule ) &&
+         !map[ToggleRule]->expression().isEmpty() )
+      it.key()->setChecked( isSatisfied( it.key(), ToggleRule ) );
+  }
+
+  QtxActionMenuMgr::internalUpdate();
+
+  myCache.clear();
+}
+
+/*!
+  \brief Update popup according to the current selection.
+*/
+void QtxPopupMgr::updateMenu()
+{
+  internalUpdate();
+}
+
+/*!
+  \brief Get an syntax expression for the action according to the specified rule type.
+  \param a action
+  \param ruleType rule type (QtxPopupMgr::RuleType)
+  \param create if \c true an expression does not exist, create it
+  \return syntax expression
+*/
+QtxEvalExpr* QtxPopupMgr::expression( QAction* a, const RuleType ruleType, const bool create ) const
+{
+  QtxEvalExpr* res = 0;
+
+  QtxPopupMgr* that = (QtxPopupMgr*)this;
+  RuleMap& ruleMap = that->myRules;
+  if ( !ruleMap.contains( a ) && create )
+    ruleMap.insert( a, ExprMap() );
+
+  if ( ruleMap.contains( a ) )
+  {
+    ExprMap& exprMap = ruleMap[a];
+    if ( exprMap.contains( ruleType ) )
+      res = exprMap[ruleType];
+    else if ( create )
+      exprMap.insert( ruleType, res = new QtxEvalExpr() );
+  }
+
+  return res;
+}
+
+/*!
+  \brief Load actions description from the file.
+  \param fname file name
+  \param r action reader
+  \return \c true on success and \c false on error
+*/
+bool QtxPopupMgr::load( const QString& fname, QtxActionMgr::Reader& r )
+{
+  PopupCreator cr( &r, this );
+  return r.read( fname, cr );
+}
+
+/*
+  \brief Get the specified parameter value.
+  \param name parameter name
+  \param idx additional index used when used parameters with same names 
+  \return parameter value
+  \sa selection()
+*/
+QVariant QtxPopupMgr::parameter( const QString& name, const int idx ) const
+{
+  QVariant val;
+  QString cacheName = name + ( idx >= 0 ? QString( "_%1" ).arg( idx ) : QString() );
+  if ( myCache.contains( cacheName ) )
+    val = myCache[cacheName];
+  else
+  {
+    if ( selection() )
+      val = idx < 0 ? selection()->parameter( name ) : 
+                      selection()->parameter( idx, name );
+    if ( val.isValid() )
+    {
+      QtxPopupMgr* that = (QtxPopupMgr*)this;
+      that->myCache.insert( cacheName, val );
+    }
+  }
+  return val;
+}
+
+/*!
+  \class QtxPopupSelection
+  \brief This class is a part of the popup menu management system. 
+
+  The QtxPopupSelection class is used as back-end for getting value
+  of each parameter found in the rule by the expression parser.
+  
+  For example, it can be used for the analyzing of the currently 
+  selected objects and defining the values of the parameters used
+  in the rules syntax expression. Rules, in their turn, define
+  each action state - visibility, enabled and toggled state.
+*/
+
+/*!
+  \brief Constructor.
+*/
+QtxPopupSelection::QtxPopupSelection()
+: QObject( 0 )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPopupSelection::~QtxPopupSelection()
+{
+}
+
+/*!
+  \brief Get an option value.
+  \param optName option name
+  \return option value or empty string if option is not found
+*/
+QString QtxPopupSelection::option( const QString& optName ) const
+{
+  QString opt;
+  if ( myOptions.contains( optName ) )
+    opt = myOptions[optName];
+  return opt;
+}
+
+/*!
+  \brief Set an option value.
+  \param optName option name
+  \param opt option value
+*/
+void QtxPopupSelection::setOption( const QString& optName, const QString& opt )
+{
+  myOptions.insert( optName, opt );
+}
+
+/*!
+  \brief Get the parameter value.
+  \param str parameter name
+  \return parameter value
+*/
+QVariant QtxPopupSelection::parameter( const QString& str ) const
+{
+  if ( str == selCountParam() )
+    return count();
+  else if ( str.startsWith( equalityParam() ) )
+  {
+    QtxEvalSetSets::ValueSet set;
+    QString par = str.mid( equalityParam().length() );
+    for ( int i = 0; i < (int)count(); i++ )
+    {
+      QVariant v = parameter( i, par );
+      if ( v.isValid() )
+       QtxEvalSetSets::add( set, v );
+      else
+       return QVariant();
+    }
+    return set;
+  }
+  else
+    return QVariant();
+}
+
+/*!
+  \brief Get symbol which detects the name of the parameter list.
+  \return equality symbol (by default, "$")
+*/
+QString QtxPopupSelection::equalityParam() const
+{
+  QString str = option( "equality" );
+  if ( str.isEmpty() )
+    str = "$";
+  return str;
+}
+
+/*!
+  \brief Get name of the parameter, specifing number of selected objects
+  \return parameter name (by default, "selcount")
+*/
+QString QtxPopupSelection::selCountParam() const
+{
+  QString str = option( "equality" );
+  if ( str.isEmpty() )
+    str = "selcount";
+  return str;
+}
+
+/*!
+  \fn int QtxPopupSelection::count() const;
+  \brief Get number of the selected objects.
+  \return nb of selected objects
+*/
+
+/*!
+  \fn QVariant QtxPopupSelection::parameter( const int idx, const QString& name ) const;
+  \brief Get number of the selected objects.
+  \param idx parameter index
+  \param name parameter name
+  \return parameter value
+*/
diff --git a/src/Qtx/QtxPopupMgr.h b/src/Qtx/QtxPopupMgr.h
new file mode 100644 (file)
index 0000000..2dbea12
--- /dev/null
@@ -0,0 +1,126 @@
+// 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
+//
+// File:      QtxPopupMgr.h
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
+
+#ifndef QTXPOPUPMGR_H
+#define QTXPOPUPMGR_H
+
+#include "QtxActionMenuMgr.h"
+
+#include <QMap>
+#include <QVariant>
+
+class QtxEvalExpr;
+class QtxEvalParser;
+class QtxPopupSelection;
+
+class QTX_EXPORT QtxPopupMgr : public QtxActionMenuMgr
+{
+  Q_OBJECT
+
+public:
+  //! Menu item rule type
+  typedef enum { 
+    VisibleRule,   //!< menu item visibility state
+    EnableRule,    //!< menu item enable state
+    ToggleRule     //!< menu item toggle state
+  } RuleType;
+
+private:
+  class PopupCreator;
+
+public:
+  QtxPopupMgr( QObject* = 0 );
+  QtxPopupMgr( QMenu*, QObject* = 0 );
+  virtual ~QtxPopupMgr();
+
+  int                insertAction( const int, const int, const QString&, const RuleType = VisibleRule );
+  int                insertAction( QAction*, const int, const QString&, const RuleType = VisibleRule );
+
+  virtual int        registerAction( QAction*, const int, const QString& rule,
+                                     const RuleType = VisibleRule );
+  virtual void       unRegisterAction( const int );
+
+  virtual bool       isVisible( const int actId, const int place ) const;
+
+  QString            rule( QAction*, const RuleType = VisibleRule ) const;
+  QString            rule( const int, const RuleType = VisibleRule ) const;
+
+  void               setRule( QAction*, const QString&, const RuleType = VisibleRule );
+  void               setRule( const int, const QString&, const RuleType = VisibleRule );
+
+  QtxPopupSelection* selection() const;
+  void               setSelection( QtxPopupSelection* );
+
+  QMenu*             menu() const;
+  void               setMenu( QMenu* );
+
+  void               updateMenu();
+
+  virtual bool       load( const QString&, QtxActionMgr::Reader& );
+
+protected:
+  virtual void       internalUpdate();
+  void               setParameters( QtxEvalParser*, QStringList& ) const;
+  virtual bool       isSatisfied( QAction*, const RuleType = VisibleRule ) const;
+  QtxEvalExpr*       expression( QAction*, const RuleType = VisibleRule, const bool = false ) const;
+
+private:
+  bool               result( QtxEvalParser* p ) const;
+  QVariant           parameter( const QString&, const int = -1 ) const;
+
+private:
+  typedef QMap<RuleType, QtxEvalExpr*> ExprMap;
+  typedef QMap<QAction*, ExprMap>      RuleMap;
+  typedef QMap<QString, QVariant>      CacheMap;
+
+private:
+  RuleMap            myRules;
+  CacheMap           myCache;
+  QtxPopupSelection* mySelection;
+};
+
+class QTX_EXPORT QtxPopupSelection : public QObject
+{
+  Q_OBJECT
+
+public:
+  QtxPopupSelection();
+  virtual ~QtxPopupSelection();
+
+  virtual int        count() const = 0;
+  virtual QVariant   parameter( const QString& ) const;
+  virtual QVariant   parameter( const int, const QString& ) const = 0;
+
+  QString            option( const QString& ) const;
+  void               setOption( const QString&, const QString& );
+
+private:
+  QString            equalityParam() const;
+  QString            selCountParam() const;
+
+private:
+  typedef QMap<QString, QString> OptionsMap;
+
+private:
+  OptionsMap         myOptions;
+};
+
+#endif // QTXPOPUPMGR_H
diff --git a/src/Qtx/QtxPreferenceMgr.cxx b/src/Qtx/QtxPreferenceMgr.cxx
new file mode 100644 (file)
index 0000000..ee43976
--- /dev/null
@@ -0,0 +1,1110 @@
+// 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
+//
+// File:      QtxPreferenceMgr.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxPreferenceMgr.h"
+
+#include "QtxResourceMgr.h"
+
+#include <QEvent>
+#include <QApplication>
+
+/*!
+  \class QtxPreferenceItem::Updater
+  \brief Preference item updater.
+  \internal
+*/
+
+class QtxPreferenceItem::Updater : public QObject
+{
+  Updater();
+public:
+  ~Updater();
+
+  static Updater*           instance();
+
+  void                      updateItem( QtxPreferenceItem* );
+  void                      removeItem( QtxPreferenceItem* );
+
+protected:
+  virtual void              customEvent( QEvent* );
+
+private:
+  QList<QtxPreferenceItem*> myItems;
+  static Updater*           _Updater;
+};
+
+QtxPreferenceItem::Updater* QtxPreferenceItem::Updater::_Updater = 0;
+
+/*!
+  \brief Constructor.
+  \internal
+*/
+QtxPreferenceItem::Updater::Updater()
+{
+}
+
+/*!
+  \brief Destructor.
+  \internal
+*/
+QtxPreferenceItem::Updater::~Updater()
+{
+}
+
+/*!
+  \brief Get the only updater instance.
+  \internal
+  \return the only updater instance
+*/
+QtxPreferenceItem::Updater* QtxPreferenceItem::Updater::instance()
+{
+  if ( !_Updater )
+    _Updater = new Updater();
+  return _Updater;
+}
+
+/*!
+  \brief Update the preference item.
+  \internal
+  \param item preference item to be updated
+*/
+void QtxPreferenceItem::Updater::updateItem( QtxPreferenceItem* item )
+{
+  if ( !item || myItems.contains( item ) )
+    return;
+
+  myItems.append( item );
+  QApplication::postEvent( this, new QEvent( QEvent::User ) );
+}
+
+/*!
+  \brief Called when preference item is removed.
+  \internal
+  \param item preference item being removed
+*/
+void QtxPreferenceItem::Updater::removeItem( QtxPreferenceItem* item )
+{
+  myItems.removeAll( item );
+}
+
+/*!
+  \brief Custom events provessing. Updates all the items.
+  \internal
+  \param e custom event (not used)
+*/
+void QtxPreferenceItem::Updater::customEvent( QEvent* /*e*/ )
+{
+  QList<QtxPreferenceItem*> lst = myItems;
+  for ( QList<QtxPreferenceItem*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
+    (*it)->updateContents();
+}
+
+/*!
+  \class QtxPreferenceItem
+  \brief Base class for implementing of all the preference items.
+
+  To implement any specific preference item, cubclass from the 
+  QtxPreferenceItem and redefine store() and retrieve() methods.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent preference item
+*/
+QtxPreferenceItem::QtxPreferenceItem( QtxPreferenceItem* parent )
+: myParent( 0 )
+{
+  myId = generateId();
+
+  if ( parent )
+    parent->insertItem( this );
+}
+
+/*!
+  \brief Constructor.
+  \param title item title
+  \param parent parent preference item
+*/
+QtxPreferenceItem::QtxPreferenceItem( const QString& title, QtxPreferenceItem* parent )
+: myParent( 0 ),
+  myTitle( title )
+{
+  myId = generateId();
+
+  if ( parent )
+    parent->insertItem( this );
+}
+
+/*!
+  \brief Constructor.
+  \param title item title
+  \param sect resource file section to be associated with the item
+  \param param resource file parameter to be associated with the item
+  \param parent parent preference item
+*/
+QtxPreferenceItem::QtxPreferenceItem( const QString& title, const QString& sect,
+                                      const QString& param, QtxPreferenceItem* parent )
+: myParent( 0 ),
+  myTitle( title ),
+  mySection( sect ),
+  myParameter( param )
+{
+  myId = generateId();
+
+  if ( parent )
+    parent->insertItem( this );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPreferenceItem::~QtxPreferenceItem()
+{
+  ItemList list = myChildren;
+  myChildren.clear();
+  qDeleteAll( list );
+
+  if ( myParent )
+    myParent->removeItem( this );
+
+  Updater::instance()->removeItem( this );
+}
+
+/*!
+  \brief Get unique item identifier.
+  \return item ID
+*/
+int QtxPreferenceItem::id() const
+{
+  return myId;
+}
+
+/*!
+  \brief Get unique item type identifier.
+  \return item type ID
+*/
+int QtxPreferenceItem::rtti() const
+{
+  return QtxPreferenceItem::RTTI();
+}
+
+/*!
+  \brief Specify unique item class identifier.
+  \return item class ID
+*/
+int QtxPreferenceItem::RTTI()
+{
+  return 1;
+}
+
+/*!
+  \brief Get root preference item.
+  \return root item
+*/
+QtxPreferenceItem* QtxPreferenceItem::rootItem() const
+{
+  QtxPreferenceItem* item = (QtxPreferenceItem*)this;
+  while ( item->parentItem() )
+    item = item->parentItem();
+  return item;
+}
+
+/*!
+  \brief Get parent preference item.
+  \return parent item
+*/
+QtxPreferenceItem* QtxPreferenceItem::parentItem() const
+{
+  return myParent;
+}
+
+/*!
+  \brief Append child preference item.
+
+  Removes (if necessary) the item from the previous parent.
+
+  \param item item to be added
+  \sa removeItem()
+*/
+void QtxPreferenceItem::insertItem( QtxPreferenceItem* item )
+{
+  if ( !item || myChildren.contains( item ) )
+    return;
+
+  if ( item->parentItem() && item->parentItem() != this )
+    item->parentItem()->removeItem( item );
+
+  item->myParent = this;
+  myChildren.append( item );
+
+  itemAdded( item );
+}
+
+/*!
+  \brief Remove child preference item.
+  \param item item to be removed
+  \sa insertItem()
+*/
+void QtxPreferenceItem::removeItem( QtxPreferenceItem* item )
+{
+  if ( !item || !myChildren.contains( item ) )
+    return;
+
+  item->myParent = 0;
+  myChildren.removeAll( item );
+
+  itemRemoved( item );
+}
+
+/*!
+  \brief Get all child preference items.
+  \param rec recursion boolean flag
+  \return list of child items
+*/
+QList<QtxPreferenceItem*> QtxPreferenceItem::childItems( const bool rec ) const
+{
+  QList<QtxPreferenceItem*> lst = myChildren;
+  if ( rec )
+  {
+    for ( ItemList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
+      lst += (*it)->childItems( rec );
+  }
+
+  return lst;
+}
+
+/*!
+  \brief Get preference item depth.
+  \return item depth
+*/
+int QtxPreferenceItem::depth() const
+{
+  return parentItem() ? parentItem()->depth() + 1 : 0;
+}
+
+/*!
+  \brief Get child preference items number.
+  \return number of child items
+  \sa isEmpty()
+*/
+int QtxPreferenceItem::count() const
+{
+  return myChildren.count();
+}
+
+/*!
+  \brief Check if the item has children.
+  \return \c true if item does not have children
+  \sa count()
+*/
+bool QtxPreferenceItem::isEmpty() const
+{
+  return myChildren.isEmpty();
+}
+
+/*!
+  \brief Get preference item icon.
+  \return item icon
+  \sa setIcon()
+*/
+QIcon QtxPreferenceItem::icon() const
+{
+  return myIcon;
+}
+
+/*!
+  \brief Get preference item title.
+  \return item title
+  \sa setTitle()
+*/
+QString QtxPreferenceItem::title() const
+{
+  return myTitle;
+}
+
+/*!
+  \brief Get resource file settings associated to the preference item.
+  \param sec used to return resource file section name
+  \param param used to return resource file parameter name
+  \sa setResource()
+*/
+void QtxPreferenceItem::resource( QString& sec, QString& param ) const
+{
+  sec = mySection;
+  param = myParameter;
+}
+
+/*!
+  \brief Set prefence item icon.
+  \param ico new item icon
+  \sa icon()
+*/
+void QtxPreferenceItem::setIcon( const QIcon& ico )
+{
+  if ( myIcon.serialNumber() == ico.serialNumber() )
+    return;
+
+  myIcon = ico;
+  sendItemChanges();
+}
+
+/*!
+  \brief Set preference item title .
+  \param title new item title
+  \sa title()
+*/
+void QtxPreferenceItem::setTitle( const QString& title )
+{
+  if ( myTitle == title )
+    return;
+
+  myTitle = title;
+  sendItemChanges();
+}
+
+/*!
+  \brief Assign resource file settings to the preference item.
+  \param sec resource file section name
+  \param param resource file parameter name
+  \sa resource()
+*/
+void QtxPreferenceItem::setResource( const QString& sec, const QString& param )
+{
+  mySection = sec;
+  myParameter = param;
+}
+
+/*!
+  \brief Update preference item.
+*/
+void QtxPreferenceItem::updateContents()
+{
+  Updater::instance()->removeItem( this );
+}
+
+/*!
+  \brief Get preference item option value.
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOption()
+*/
+QVariant QtxPreferenceItem::option( const QString& name ) const
+{
+  return optionValue( name.toLower() );
+}
+
+/*!
+  \brief Set preference item option value.
+  \param name option name
+  \param val new property value
+  \sa option()
+*/
+void QtxPreferenceItem::setOption( const QString& name, const QVariant& val )
+{
+  QVariant old = optionValue( name.toLower() );
+  setOptionValue( name.toLower(), val );
+  if ( old != optionValue( name.toLower() ) )
+    sendItemChanges();
+}
+
+/*!
+  \fn void QtxPreferenceItem::store();
+  \brief Save preference item (for example, to the resource file).
+
+  This method should be implemented in the subclasses.
+
+  \sa retrieve()
+*/
+
+/*!
+  \fn virtual void QtxPreferenceItem::retrieve();
+  \brief Restore preference item (for example, from the resource file).
+
+  This method should be implemented in the subclasses.
+
+  \sa store()
+*/
+
+/*!
+  \brief Get the value of the associated resource file setting.
+  \return associated resource file setting value
+  \sa setResourceValue()
+*/
+QString QtxPreferenceItem::resourceValue() const
+{
+  return getString();
+}
+
+/*!
+  \brief Get the value of the associated resource file setting.
+  \param val new associated resource file setting value
+  \sa resourceValue()
+*/
+void QtxPreferenceItem::setResourceValue( const QString& val )
+{
+  setString( val );
+}
+
+/*!
+  \brief Get the resources manager.
+  \return resource manager pointer or 0 if it is not defined
+*/
+QtxResourceMgr* QtxPreferenceItem::resourceMgr() const
+{
+  QtxPreferenceMgr* mgr = preferenceMgr();
+  return mgr ? mgr->resourceMgr() : 0;
+}
+
+/*!
+  \brief Get the parent preferences manager.
+  \return preferences manager or 0 if it is not defined
+*/
+QtxPreferenceMgr* QtxPreferenceItem::preferenceMgr() const
+{
+  return parentItem() ? parentItem()->preferenceMgr() : 0;
+}
+
+/*!
+  \brief Find the item by the specified identifier.
+  \param id child item ID
+  \param rec if \c true recursive search is done
+  \return child item or 0 if it is not found
+*/
+QtxPreferenceItem* QtxPreferenceItem::findItem( const int id, const bool rec ) const
+{
+  QtxPreferenceItem* item = 0;
+  for ( ItemList::const_iterator it = myChildren.begin(); it != myChildren.end() && !item; ++it )
+  {
+    QtxPreferenceItem* i = *it;
+    if ( i->id() == id )
+      item = i;
+    else if ( rec )
+      item = i->findItem( id, rec );
+  }
+  return item;
+}
+
+/*!
+  \brief Find the item by the specified title.
+  \param title child item title
+  \param rec if \c true recursive search is done
+  \return child item or 0 if it is not found
+*/
+QtxPreferenceItem* QtxPreferenceItem::findItem( const QString& title, const bool rec ) const
+{
+  QtxPreferenceItem* item = 0;
+  for ( ItemList::const_iterator it = myChildren.begin(); it != myChildren.end() && !item; ++it )
+  {
+    QtxPreferenceItem* i = *it;
+    if ( i->title() == title )
+      item = i;
+    else if ( rec )
+      item = i->findItem( title, rec );
+  }
+  return item;
+}
+
+/*!
+  \brief Find the item by the specified title and identifier.
+  \param title child item title
+  \param id child item ID
+  \param rec if \c true recursive search is done
+  \return child item or 0 if it is not found
+*/
+QtxPreferenceItem* QtxPreferenceItem::findItem( const QString& title, const int id, const bool rec ) const
+{
+  QtxPreferenceItem* item = 0;
+  for ( ItemList::const_iterator it = myChildren.begin(); it != myChildren.end() && !item; ++it )
+  {
+    QtxPreferenceItem* i = *it;
+    if ( i->title() == title && i->id() == id )
+      item = i;
+    else if ( rec )
+      item = i->findItem( title, id, rec );
+  }
+  return item;
+}
+
+
+/*!
+  \brief Get integer resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return integer value of the associated resource
+  \sa setInteger()
+*/
+int QtxPreferenceItem::getInteger( const int val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->integerValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Get double resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return double value of the associated resource
+  \sa setDouble()
+*/
+double QtxPreferenceItem::getDouble( const double val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->doubleValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Get boolean resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return boolean value of the associated resource
+  \sa setBoolean()
+*/
+bool QtxPreferenceItem::getBoolean( const bool val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->booleanValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Get string resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return string value of the associated resource
+  \sa setString()
+*/
+QString QtxPreferenceItem::getString( const QString& val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->stringValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Get color resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return color value of the associated resource
+  \sa setColor()
+*/
+QColor QtxPreferenceItem::getColor( const QColor& val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->colorValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Get font resources value corresponding to the item.
+  \param val default value (returned if there is no such resource)
+  \return font value of the associated resource
+  \sa setFont()
+*/
+QFont QtxPreferenceItem::getFont( const QFont& val ) const
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  return resMgr ? resMgr->fontValue( mySection, myParameter, val ) : val;
+}
+
+/*!
+  \brief Set integer resources value corresponding to the item.
+  \param val new value
+  \sa getInteger()
+*/
+void QtxPreferenceItem::setInteger( const int val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Set double resources value corresponding to the item.
+  \param val new value
+  \sa getDouble()
+*/
+void QtxPreferenceItem::setDouble( const double val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Set boolean resources value corresponding to the item.
+  \param val new value
+  \sa getBoolean()
+*/
+void QtxPreferenceItem::setBoolean( const bool val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Set string resources value corresponding to the item.
+  \param val new value
+  \sa getString()
+*/
+void QtxPreferenceItem::setString( const QString& val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Set color resources value corresponding to the item.
+  \param val new value
+  \sa getColor()
+*/
+void QtxPreferenceItem::setColor( const QColor& val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Set font resources value corresponding to the item.
+  \param val new value
+  \sa getFont()
+*/
+void QtxPreferenceItem::setFont( const QFont& val )
+{
+  QtxResourceMgr* resMgr = resourceMgr();
+  if ( resMgr )
+    resMgr->setValue( mySection, myParameter, val );
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is added.
+  
+  This function can be reimplemented in the subclasses to customize
+  child item addition operation. Base implementation does nothing.
+
+  \param item child item being added
+  \sa itemRemoved(), itemChanged()
+*/
+void QtxPreferenceItem::itemAdded( QtxPreferenceItem* /*item*/ )
+{
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is removed.
+  
+  This function can be reimplemented in the subclasses to customize
+  child item removal operation. Base implementation does nothing.
+
+  \param item child item being removed
+  \sa itemAdded(), itemChanged()
+*/
+void QtxPreferenceItem::itemRemoved( QtxPreferenceItem* /*item*/ )
+{
+}
+
+/*!
+  \brief Callback function which is called when the child
+  preference item is modified.
+  
+  This function can be reimplemented in the subclasses to customize
+  child item modifying operation. Base implementation does nothing.
+
+  \param item child item being modified
+  \sa itemAdded(), itemRemoved()
+*/
+void QtxPreferenceItem::itemChanged( QtxPreferenceItem* /*item*/ )
+{
+}
+
+/*!
+  \brief Initiate item updating.
+*/
+void QtxPreferenceItem::triggerUpdate()
+{
+  Updater::instance()->updateItem( this );
+}
+
+/*!
+  \brief Get preference item option value.
+
+  This function can be reimplemented in the subclasses.
+  Base implementation does nothing.
+  
+  \param name option name
+  \return property value or null QVariant if option is not set
+  \sa setOptionValue()
+*/
+QVariant QtxPreferenceItem::optionValue( const QString& /*name*/ ) const
+{
+  return QVariant();
+}
+
+/*!
+  \brief Set preference item option value.
+
+  This function can be reimplemented in the subclasses.
+  Base implementation does nothing.
+  
+  \param name option name
+  \param val new property value
+  \sa optionValue()
+*/
+void QtxPreferenceItem::setOptionValue( const QString& /*name*/, const QVariant& /*val*/ )
+{
+}
+
+/*!
+  \brief Initiate item changing call back operation.
+*/
+void QtxPreferenceItem::sendItemChanges()
+{
+  if ( parentItem() )
+    parentItem()->itemChanged( this );
+}
+
+/*!
+  \brief Generate unique preference item identifier.
+  \return unique item ID
+*/
+int QtxPreferenceItem::generateId()
+{
+  static int _id = 0;
+  return _id++;
+}
+
+/*!
+  \class QtxPreferenceMgr
+  \brief Class for managing preferences items.
+*/
+
+/*!
+  \brief Constructor.
+  \param mgr resources manager
+*/
+QtxPreferenceMgr::QtxPreferenceMgr( QtxResourceMgr* mgr )
+: QtxPreferenceItem( 0 ),
+  myResMgr( mgr )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxPreferenceMgr::~QtxPreferenceMgr()
+{
+}
+
+/*!
+  \brief Get the resources manager.
+  \return resource manager pointer or 0 if it is not defined
+*/
+QtxResourceMgr* QtxPreferenceMgr::resourceMgr() const
+{
+  return myResMgr;
+}
+
+/*!
+  \brief Get the parent preferences manager.
+  \return pointer to itself
+*/
+QtxPreferenceMgr* QtxPreferenceMgr::preferenceMgr() const
+{
+  return (QtxPreferenceMgr*)this;
+}
+
+/*
+  \brief Add new preference item.
+  \param label label of widget to edit preference item
+  \param pId parent preference item id
+  \param type preference item type
+  \param section resource file section associated to the preference item
+  \param param resource file parameter associated to the preference item
+*/
+/*
+int QtxPreferenceMgr::addItem( const QString& label, const int pId, const int type,
+                               const QString& section, const QString& param )
+{
+  Item* i = createItem( label, type, pId );
+  if ( !i )
+    return -1;
+
+  if ( !myItems.contains( i->id() ) )
+  {
+    myItems.insert( i->id(), i );
+
+    i->setTitle( label );
+    i->setResource( section, param );
+
+    if ( !i->parentItem() && !myChildren.contains( i ) )
+      myChildren.append( i );
+
+    itemAdded( i );
+  }
+
+  return i->id();
+}
+*/
+
+/*!
+  \brief Get preference item option value.
+  \param id preference item ID
+  \param propName option name
+  \return property value or null QVariant if option is not set
+  \sa setOption()
+*/
+QVariant QtxPreferenceMgr::option( const int id, const QString& propName ) const
+{
+  QVariant propValue;
+  QtxPreferenceItem* i = findItem( id, true );
+  if ( i )
+    propValue = i->option( propName );
+  return propValue;
+}
+
+/*!
+  \brief Set preference item option value.
+  \param id preference item ID
+  \param propName option name
+  \param propValue new property value
+  \sa option()
+*/
+void QtxPreferenceMgr::setOption( const int id, const QString& propName, const QVariant& propValue )
+{
+  QtxPreferenceItem* i = findItem( id, true );
+  if ( i )
+    i->setOption( propName, propValue );
+}
+
+/*!
+  \brief Store all preferences item to the resource manager.
+  \sa retrieve()
+*/
+void QtxPreferenceMgr::store()
+{
+  ResourceMap before;
+  resourceValues( before );
+
+  QList<QtxPreferenceItem*> items = childItems( true );
+  for ( QList<QtxPreferenceItem*>::iterator it = items.begin(); it != items.end(); ++it )
+    (*it)->store();
+
+  ResourceMap after;
+  resourceValues( after );
+
+  ResourceMap changed;
+  differentValues( before, after, changed );
+
+  changedResources( changed );
+}
+
+/*!
+  \brief Retrieve all preference items from the resource manager.
+  \sa store()
+*/
+void QtxPreferenceMgr::retrieve()
+{
+  QList<QtxPreferenceItem*> items = childItems( true );
+  for ( QList<QtxPreferenceItem*>::iterator it = items.begin(); it != items.end(); ++it )
+    (*it)->retrieve();
+}
+
+/*!
+  \brief Dumps all values to the backup container.
+  \sa fromBackup()
+*/
+void QtxPreferenceMgr::toBackup()
+{
+  myBackup.clear();
+  resourceValues( myBackup );
+}
+
+/*!
+  \brief Restore all values from the backup container.
+  \sa toBackup()
+*/
+void QtxPreferenceMgr::fromBackup()
+{
+  ResourceMap before;
+  resourceValues( before );
+
+  setResourceValues( myBackup );
+
+  ResourceMap after;
+  resourceValues( after );
+
+  ResourceMap changed;
+  differentValues( before, after, changed );
+
+  changedResources( changed );
+}
+
+/*!
+  \brief Update preferences manager.
+  
+  Base implementation does nothing.
+*/
+void QtxPreferenceMgr::update()
+{
+}
+
+/*
+  \brief Create preference item.
+  \param label preference item title
+  \param type preference item type
+  \param pId parent preference item ID
+  \return new item
+*/
+/*
+QtxPreferenceItem* QtxPreferenceMgr::createItem( const QString& label, const int type, const int pId )
+{
+  Item* i = 0;
+  if ( pId < 0 )
+    i = createItem( label, type );
+  else
+  {
+    Item* pItem = item( pId );
+    if ( pItem )
+    {
+      i = pItem->createItem( label, type );
+      pItem->insertChild( i );
+    }
+  }
+
+  return i;
+}
+*/
+
+/*!
+  \brief Get all resources items values.
+  \param map used as container filled with the resources values (<ID>:<value>)
+  \sa setResourceValues()
+*/
+void QtxPreferenceMgr::resourceValues( QMap<int, QString>& map ) const
+{
+  QString sect, name;
+  QtxResourceMgr* resMgr = resourceMgr();
+  QList<QtxPreferenceItem*> items = childItems( true );
+  for ( QList<QtxPreferenceItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QtxPreferenceItem* item = *it;
+    item->resource( sect, name );
+    if ( resMgr->hasValue( sect, name ) )
+      map.insert( item->id(), item->resourceValue() );
+  }
+}
+
+/*!
+  \brief Get all resources items values.
+  \param map used as container filled with the resources values
+  (<item>:<value>)
+  \sa setResourceValues()
+*/
+void QtxPreferenceMgr::resourceValues( ResourceMap& map ) const
+{
+  QString sect, name;
+  QtxResourceMgr* resMgr = resourceMgr();
+  QList<QtxPreferenceItem*> items = childItems( true );
+  for ( QList<QtxPreferenceItem*>::const_iterator it = items.begin(); it != items.end(); ++it )
+  {
+    QtxPreferenceItem* item = *it;
+    item->resource( sect, name );
+    if ( resMgr->hasValue( sect, name ) )
+      map.insert( item, item->resourceValue() );
+  }
+}
+
+/*!
+  \brief Set all resources items values.
+  \param map map with resources values (<ID>:<value>)
+  \sa resourceValues()
+*/
+void QtxPreferenceMgr::setResourceValues( QMap<int, QString>& map ) const
+{
+  for ( QMap<int, QString>::const_iterator it = map.begin(); it != map.end(); ++it )
+  {
+    QtxPreferenceItem* i = findItem( it.key(), true );
+    if ( i )
+      i->setResourceValue( it.value() );
+  }
+}
+
+/*!
+  \brief Set all resources items values.
+  \param map map with resources values (<item>:<value>)
+  \sa resourceValues()
+*/
+void QtxPreferenceMgr::setResourceValues( ResourceMap& map ) const
+{
+  for ( ResourceMap::const_iterator it = map.begin(); it != map.end(); ++it )
+    it.key()->setResourceValue( it.value() );
+}
+
+/*!
+  \brief Compare two maps of resources values to find differences.
+  \param map1 first map
+  \param map2 second map
+  \param resMap map to be filled with different values
+  \param fromFirst if \c true, then \a resMap will be filled with the values
+  from \a map1, otherwise - from \a map2
+*/
+void QtxPreferenceMgr::differentValues( const QMap<int, QString>& map1, const QMap<int, QString>& map2,
+                                        QMap<int, QString>& resMap, const bool fromFirst ) const
+{
+  resMap.clear();
+  const QMap<int, QString>& later = fromFirst ? map1 : map2;
+  const QMap<int, QString>& early = fromFirst ? map2 : map1;
+
+  for ( QMap<int, QString>::const_iterator it = later.begin(); it != later.end(); ++it )
+  {
+    if ( !early.contains( it.key() ) || early[it.key()] != it.value() )
+      resMap.insert( it.key(), it.value() );
+  }
+}
+
+/*!
+  \brief Compare two maps of resources values to find differences.
+  \param map1 first map
+  \param map2 second map
+  \param resMap map to be filled with different values
+  \param fromFirst if \c true, then \a resMap will be filled with the values
+  from \a map1, otherwise - from \a map2
+*/
+void QtxPreferenceMgr::differentValues( const ResourceMap& map1, const ResourceMap& map2,
+                                        ResourceMap& resMap, const bool fromFirst ) const
+{
+  resMap.clear();
+  const ResourceMap& later = fromFirst ? map1 : map2;
+  const ResourceMap& early = fromFirst ? map2 : map1;
+
+  for ( ResourceMap::const_iterator it = later.begin(); it != later.end(); ++it )
+  {
+    if ( !early.contains( it.key() ) || early[it.key()] != it.value() )
+      resMap.insert( it.key(), it.value() );
+  }
+}
+
+/*!
+  \brief Perform custom activity on resource changing.
+
+  This method is called from store() and fromBackup() methods.
+  Base implementation does nothing.
+  
+  \sa store(), fromBackup()
+*/
+void QtxPreferenceMgr::changedResources( const ResourceMap& )
+{
+}
diff --git a/src/Qtx/QtxPreferenceMgr.h b/src/Qtx/QtxPreferenceMgr.h
new file mode 100644 (file)
index 0000000..50fc324
--- /dev/null
@@ -0,0 +1,179 @@
+// 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
+//
+// File:      QtxPreferenceMgr.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXPREFERENCEMGR_H
+#define QTXPREFERENCEMGR_H
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+#include "Qtx.h"
+
+#include <QFont>
+#include <QIcon>
+#include <QColor>
+#include <QVariant>
+
+class QtxResourceMgr;
+class QtxPreferenceMgr;
+
+class QTX_EXPORT QtxPreferenceItem
+{
+  class Updater;
+
+public:
+  QtxPreferenceItem( QtxPreferenceItem* = 0 );
+  QtxPreferenceItem( const QString&, QtxPreferenceItem* );
+  QtxPreferenceItem( const QString&, const QString&, const QString&, QtxPreferenceItem* );
+  virtual ~QtxPreferenceItem();
+
+  int                       id() const;
+  virtual int               rtti() const;
+
+  QtxPreferenceItem*        rootItem() const;
+  QtxPreferenceItem*        parentItem() const;
+  QList<QtxPreferenceItem*> childItems( const bool = false ) const;
+
+  int                       depth() const;
+  int                       count() const;
+  virtual bool              isEmpty() const;
+
+  void                      insertItem( QtxPreferenceItem* );
+  void                      removeItem( QtxPreferenceItem* );
+
+  QIcon                     icon() const;
+  QString                   title() const;
+  void                      resource( QString&, QString& ) const;
+
+  virtual void              setIcon( const QIcon& );
+  virtual void              setTitle( const QString& );
+  virtual void              setResource( const QString&, const QString& );
+
+  virtual void              updateContents();
+
+  QVariant                  option( const QString& ) const;
+  void                      setOption( const QString&, const QVariant& );
+
+  virtual void              store() = 0;
+  virtual void              retrieve() = 0;
+
+  QString                   resourceValue() const;
+  void                      setResourceValue( const QString& );
+
+  QtxPreferenceItem*        findItem( const int, const bool = false ) const;
+  QtxPreferenceItem*        findItem( const QString&, const bool = false ) const;
+  QtxPreferenceItem*        findItem( const QString&, const int, const bool = false ) const;
+
+  virtual QtxResourceMgr*   resourceMgr() const;
+  virtual QtxPreferenceMgr* preferenceMgr() const;
+
+  static int                RTTI();
+
+protected:
+  int                       getInteger( const int = 0 ) const;
+  double                    getDouble( const double = 0.0 ) const;
+  bool                      getBoolean( const bool = false ) const;
+  QColor                    getColor( const QColor& = QColor() ) const;
+  QFont                     getFont( const QFont& = QFont() ) const;
+  QString                   getString( const QString& = QString::null ) const;
+
+  void                      setInteger( const int );
+  void                      setDouble( const double );
+  void                      setBoolean( const bool );
+  void                      setColor( const QColor& );
+  void                      setFont( const QFont& );  
+  void                      setString( const QString& );
+
+  virtual void              itemAdded( QtxPreferenceItem* );
+  virtual void              itemRemoved( QtxPreferenceItem* );
+  virtual void              itemChanged( QtxPreferenceItem* );
+
+  void                      sendItemChanges();
+
+  virtual void              triggerUpdate();
+
+  virtual QVariant          optionValue( const QString& ) const;
+  virtual void              setOptionValue( const QString&, const QVariant& );
+
+protected:
+  typedef QList<QtxPreferenceItem*> ItemList;
+
+private:
+  static int                generateId();
+
+private:
+  int                       myId;
+  QtxPreferenceItem*        myParent;
+  ItemList                  myChildren;
+
+  QIcon                     myIcon;
+  QString                   myTitle;
+  QString                   mySection;
+  QString                   myParameter;
+};
+
+class QTX_EXPORT QtxPreferenceMgr : public QtxPreferenceItem
+{
+public:
+  QtxPreferenceMgr( QtxResourceMgr* );
+  virtual ~QtxPreferenceMgr();
+
+  virtual QtxResourceMgr*   resourceMgr() const;
+  virtual QtxPreferenceMgr* preferenceMgr() const;
+
+  QVariant                  option( const int, const QString& ) const;
+  void                      setOption( const int, const QString&, const QVariant& );
+
+  virtual void              store();
+  virtual void              retrieve();
+
+  virtual void              update();
+
+  virtual void              toBackup();
+  virtual void              fromBackup();
+
+protected:
+  typedef QMap<QtxPreferenceItem*, QString> ResourceMap;
+
+  void                      resourceValues( QMap<int, QString>& ) const;
+  void                      resourceValues( ResourceMap& ) const;
+
+  void                      setResourceValues( QMap<int, QString>& ) const;
+  void                      setResourceValues( ResourceMap& ) const;
+  
+  void                      differentValues( const QMap<int, QString>&, const QMap<int, QString>&,
+                                             QMap<int, QString>&, const bool fromFirst = false ) const;
+  void                      differentValues( const ResourceMap&, const ResourceMap&,
+                                             ResourceMap&, const bool fromFirst = false ) const;
+
+  virtual void              changedResources( const ResourceMap& );
+
+private:
+  QtxResourceMgr*           myResMgr;
+  ResourceMap               myBackup;
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
index 5f6edf1c436985612df5379d6520661fc1543188..2741e835264c96b1391e34c5763d91a038c33496 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#include "QtxResourceMgr.h"
-
-#include <QtCore/qdir.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qregexp.h>
-#include <QtCore/qtextstream.h>
-#include <QtCore/qtranslator.h>
+// File:      QtxResourceMgr.cxx
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
 
-#include <QtGui/qpixmap.h>
-#include <QtGui/qapplication.h>
+#include "QtxResourceMgr.h"
 
+#include <QDir>
+#include <QFile>
+#include <QRegExp>
+#include <QTextStream>
+#include <QTranslator>
+#include <QApplication>
 #ifndef QT_NO_DOM
-#include <QtXml/qdom.h>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QDomNode>
 #endif
 
 #define EMULATE_GLOBAL_CONTEXT
@@ -36,8 +38,9 @@
 #include <stdlib.h>
 
 /*!
-  Class: QtxResourceMgr::Resources
-  Level: Internal
+  \class QtxResourceMgr::Resources
+  \internal
+  \brief Represents container for settings read from the resource file.
 */
 
 class QtxResourceMgr::Resources
@@ -84,14 +87,19 @@ private:
   typedef QMap<QString, Section> SectionMap;
 
 private:
-  QtxResourceMgr*        myMgr;
-  SectionMap             mySections;
-  QString                myFileName;
-  QMap<QString,QPixmap>  myPixmapCache;
+  QtxResourceMgr*        myMgr;             //!< resources manager
+  SectionMap             mySections;        //!< sections map
+  QString                myFileName;        //!< resources file name
+  QMap<QString,QPixmap>  myPixmapCache;     //!< pixmaps cache
 
   friend class QtxResourceMgr::Format;
 };
 
+/*!
+  \brief Constructor.
+  \param mgr parent resources manager
+  \param fileName resources file name
+*/
 QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileName )
 : myMgr( mgr ),
   myFileName( fileName )
@@ -99,15 +107,19 @@ QtxResourceMgr::Resources::Resources( QtxResourceMgr* mgr, const QString& fileNa
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxResourceMgr::Resources::~Resources()
 {
 }
 
 /*!
-  Returns name of resource file
-  This file is used to load/save operations
+  \brief Get resources file name.
+
+  This file is used to load/save operations.
+
+  \return file name
+  \sa setFile()
 */
 QString QtxResourceMgr::Resources::file() const
 {
@@ -115,8 +127,9 @@ QString QtxResourceMgr::Resources::file() const
 }
 
 /*!
-  Sets name of resource file
-  \param fn - name of file
+  \brief Set resources file name.
+  \param fn file name
+  \sa file()
 */
 void QtxResourceMgr::Resources::setFile( const QString& fn )
 {
@@ -124,14 +137,12 @@ void QtxResourceMgr::Resources::setFile( const QString& fn )
 }
 
 /*!
-  Returns string representation of parameter value
-  Returns QString::null if there is no such parameter
-
-  \param sect - name of section
-  \param name - name of parameter
-  \param subst - if it is true, then the substitution of variables
-  will be done with help of makeSubstitution method
-  \sa makeSubstitution()
+  \brief Get string representation of parameter value.
+  \param sect section name
+  \param name parameter name
+  \param subst if \c true, perform variables substitution
+  \return parameter value or null QString if there is no such parameter
+  \sa setValue(), makeSubstitution()
 */
 QString QtxResourceMgr::Resources::value( const QString& sect, const QString& name, const bool subst ) const
 {
@@ -147,11 +158,11 @@ QString QtxResourceMgr::Resources::value( const QString& sect, const QString& na
 }
 
 /*!
-  Sets value by it's string representation
-
-  \param sect - name of section
-  \param name - name of parameter
-  \param val - string value
+  \brief Set parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
+  \sa value(), makeSubstitution()
 */
 void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& name, const QString& val )
 {
@@ -162,8 +173,9 @@ void QtxResourceMgr::Resources::setValue( const QString& sect, const QString& na
 }
 
 /*!
-  \return true if section exists
-  \param sect - name of section
+  \brief Check section existence.
+  \param sect section name
+  \return \c true if section exists
 */
 bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
 {
@@ -171,9 +183,10 @@ bool QtxResourceMgr::Resources::hasSection( const QString& sect ) const
 }
 
 /*!
-  \return true if parameter exists in section
-  \param sect - name of section
-  \param name - name of parameter
+  \brief Check parameter existence.
+  \param sect section name
+  \param name parameter name
+  \return \c true if parameter exists in specified section
 */
 bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& name ) const
 {
@@ -181,8 +194,8 @@ bool QtxResourceMgr::Resources::hasValue( const QString& sect, const QString& na
 }
 
 /*!
-  Removes section from resources
-  \param sect - name of section
+  \brief Remove resourcs section.
+  \param sect secton name
 */
 void QtxResourceMgr::Resources::removeSection( const QString& sect )
 {
@@ -190,9 +203,9 @@ void QtxResourceMgr::Resources::removeSection( const QString& sect )
 }
 
 /*!
-  Removes parameter from section
-  \param sect - name of section
-  \param name - name of parameter
+  \brief Remove parameter from the section.
+  \param sect section name
+  \param name parameter name
 */
 void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString& name )
 {
@@ -206,7 +219,7 @@ void QtxResourceMgr::Resources::removeValue( const QString& sect, const QString&
 }
 
 /*!
-  Removes all sections
+  \brief Remove all sections.
 */
 void QtxResourceMgr::Resources::clear()
 {
@@ -214,6 +227,7 @@ void QtxResourceMgr::Resources::clear()
 }
 
 /*!
+  \brief Get all sections names.
   \return list of section names
 */
 QStringList QtxResourceMgr::Resources::sections() const
@@ -222,8 +236,9 @@ QStringList QtxResourceMgr::Resources::sections() const
 }
 
 /*!
-  \return list of parameter names from section
-  \param sec - name of section
+  \brief Get all parameters name in specified section.
+  \param sec section name
+  \return list of settings names
 */
 QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
 {
@@ -234,11 +249,19 @@ QStringList QtxResourceMgr::Resources::parameters( const QString& sec ) const
 }
 
 /*!
-  \return path of file from directory built by parameter
-  \return QString::null if built path doesn't exist
-  \param sec - name of section
-  \param prefix - name of parameter containing some path
-  \param name - name of file
+  \brief Get absolute path to the file which name is defined by the parameter.
+
+  The file name is defined by \a name argument, while directory name is retrieved
+  from resources parameter \a prefix of section \a sec. Both directory and file name
+  can be relative. If the directory is relative, it is calculated from the initial
+  resources file name (see file()). Directory parameter can contain environment 
+  variables, which are substituted automatically.
+
+  \param sec section name
+  \param prefix parameter containing directory name
+  \param name file name
+  \return absolute file path or null QString if file does not exist
+  \sa fileName(), file(), makeSubstitution()
 */
 QString QtxResourceMgr::Resources::path( const QString& sec, const QString& prefix, const QString& name ) const
 {
@@ -252,7 +275,8 @@ QString QtxResourceMgr::Resources::path( const QString& sec, const QString& pref
 }
 
 /*!
-  \return corresponding resource manager
+  \brief Get resource manager
+  \return resource manager pointer
 */
 QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
 {
@@ -260,7 +284,12 @@ QtxResourceMgr* QtxResourceMgr::Resources::resMgr() const
 }
 
 /*!
-  \return instance of section by it's name. Section will be created if it doesn't exist
+  \brief Get resources section by specified name.
+
+  If section does not exist it is created (empty).
+
+  \param sn section name
+  \return resources section
 */
 QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
 {
@@ -271,7 +300,9 @@ QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn )
 }
 
 /*!
-  \return instance of section by it's name. Section will be created if it doesn't exist
+  \brief Get resources section by specified name.
+  \param sn section name
+  \return resources section
 */
 const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString& sn ) const
 {
@@ -279,10 +310,21 @@ const QtxResourceMgr::Section QtxResourceMgr::Resources::section( const QString&
 }
 
 /*!
-  \return full path of file
-  \param sect - name of section
-  \param prefix - name of parameter containing some path
-  \param name - name of file
+  \brief Get file path.
+
+  The file name is defined by \a name argument, while directory name is retrieved
+  from resources parameter \a prefix of section \a sec. Both directory and file name
+  can be relative. If the directory is relative, it is calculated from the initial
+  resources file name (see file()). Directory parameter can contain environment 
+  variables, which are substituted automatically.
+  File existence is not checked.
+
+  \param sec section name
+  \param prefix parameter containing directory name
+  \param name file name
+  \return absolute file path or null QString if \a prefix parameter
+          does not exist in section \sec
+  \sa path(), file(), makeSubstitution()
 */
 QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString& prefix, const QString& name ) const
 {
@@ -309,10 +351,16 @@ QString QtxResourceMgr::Resources::fileName( const QString& sect, const QString&
 }
 
 /*!
-  \return QPixmap loaded from file
-  \param sect - name of section
-  \param prefix - name of parameter containing some path
-  \param name - name of picture file
+  \brief Load and return pixmap from external file.
+  
+  If QtxResourceMgr::isPixmapCached() is \c true then cached pixmap is returned
+  (if it is already loaded), otherwise it is loaded from file.
+  If the file name is invalid, null pixmap is returned.
+
+  \param sect section name
+  \param prefix parameter containing resources directory name
+  \param name pixmap file name
+  \return pixmap loaded from file
 */
 QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QString& prefix, const QString& name ) const
 {
@@ -331,10 +379,11 @@ QPixmap QtxResourceMgr::Resources::loadPixmap( const QString& sect, const QStrin
 }
 
 /*!
-  \return just created and loaded translator
-  \param sect - name of section
-  \param prefix - name of parameter containing some path
-  \param name - name of file
+  \brief Load translator.
+  \param sect section name
+  \param prefix parameter containing resources directory
+  \param name translation file name
+  \return just created and loaded translator or 0 in case of error
 */
 QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, const QString& prefix, const QString& name ) const
 {
@@ -387,11 +436,18 @@ QTranslator* QtxResourceMgr::Resources::loadTranslator( const QString& sect, con
 }
 
 /*!
-  Finds in string variables by patterns: ${name} or $(name) or %name%
-  \return first found name or QString::null if there is no ones
-  \param str - string where the search is processed
-  \param start - integer value for returning start position of variable
-  \param len - integer value for returning length of variable
+  \brief Parse given string to retrieve environment variable.
+
+  Looks through the string for the patterns: ${name} or $(name) or %name%.
+  If string contains variable satisfying any pattern, the variable name
+  is returned, start index of the variable is returned in the \a start parameter,
+  and length of the variable is returned in the \a len parameter.
+
+  \param str string being processed
+  \param start if variable is found, this parameter contains its starting 
+         position in the \a str
+  \param len if variable is found, this parameter contains its length 
+  \return first found variable or null QString if there is no ones
 */
 QString QtxResourceMgr::Resources::environmentVariable( const QString& str, int& start, int& len ) const
 {
@@ -428,13 +484,15 @@ QString QtxResourceMgr::Resources::environmentVariable( const QString& str, int&
 }
 
 /*!
-  Substitutes variables by its' values. If variable is from enviroment,
-  it will be replaced by environment value. If it isn't, method tries to
-  find it's value among resources
-  \return new variant of string 'str'
-  \param str - string to process substitution
-  \param sect - section, in which the variables will be finding
-  \param name - name of variable which must be ignored during substitution
+  \brief Substitute variables by their values.
+
+  Environment variable is substituted by its value. For other variables resource
+  manager tries to find value among defined resources parameters.
+
+  \param str string to be processed
+  \param sect section, where variables are searched
+  \param name name of variable which must be ignored during substitution
+  \return processed string (with all substitutions made)
 */
 QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const QString& sect, const QString& name ) const
 {
@@ -476,9 +534,11 @@ QString QtxResourceMgr::Resources::makeSubstitution( const QString& str, const Q
 }
 
 /*!
-       Class: QtxResourceMgr::IniFormat
-       Level: Internal
+  \class QtxResourceMgr::IniFormat
+  \internal
+  \brief Reader/writer for .ini resources files.
 */
+
 class QtxResourceMgr::IniFormat : public Format
 {
 public:
@@ -491,7 +551,7 @@ protected:
 };
 
 /*!
-  Default constructor
+  \brief Constructor.
 */
 QtxResourceMgr::IniFormat::IniFormat()
 : Format( "ini" )
@@ -499,16 +559,17 @@ QtxResourceMgr::IniFormat::IniFormat()
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxResourceMgr::IniFormat::~IniFormat()
 {
 }
 
 /*!
-  Loads resources from ini-file to map of sections
-  \param fname - name of resource file
-  \param secMap - map of sections
+  \brief Load resources from ini-file.
+  \param fname resources file name
+  \param secMap resources map to be filled in
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Section>& secMap )
 {
@@ -576,9 +637,10 @@ bool QtxResourceMgr::IniFormat::load( const QString& fname, QMap<QString, Sectio
 }
 
 /*!
-  Saves map of sections to resource ini-file
-  \param fname - name of resource file
-  \param secMap - map of sections
+  \brief Save resources to the ini-file.
+  \param fname resources file name
+  \param secMap resources map
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
 {
@@ -606,8 +668,9 @@ bool QtxResourceMgr::IniFormat::save( const QString& fname, const QMap<QString,
 }
 
 /*!
-       Class: QtxResourceMgr::XmlFormat
-       Level: Internal
+  \class QtxResourceMgr::XmlFormat
+  \internal
+  \brief Reader/writer for .xml resources files.
 */
 
 class QtxResourceMgr::XmlFormat : public Format
@@ -629,7 +692,7 @@ private:
 };
 
 /*!
-  Default constructor
+  \brief Constructor.
 */
 QtxResourceMgr::XmlFormat::XmlFormat()
 : Format( "xml" )
@@ -637,16 +700,17 @@ QtxResourceMgr::XmlFormat::XmlFormat()
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxResourceMgr::XmlFormat::~XmlFormat()
 {
 }
 
 /*!
-  Loads resources from xml-file to map of sections
-  \param fname - name of resource file
-  \param secMap - map of sections
+  \brief Load resources from xml-file.
+  \param fname resources file name
+  \param secMap resources map to be filled in
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Section>& secMap )
 {
@@ -744,9 +808,10 @@ bool QtxResourceMgr::XmlFormat::load( const QString& fname, QMap<QString, Sectio
 }
 
 /*!
-  Saves map of sections to resource xml-file
-  \param fname - name of resource file
-  \param secMap - map of sections
+  \brief Save resources to the xml-file.
+  \param fname resources file name
+  \param secMap resources map
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString, Section>& secMap )
 {
@@ -789,7 +854,8 @@ bool QtxResourceMgr::XmlFormat::save( const QString& fname, const QMap<QString,
 }
 
 /*!
-  \return XML tag of document
+  \brief Get document tag name
+  \return XML document tag name
 */
 QString QtxResourceMgr::XmlFormat::docTag() const
 {
@@ -800,7 +866,8 @@ QString QtxResourceMgr::XmlFormat::docTag() const
 }
 
 /*!
-  \return XML tag of section
+  \brief Get section tag name
+  \return XML section tag name
 */
 QString QtxResourceMgr::XmlFormat::sectionTag() const
 {
@@ -811,7 +878,8 @@ QString QtxResourceMgr::XmlFormat::sectionTag() const
 }
 
 /*!
-  \return XML tag of parameter
+  \brief Get parameter tag name
+  \return XML parameter tag name
 */
 QString QtxResourceMgr::XmlFormat::parameterTag() const
 {
@@ -822,7 +890,8 @@ QString QtxResourceMgr::XmlFormat::parameterTag() const
 }
 
 /*!
-  \return XML attribute of parameter name
+  \brief Get parameter tag's "name" attribute name
+  \return XML parameter tag's "name" attribute name
 */
 QString QtxResourceMgr::XmlFormat::nameAttribute() const
 {
@@ -833,7 +902,8 @@ QString QtxResourceMgr::XmlFormat::nameAttribute() const
 }
 
 /*!
-  \return XML attribute of parameter value
+  \brief Get parameter tag's "value" attribute name
+  \return XML parameter tag's "value" attribute name
 */
 QString QtxResourceMgr::XmlFormat::valueAttribute() const
 {
@@ -844,13 +914,13 @@ QString QtxResourceMgr::XmlFormat::valueAttribute() const
 }
 
 /*!
-       Class: QtxResourceMgr::Format
-       Level: Public
+  \class QtxResourceMgr::Format
+  \brief Generic resources files reader/writer class.
 */
 
 /*!
-  \brief Constructs the format object with specified name.
-  \param fmt - name of the format
+  \brief Constructor.
+  \param fmt format name (for example, "xml" or "ini")
 */
 QtxResourceMgr::Format::Format( const QString& fmt )
 : myFmt( fmt )
@@ -858,14 +928,15 @@ QtxResourceMgr::Format::Format( const QString& fmt )
 }
 
 /*!
-  \brief Destructs the format object.
+  \brief Destructor
 */
 QtxResourceMgr::Format::~Format()
 {
 }
 
 /*!
-  \brief Returns the format name.
+  \brief Get the format name.
+  \return format name
 */
 QString QtxResourceMgr::Format::format() const
 {
@@ -873,7 +944,8 @@ QString QtxResourceMgr::Format::format() const
 }
 
 /*!
-  \brief Returns the string list of the format options.
+  \brief Get options names.
+  \return list of the format options
 */
 QStringList QtxResourceMgr::Format::options() const
 {
@@ -881,9 +953,12 @@ QStringList QtxResourceMgr::Format::options() const
 }
 
 /*!
-  \brief Returns the value of the option with specified name.
-         If option doesn't exist then empty string returned.
-  \param opt - name of the option
+  \brief Get the value of the option with specified name.
+
+  If option doesn't exist then null QString is returned.
+        
+  \param opt option name
+  \return option value
 */
 QString QtxResourceMgr::Format::option( const QString& opt ) const
 {
@@ -894,9 +969,9 @@ QString QtxResourceMgr::Format::option( const QString& opt ) const
 }
 
 /*!
-  \brief Sets the value of the option with specified name.
-  \param opt - name of the option
-  \param opt - value of the option
+  \brief Set the value of the option with specified name.
+  \param opt option name
+  \param val option value
 */
 void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
 {
@@ -904,8 +979,9 @@ void QtxResourceMgr::Format::setOption( const QString& opt, const QString& val )
 }
 
 /*!
-  \brief Perform the loading of the resources from resource file.
-  \param res - resources object which will be loaded
+  \brief Load resources from the resource file.
+  \param res resources object
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::Format::load( Resources* res )
 {
@@ -923,8 +999,9 @@ bool QtxResourceMgr::Format::load( Resources* res )
 }
 
 /*!
-  \brief Perform the saving of the resources into resource file.
-  \param res - resources object which will be saved
+  \brief Save resources to the resource file.
+  \param res resources object
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::Format::save( Resources* res )
 {
@@ -939,34 +1016,111 @@ bool QtxResourceMgr::Format::save( Resources* res )
 }
 
 /*!
-       Class: QtxResourceMgr
-       Level: Public
+  \fn virtual bool QtxResourceMgr::Format::load( const QString& fname,
+                                                 QMap<QString, Section>& secMap )
+  \brief Load resources from the specified resources file.
+
+  Should be implemented in the successors.
+
+  \param fname resources file name
+  \param secMap resources map to be filled in
+  \return \c true on success and \c false on error
 */
 
 /*!
-  \brief Constructs the resource manager object for application.
-  \param appName - name of the application which resources will be used.
-  \param resVarTemplate - template for the resource environment variable name which
-                          should point to the resource directory list.
-                          Default value is "%1Resources". Its mean that for application
-                          with name "MyApp" environment variable "MyAppResources" will
-                          be used. Template may not have the parameter '%1' substituted
-                          by application name. In this case this string will be used as
-                          is without substitution.
-  Resource environment variable should contains one or several resource directories
-  separated by symbol ';'. Resource directories list transfered into the setDirList().
-  These directories and the user home directory used for the loading application resources.
-  Each of the resource directories can contains resource file. The name of this file defined
-  by the function globalFileName(). Resource file name in the user home defined by the
-  function userFileName(). Any resource looking firstly in the user home resources then
-  resource directories used in the specified order. All setted resources always stored into
-  the resource file at the user home. Only user home resource file is saved.
-  If you want to ignore of loading of Local User Preferences, you needs setup setIngoreUserValues()
-  as true.
+ \fn virtual bool QtxResourceMgr::Format::save( const QString& fname, 
+                                                const QMap<QString, Section>& secMap )
+
+  \brief Save resources to the specified resources file.
+
+  Should be implemented in the successors.
+
+  \param fname resources file name
+  \param secMap resources map
+  \return \c true on success and \c false on error
+*/
+
+/*!
+  \class QtxResourceMgr
+  \brief Application resources manager.
+
+  This class can be used to define settings, save/load settings and 
+  application preferences to the resource file(s), load translation files
+  (internationalization mechanism), load pixmaps and other resources from
+  external files, etc.
+
+  Currently it supports .ini and .xml resources file formats. To implement
+  own resources file format, inherit from the Format class and implement virtual
+  Format::load() and Format::save() methods.
+
+  Resources manager is initialized by the (symbolic) name of the application.
+  The parameter \a resVarTemplate specifies the template for the environment
+  variable which should point to the resource directory or list of directories.
+  Environment variable  name is calculated by substitution of "%1" substring in
+  the \a resVarTemplate parameter (if it contains such substring) by the 
+  application name (\a appName).
+  By default, \a resVarTemplate is set to "%1Resources". For example, if the application name
+  is "MyApp", the environment variable "MyAppResources" will be inspected in this case.
+  
+  Resource manager can handle several global application configuration files and
+  one user configuration file. Location of global configuration files is defined
+  by the environment variable (see above) and these files are always read-only.
+  The name of the global configuration files is retrieved by calling virtual method
+  globalFileName() which can be redefined in the QtxResourceMgr class successors.
+  User configuration file always situated in the user's home directory. It's name
+  is defined by calling virtual method userFileName() which can be also redefined
+  in the QtxResourceMgr class successors. This is the only file which the preferences
+  changed by the user during the application session are written to (usually 
+  when the application closes).
+
+  Resources environment variable should contain one or several resource directories
+  (separated by ";" symbol on Windows and ":" or ";" on Linux). Each resource directory 
+  can contain application global configuration file. The user configuration file has
+  the highest priority, for the global configuration files the priority is decreasing from
+  left to right, i.e. the first directory in the directoris list, defined by the 
+  resources environment variable has higher priority. Priority has the meaning when
+  searching requested resources (application preference, pixmap file name, translation
+  file, etc).
+  Loading of the user configuration file can be omitted by calling setIgnoreUserValues() 
+  with \c true parameter.
+
+  Resources manager operates with such terms like options, sections and parameters. 
+  Parametets are named application resources, for example, application preferences like
+  integer, double, boolean or string values, pictures, font and color definitions, etc.
+  Parameters are organized inside the resources files into the named groups - sections.
+  Options are special kind of resoures which allow customizing resource files interpreting.
+  For example, by default language settings are defined in the resource file in the
+  section "language". It is possible to change this section name by setting "language" 
+  option to another value (see setOption()).
+  
+  Retrieving preferences values can be done by using one of value() methods, each returns
+  \c true if the corresponding preference is found. Another way is to use integerValue(),
+  doubleValue(), etc methods, which allow specifying default value which is used if the
+  specified preference is not found. Removing of preferences or sections can be done using
+  remove(const QString& sect) or remove(const QString& sect, const QString& name) methods.
+  To add the preference or to change exiting preference value use setValue() methods family.
+  Methods hasSection() and hasValue() can be used to check existence of section or
+  preference (in the specified section). List of all sections can be retrieved with the
+  sections() method, and list of all settings names in some specified section can be 
+  obtained with parameters() method.
+
+  Pixmaps can be loaded with the loadPixmap() methods. If the specified pixmap is not found,
+  the default one is returned. Default pixmap can be set by setDefaultPixmap().
+
+  One of the key feature of the resources manager is support of application 
+  internationalization mechanism. Translation files for the specified language can be loaded
+  with loadLanguage() method.
+*/
+
+/*!
+  \brief Constructs the resource manager.
+  \param appName application name
+  \param resVarTemplate resource environment variable pattern
 */
 QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTemplate )
 : myAppName( appName ),
   myCheckExist( true ),
+  myDefaultPix( 0 ),
   myIsPixmapCached( true ),
   myIsIgnoreUserValues( false )
 {
@@ -991,7 +1145,9 @@ QtxResourceMgr::QtxResourceMgr( const QString& appName, const QString& resVarTem
 }
 
 /*!
-  \brief Destructs the resource manager object and free allocated memory.
+  \brief Destructor.
+  
+  Destroy the resource manager and free allocated memory.
 */
 QtxResourceMgr::~QtxResourceMgr()
 {
@@ -1003,10 +1159,13 @@ QtxResourceMgr::~QtxResourceMgr()
   myResources.clear();
   for ( FormatList::iterator formIt = myFormats.begin(); formIt != myFormats.end(); ++formIt )
     delete *formIt;
+
+  delete myDefaultPix;
 }
 
 /*!
-  \brief Returns the application name.
+  \brief Get the application name.
+  \return application name
 */
 QString QtxResourceMgr::appName() const
 {
@@ -1014,9 +1173,12 @@ QString QtxResourceMgr::appName() const
 }
 
 /*!
-  \brief Returns the checking of the existance flag. If its 'true' then resource
-         will be setted into the manager only if it doesn't exist or has different
-         value that existing value.
+  \brief Get the "check existance" flag
+
+  If this flag is \c true then preference can be set (with setValue() method) 
+  only if it doesn't exist or if the value is changed.
+
+  \return \c true if "check existance" flag is set
 */
 bool QtxResourceMgr::checkExisting() const
 {
@@ -1024,8 +1186,8 @@ bool QtxResourceMgr::checkExisting() const
 }
 
 /*!
-  \brief Sets the checking of the existance flag.
-  \param on - boolean value of the flag.
+  \brief Set the "check existance" flag.
+  \param on new flag value
 */
 void QtxResourceMgr::setCheckExisting( const bool on )
 {
@@ -1033,7 +1195,13 @@ void QtxResourceMgr::setCheckExisting( const bool on )
 }
 
 /*!
-  \brief Returns the resource directories list except user home directory.
+  \brief Get the resource directories list.
+
+  Home user directory (where the user application configuration file is situated)
+  is not included. This is that directories list defined by the application
+  resources environment variable.
+
+  \return list of directories names
 */
 QStringList QtxResourceMgr::dirList() const
 {
@@ -1041,8 +1209,11 @@ QStringList QtxResourceMgr::dirList() const
 }
 
 /*!
-  \brief Initialise the manager. Prepare the resource containers and load resources.
-  \param autoLoad - if 'true' then all resources will be loaded.
+  \brief Initialise resources manager.
+
+  Prepare the resources containers and load resources (if \a autoLoad is \c true).
+
+  \param autoLoad if \c true then all resources are loaded
 */
 void QtxResourceMgr::initialize( const bool autoLoad ) const
 {
@@ -1065,7 +1236,15 @@ void QtxResourceMgr::initialize( const bool autoLoad ) const
 }
 
 /*!
-  \brief Return true if all loaded pixmaps are stored in internal map; by default: true
+  \brief Get "cached pixmaps" option value.
+
+  Resources manager allows possibility to cache loaded pixmaps that allow to
+  improve application performance. This feature is turned on by default - all 
+  loaded pixmaps are stored in the internal map. Switching of this feature on/off
+  can be done by setIsPixmapCached() method.
+
+  \return \c true if pixmap cache is turned on
+  \sa setIsPixmapCached()
 */
 bool QtxResourceMgr::isPixmapCached() const
 {
@@ -1073,8 +1252,9 @@ bool QtxResourceMgr::isPixmapCached() const
 }
 
 /*!
-  \brief Set true, if it is necessary to store all loaded pixmap in internal map
-  (it accelerates following calls of loadPixmap)
+  \brief Switch "cached pixmaps" option on/off.
+  \param on enable pixmap cache if \c true and disable it if \c false
+  \sa isPixmapCached()
 */
 void QtxResourceMgr::setIsPixmapCached( const bool on )
 {
@@ -1082,7 +1262,7 @@ void QtxResourceMgr::setIsPixmapCached( const bool on )
 }
 
 /*!
-  \brief Removes all resources from the manager.
+  \brief Remove all resources from the resources manager.
 */
 void QtxResourceMgr::clear()
 {
@@ -1091,8 +1271,12 @@ void QtxResourceMgr::clear()
 }
 
 /*!
-  Set state 'ignore user values'.
-  If it is true, then all resources loaded from user home directory is ignored
+  \brief Set "ignore user values" option value.
+  
+  If this option is \c true, then all resources loaded from user home directory are ignored.
+  
+  \param val new option value
+  \sa ignoreUserValues()
 */
 void QtxResourceMgr::setIgnoreUserValues( const bool val )
 {
@@ -1100,7 +1284,10 @@ void QtxResourceMgr::setIgnoreUserValues( const bool val )
 }
 
 /*!
-  \return state 'ignore user values'
+  \brief Get "ignore user values" option value.
+  
+  \return "ignore user values" option value
+  \sa setIgnoreUserValues()
 */
 bool QtxResourceMgr::ignoreUserValues() const
 {
@@ -1108,11 +1295,12 @@ bool QtxResourceMgr::ignoreUserValues() const
 }
 
 /*!
-  \brief Get the resource value as integer. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param iVal - Reference on the variable which should contains the resource output.
+  \brief Get interger parameter value.
+  \param sect section name
+  \param name parameter name
+  \param iVal parameter to return resulting integer value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a iVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal ) const
 {
@@ -1127,11 +1315,12 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, int& iVal
 }
 
 /*!
-  \brief Get the resource value as double. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param dVal - Reference on the variable which should contains the resource output.
+  \brief Get double parameter value.
+  \param sect section name
+  \param name parameter name
+  \param dVal parameter to return resulting double value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a dVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dVal ) const
 {
@@ -1146,11 +1335,12 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, double& dV
 }
 
 /*!
-  \brief Get the resource value as boolean. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param bVal - Reference on the variable which should contains the resource output.
+  \brief Get boolean parameter value.
+  \param sect section name
+  \param name parameter name
+  \param bVal parameter to return resulting boolean value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a bVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal ) const
 {
@@ -1180,11 +1370,12 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, bool& bVal
 }
 
 /*!
-  \brief Get the resource value as color. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param cVal - Reference on the variable which should contains the resource output.
+  \brief Get color parameter value.
+  \param sect section name
+  \param name parameter name
+  \param cVal parameter to return resulting color value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a cVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cVal ) const
 {
@@ -1228,11 +1419,12 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cV
 }
 
 /*!
-  \brief Get the resource value as font. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param fVal - Reference on the variable which should contains the resource output.
+  \brief Get font parameter value.
+  \param sect section name
+  \param name parameter name
+  \param fVal parameter to return resulting font value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a fVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVal ) const
 {
@@ -1273,11 +1465,12 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, QFont& fVa
 }
 
 /*!
-  \brief Get the resource value as byte array. Returns 'true' if it successfull otherwise
-         returns 'false'.
-  \param sect - Resource section name which contains resource.
-  \param name - Name of the resource.
-  \param baVal - Reference on the variable which should contains the resource output.
+  \brief Get byte array parameter value.
+  \param sect section name
+  \param name parameter name
+  \param baVal parameter to return resulting byte array value
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a baVal value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray& baVal ) const
 {
@@ -1307,14 +1500,13 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, QByteArray
 }
 
 /*!
-  \brief Get the resource value as string (native format). Returns 'true' if it
-         successfull otherwise returns 'false'.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param val   - Reference on the variable which should contains the resource output.
-  \param subst - If 'true' then manager substitute reference on environment variables
-                 and other resources by thier values. Default value of this parameter
-                 is 'true'
+  \brief Get string parameter value (native format).
+  \param sect section name
+  \param name parameter name
+  \param val parameter to return resulting byte array value
+  \param subst if \c true perform environment variables substitution
+  \return \c true if parameter is found and \c false if parameter is not found
+          (in this case \a val value is undefined)
 */
 bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& val, const bool subst ) const
 {
@@ -1337,11 +1529,15 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, QString& v
 }
 
 /*!
-  \brief Returns the integer resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get interger parameter value.
+
+  If the specified parameter is not found or can not be converted to the integer value,
+  the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 int QtxResourceMgr::integerValue( const QString& sect, const QString& name, const int def ) const
 {
@@ -1352,11 +1548,15 @@ int QtxResourceMgr::integerValue( const QString& sect, const QString& name, cons
 }
 
 /*!
-  \brief Returns the double resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get double parameter value.
+
+  If the specified parameter is not found or can not be converted to the double value,
+  the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, const double def ) const
 {
@@ -1367,11 +1567,15 @@ double QtxResourceMgr::doubleValue( const QString& sect, const QString& name, co
 }
 
 /*!
-  \brief Returns the boolean resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get boolean parameter value.
+
+  If the specified parameter is not found or can not be converted to the boolean value,
+  the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, const bool def ) const
 {
@@ -1382,11 +1586,15 @@ bool QtxResourceMgr::booleanValue( const QString& sect, const QString& name, con
 }
 
 /*!
-  \brief Returns the font resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get font parameter value.
+
+  If the specified parameter is not found or can not be converted to the font value,
+  the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const QFont& def ) const
 {
@@ -1397,11 +1605,15 @@ QFont QtxResourceMgr::fontValue( const QString& sect, const QString& name, const
 }
 
 /*!
-  \brief Returns the color resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get color parameter value.
+
+  If the specified parameter is not found or can not be converted to the color value,
+  the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, const QColor& def ) const
 {
@@ -1412,11 +1624,14 @@ QColor QtxResourceMgr::colorValue( const QString& sect, const QString& name, con
 }
 
 /*!
-  \brief Returns the string resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get string parameter value.
+
+  If the specified parameter is not found, the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, const QString& def ) const
 {
@@ -1427,11 +1642,14 @@ QString QtxResourceMgr::stringValue( const QString& sect, const QString& name, c
 }
 
 /*!
-  \brief Returns the byte array resource value. If resource can not be found or converted
-         then specified default value will be returned.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
-  \param def   - Default resource value which will be used when resource not found.
+  \brief Get byte array parameter value.
+
+  If the specified parameter is not found, the specified default value is returned instead.
+
+  \param sect section name
+  \param name parameter name
+  \param def default value
+  \return parameter value (or default value if parameter is not found)
 */
 QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& name, const QByteArray& def ) const
 {
@@ -1442,9 +1660,10 @@ QByteArray QtxResourceMgr::byteArrayValue( const QString& sect, const QString& n
 }
 
 /*!
-  \brief Checks existance of the specified resource.
-  \param sect  - Resource section name which contains resource.
-  \param name  - Name of the resource.
+  \brief Check parameter existence.
+  \param sect section name
+  \param name parameter name
+  \return \c true if parameter exists in specified section
 */
 bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
 {
@@ -1458,8 +1677,9 @@ bool QtxResourceMgr::hasValue( const QString& sect, const QString& name ) const
 }
 
 /*!
-  \brief Checks existance of the specified resource section.
-  \param sect  - Resource section name which contains resource.
+  \brief Check section existence.
+  \param sect section name
+  \return \c true if section exists
 */
 bool QtxResourceMgr::hasSection( const QString& sect ) const
 {
@@ -1473,10 +1693,10 @@ bool QtxResourceMgr::hasSection( const QString& sect ) const
 }
 
 /*!
-  \brief Sets the integer resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set integer parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val )
 {
@@ -1488,10 +1708,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, int val
 }
 
 /*!
-  \brief Sets the double resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set double parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, double val )
 {
@@ -1503,10 +1723,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, double
 }
 
 /*!
-  \brief Sets the boolean resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set boolean parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool val )
 {
@@ -1518,10 +1738,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, bool va
 }
 
 /*!
-  \brief Sets the color resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set color parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QColor& val )
 {
@@ -1533,10 +1753,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Q
 }
 
 /*!
-  \brief Sets the font resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set font parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QFont& val )
 {
@@ -1558,10 +1778,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Q
 }
 
 /*!
-  \brief Sets the string resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set string parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QString& val )
 {
@@ -1573,10 +1793,10 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Q
 }
 
 /*!
-  \brief Sets the string resource value.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
-  \param val   - Resource value.
+  \brief Set byte array parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setValue( const QString& sect, const QString& name, const QByteArray& val )
 {
@@ -1588,16 +1808,15 @@ void QtxResourceMgr::setValue( const QString& sect, const QString& name, const Q
   QStringList lst;
   for ( int i = 0; i < val.size();  i++ )
   {
-    ::sprintf( buf, "#%02X", val.at( i ) );
+    ::sprintf( buf, "#%02X", (unsigned char)val.at( i ) );
     lst.append( QString( buf ) );
   }
-
   setResource( sect, name, lst.join( " " ) );
 }
 
 /*!
-  \brief Remove the all specified resource section.
-  \param sect  - Resource section name.
+  \brief Remove resources section.
+  \param sect section name
 */
 void QtxResourceMgr::remove( const QString& sect )
 {
@@ -1608,9 +1827,9 @@ void QtxResourceMgr::remove( const QString& sect )
 }
 
 /*!
-  \brief Remove the specified resource.
-  \param sect  - Resource section name.
-  \param name  - Name of the resource.
+  \brief Remove the specified parameter.
+  \param sect section name
+  \param name parameter name
 */
 void QtxResourceMgr::remove( const QString& sect, const QString& name )
 {
@@ -1621,7 +1840,8 @@ void QtxResourceMgr::remove( const QString& sect, const QString& name )
 }
 
 /*!
-  \brief Returns the current format which operates with resource files.
+  \brief Get current configuration files format.
+  \return configuration files format name
 */
 QString QtxResourceMgr::currentFormat() const
 {
@@ -1632,8 +1852,8 @@ QString QtxResourceMgr::currentFormat() const
 }
 
 /*!
-  \brief Sets the current format which operates with resource files.
-  \param fmt - Resource format name.
+  \brief Set current configuration files format.
+  \param fmt configuration files format name
 */
 void QtxResourceMgr::setCurrentFormat( const QString& fmt )
 {
@@ -1659,8 +1879,9 @@ void QtxResourceMgr::setCurrentFormat( const QString& fmt )
 }
 
 /*!
-  \brief Returns the resource format object by it name.
-  \param fmt - Resource format name.
+  \brief Get configuration files format by specified format name.
+  \param fmt configuration files format name
+  \return format object or 0 if format is not defined
 */
 QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
 {
@@ -1675,8 +1896,11 @@ QtxResourceMgr::Format* QtxResourceMgr::format( const QString& fmt ) const
 }
 
 /*!
-  \brief Add the resource format to the manager. Newly added become current.
-  \param form - Resource format object.
+  \brief Install configuration files format.
+  
+  Added format becomes current.
+
+  \param form format object to be installed
 */
 void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
 {
@@ -1685,8 +1909,8 @@ void QtxResourceMgr::installFormat( QtxResourceMgr::Format* form )
 }
 
 /*!
-  \brief Remove the resource format from the manager.
-  \param form - Resource format object.
+  \brief Remove configuration files format.
+  \param form format object to be uninstalled
 */
 void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
 {
@@ -1694,7 +1918,8 @@ void QtxResourceMgr::removeFormat( QtxResourceMgr::Format* form )
 }
 
 /*!
-  \brief Returns the string list of the resource format options names.
+  \brief Get resource format options names.
+  \return list of options names
 */
 QStringList QtxResourceMgr::options() const
 {
@@ -1702,9 +1927,13 @@ QStringList QtxResourceMgr::options() const
 }
 
 /*!
-  \brief Returns the string value for the specified option. If option doesn't exist
-         then empty string will be returned.
-  \param opt - Option name.
+  \brief Get the string value of the specified resources format option.
+
+  If option does not exist, null QString is returned.
+
+  \param opt option name
+  \return option value
+  \sa setOption(), options()
 */
 QString QtxResourceMgr::option( const QString& opt ) const
 {
@@ -1715,9 +1944,10 @@ QString QtxResourceMgr::option( const QString& opt ) const
 }
 
 /*!
-  \brief Sets the string value for the specified option.
-  \param opt - Option name.
-  \param val - Option value.
+  \brief Set the string value of the specified resources format option.
+  \param opt option name
+  \param val option value
+  \sa option(), options()
 */
 void QtxResourceMgr::setOption( const QString& opt, const QString& val )
 {
@@ -1725,7 +1955,9 @@ void QtxResourceMgr::setOption( const QString& opt, const QString& val )
 }
 
 /*!
-  \brief Load the all resources from the resource files.
+  \brief Load all resources from all resource files (global and user).
+  \return \c true on success and \c false on error
+  \sa save()
 */
 bool QtxResourceMgr::load()
 {
@@ -1743,7 +1975,9 @@ bool QtxResourceMgr::load()
 }
 
 /*!
-  \brief Import some file with resources
+  \brief Import resources from specified resource file.
+  \param fname resources file name
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::import( const QString& fname )
 {
@@ -1763,7 +1997,8 @@ bool QtxResourceMgr::import( const QString& fname )
 }
 
 /*!
-  \brief Save the changed resources in to the user resource file.
+  \brief Save all resources to the user resource files.
+  \return \c true on success and \c false on error
 */
 bool QtxResourceMgr::save()
 {
@@ -1780,7 +2015,8 @@ bool QtxResourceMgr::save()
 }
 
 /*!
-  \brief Returns the string list of the existing section names..
+  \brief Get all sections names.
+  \return list of section names
 */
 QStringList QtxResourceMgr::sections() const
 {
@@ -1802,8 +2038,9 @@ QStringList QtxResourceMgr::sections() const
 }
 
 /*!
-  \brief Returns the string list of the existing resource names in the specified section.
-  \param sec - Resource section name.
+  \brief Get all parameters name in specified section.
+  \param sec section name
+  \return list of settings names
 */
 QStringList QtxResourceMgr::parameters( const QString& sec ) const
 {
@@ -1834,11 +2071,18 @@ QStringList QtxResourceMgr::parameters( const QString& sec ) const
 }
 
 /*!
-  \return path of file from directory built by parameter
-  \return QString::null if built path doesn't exist
-  \param sec - name of section
-  \param prefix - name of parameter containing some path
-  \param name - name of file
+  \brief Get absolute path to the file which name is defined by the parameter.
+
+  The file name is defined by \a name argument, while directory name is retrieved
+  from resources parameter \a prefix of section \a sec. Both directory and file name
+  can be relative. If the directory is relative, it is calculated from the initial
+  resources file name. Directory parameter can contain environment 
+  variables, which are substituted automatically.
+
+  \param sec section name
+  \param prefix parameter containing directory name
+  \param name file name
+  \return absolute file path or null QString if file does not exist
 */
 QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const QString& name ) const
 {
@@ -1849,7 +2093,13 @@ QString QtxResourceMgr::path( const QString& sect, const QString& prefix, const
 }
 
 /*!
-  \return section corresponding to resources paths
+  \brief Get application resources section name.
+
+  By default, application resources section name is "resources" but
+  it can be changed by setting the corresponding resources manager option.
+  
+  \return section corresponding to the resources directories
+  \sa option(), setOption()
 */
 QString QtxResourceMgr::resSection() const
 {
@@ -1860,7 +2110,13 @@ QString QtxResourceMgr::resSection() const
 }
 
 /*!
-  \return section corresponding to language settings
+  \brief Get application language section name.
+
+  By default, application language section name is "language" but
+  it can be changed by setting the corresponding resources manager option.
+  
+  \return section corresponding to the application language settings
+  \sa option(), setOption()
 */
 QString QtxResourceMgr::langSection() const
 {
@@ -1871,26 +2127,44 @@ QString QtxResourceMgr::langSection() const
 }
 
 /*!
-  \return default image used when during loading the image file doesn't exist
+  \brief Get default pixmap.
+  
+  Default pixmap is used when requested pixmap resource is not found.
+
+  \return default pixmap
+  \sa setDefaultPixmap(), loadPixmap()
 */
 QPixmap QtxResourceMgr::defaultPixmap() const
 {
-  return myDefaultPix;
+  QPixmap res;
+  if ( myDefaultPix && !myDefaultPix->isNull() )
+    res = *myDefaultPix;
+  return res;
 }
 
 /*!
-  Set image as default image used when during loading the image file doesn't exist
-  \param pix - image
+  \brief Set default pixmap.
+  
+  Default pixmap is used when requested pixmap resource is not found.
+
+  \param pix default pixmap
+  \sa defaultPixmap(), loadPixmap()
 */
 void QtxResourceMgr::setDefaultPixmap( const QPixmap& pix )
 {
-  myDefaultPix = pix;
+  delete myDefaultPix;
+  if ( pix.isNull() )
+    myDefaultPix = 0;
+  else
+    myDefaultPix = new QPixmap( pix );
 }
 
 /*!
-  \return image loaded from file 
-  \param prefix - name of parameter containing some path
-  \param name - name of file
+  \brief Load pixmap resource.
+  \param prefix parameter which refers to the resources directory (directories)
+  \param name pixmap file name
+  \return pixmap loaded from the file 
+  \sa defaultPixmap(), setDefaultPixmap()
 */
 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name ) const
 {
@@ -1898,12 +2172,14 @@ QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name )
 }
 
 /*!
-  \return image loaded from file 
-  \param prefix - name of parameter containing some path
-  \param name - name of file
-  \param useDef - indicates if it is possible to use default image returning by defaultPixmap() method.
-  If it is false, the empty pixmap will be used as default
-  \sa defaultPixmap()
+  \brief Load pixmap resource.
+  \overload
+  \param prefix parameter which refers to the resources directory (directories)
+  \param name pixmap file name
+  \param useDef if \c false, default pixmap is not returned if resource is not found,
+         in this case null pixmap is returned instead
+  \return pixmap loaded from the file 
+  \sa defaultPixmap(), setDefaultPixmap()
 */
 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const bool useDef ) const
 {
@@ -1911,13 +2187,13 @@ QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name,
 }
 
 /*!
-  Finds in all sections an existing path corresponding to 'prefix' parameter
-  and load image with name 'name' from this folder
-
-  \return image loaded from file 
-  \param prefix - name of parameter containing some path
-  \param name - name of file
-  \param defPix - default image used when file doesn't exist
+  \brief Load pixmap resource.
+  \overload
+  \param prefix parameter which refers to the resources directory (directories)
+  \param name pixmap file name
+  \param defPix default which should be used if the resource file doesn't exist
+  \return pixmap loaded from the file 
+  \sa defaultPixmap(), setDefaultPixmap()
 */
 QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name, const QPixmap& defPix ) const
 {
@@ -1932,20 +2208,25 @@ QPixmap QtxResourceMgr::loadPixmap( const QString& prefix, const QString& name,
 }
 
 /*!
-  Loads translator for language
-  Name of translator file is constructed by list returning by option "translators" or,
-  if it is empty, by predefined pattern "%P_msg_%L.qm". It is recommended to used in translators
-  name the strings %A, %P, %L whose will be replaced by application name, prefix and language name correspondingly
+  \brief Load translation files according to the specified language.
+
+  Names of the translation files are calculated according to the pattern specified
+  by the "translators" option (this option is read from the section "language" of resources files).
+  By default, "%P_msg_%L.qm" pattern is used.
+  Keywords \%A, \%P, \%L in the pattern are substituted by the application name, prefix and language name
+  correspondingly.
+  For example, for prefix "SUIT" an language "en", all translation files "SUIT_msg_en.qm" are searched and
+  loaded.
 
-  \param pref - name of parameter containing path to translator's file.
-  If it is empty, the list of parameters from resource section ( resSection() )
-  is used.
+  If prefix is empty or null string, all translation files specified in the "resources" section of resources
+  files are loaded (actually, the section is retrieved from resSection() method). 
+  If language is not specified, it is retrieved from the langSection() method, and if the latest is also empty,
+  by default "en" (English) language is used.
 
-  \param l - name of language. If it is empty, then value of parameter "language"
-  from language section ( langSection() ) is used. If it is also empty, then
-  predefined name "en" is used
+  \param pref parameter which defines translation context (for example, package name)
+  \param l language name
 
-  \sa resSection(), langSection()
+  \sa resSection(), langSection(), loadTranslators()
 */
 void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
 {
@@ -2006,10 +2287,10 @@ void QtxResourceMgr::loadLanguage( const QString& pref, const QString& l )
 }
 
 /*!
-  Loads translators by path and list of files
-
-  \param prefix - value of this parameter must contain path
-  \param translators - list of translators' files 
+  \brief Load translation files for the specified translation context.
+  \param prefix parameter which defines translation context (for example, package name)
+  \param translators list of translation files 
+  \sa loadLanguage()
 */
 void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList& translators )
 {
@@ -2037,10 +2318,10 @@ void QtxResourceMgr::loadTranslators( const QString& prefix, const QStringList&
 }
 
 /*!
-  Loads translator by path and file name
-
-  \param prefix - value of this parameter must contain path
-  \param name - name of translator file
+  \brief Load translation file.
+  \param prefix parameter which defines translation context (for example, package name)
+  \param name translator file name
+  \sa loadLanguage(), loadTranslators()
 */
 void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name )
 {
@@ -2061,9 +2342,8 @@ void QtxResourceMgr::loadTranslator( const QString& prefix, const QString& name
 }
 
 /*!
-  Remove all translators corresponding to prefix
-
-  \param prefix - parameter containing path
+  \brief Remove all translators corresponding to the specified translation context.
+  \param prefix parameter which defines translation context (for example, package name)
 */
 void QtxResourceMgr::removeTranslators( const QString& prefix )
 {
@@ -2080,9 +2360,9 @@ void QtxResourceMgr::removeTranslators( const QString& prefix )
 }
 
 /*!
-  Moves translators corresponding to prefix to the top of translator stack 
-
-  \param prefix - parameter containing path
+  \brief Move all translators corresponding to the specified translation context 
+         to the top of translators stack (increase their priority).
+  \param prefix parameter which defines translation context (for example, package name)
 */
 void QtxResourceMgr::raiseTranslators( const QString& prefix )
 {
@@ -2097,7 +2377,8 @@ void QtxResourceMgr::raiseTranslators( const QString& prefix )
 }
 
 /*!
-  Copies all resources to user resources, so that they will be saved in user home folder
+  \brief Copy all parameters to the user resources in order to
+         saved them lately in the user home folder.
 */
 void QtxResourceMgr::refresh()
 {
@@ -2111,7 +2392,11 @@ void QtxResourceMgr::refresh()
 }
 
 /*!
-  \brief Sets the resource directories list except user home directory and clear resources
+  \brief Set the resource directories (where global confguration files are searched).
+  
+  This function also clears all currently set resources.
+
+  \param dl directories list
 */
 void QtxResourceMgr::setDirList( const QStringList& dl )
 {
@@ -2123,10 +2408,10 @@ void QtxResourceMgr::setDirList( const QStringList& dl )
 }
 
 /*!
-  Sets resource value
-  \param sect - name of section
-  \param name - name of parameter
-  \param val - string representation of value
+  \brief Set parameter value.
+  \param sect section name
+  \param name parameter name
+  \param val parameter value
 */
 void QtxResourceMgr::setResource( const QString& sect, const QString& name, const QString& val )
 {
@@ -2137,10 +2422,22 @@ void QtxResourceMgr::setResource( const QString& sect, const QString& name, cons
 }
 
 /*!
-  \return name of resource file, which is being found in user home directory
-  \param appName - name of application
-  \param for_load - flag indicating that file will be used for loading (true) or for saving(false)
-  It makes possible to use different resource files for loading and saving
+  \brief Get user configuration file name.
+
+  This method can be redefined in the successor class to customize the user configuration file name.
+  User configuration file is always situated in the user's home directory. By default .<appName>rc
+  file is used on Linux (e.g. .MyApprc) and <appName>.<format> under Windows (e.g. MyApp.xml).
+
+  Parameter \a for_load (not used in default implementation) specifies the usage mode, i.e. if
+  user configuration file is opened for reading or writing. This allows customizing a way of application
+  resources initializing (for example, if the user configuraion file includes version number and there is
+  no file corresponding to this version in the user's home directory, it could be good idea to try 
+  the configuration file from the previous versions of the application).
+  
+  \param appName application name
+  \param for_load boolean flag indicating that file is opened for loading or saving (not used) 
+  \return user configuration file name
+  \sa globalFileName()
 */
 QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_load*/ ) const
 {
@@ -2160,7 +2457,16 @@ QString QtxResourceMgr::userFileName( const QString& appName, const bool /*for_l
 }
 
 /*!
-  \return name of resource file, which is being found in all resource directories, except user home
+  \brief Get global configuration file name.
+  
+  This method can be redefined in the successor class to customize the global configuration file name.
+  Global configuration files are searched in the directories specified by the application resources
+  environment variable (e.g. MyAppResources). By default <appName>.<format> file name is used
+  (e.g. MyApp.xml).
+
+  \param appName application name
+  \return global configuration file name
+  \sa userFileName()
 */
 QString QtxResourceMgr::globalFileName( const QString& appName ) const
 {
@@ -2168,10 +2474,13 @@ QString QtxResourceMgr::globalFileName( const QString& appName ) const
 }
 
 /*!
-  Replaced substrings by pattern %A, %B, etc by values from map
+  \brief Perform substitution of the patterns like \%A, \%B, etc by values from the map.
+
+  Used by loadLanguage().
 
-  \param src - string to be processed
-  \param substMap - map of values for replacing
+  \param src sring to be processed
+  \param substMap map of values for replacing
+  \return processed string
 */
 QString QtxResourceMgr::substMacro( const QString& src, const QMap<QChar, QString>& substMap ) const
 {
index 13f116fcdffb1747b2af8aeda6e9222c39841253..b70caa2c545ac4b3c0fc9f412046ada4cf010bf4 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#ifndef QTX_RESOURCEMGR_H
-#define QTX_RESOURCEMGR_H
+// File:      QtxResourceMgr.h
+// Author:    Alexander SOLOVYOV, Sergey TELKOV
+
+#ifndef QTXRESOURCEMGR_H
+#define QTXRESOURCEMGR_H
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qbytearray.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/qtranslator.h>
+#ifndef QTX_NO_INDEXED_MAP
+#include "QtxMap.h"
+#endif
 
-#include <QtGui/qfont.h>
-#include <QtGui/qcolor.h>
-#include <QtGui/qpixmap.h>
+#include <QMap>
+#include <QList>
+#include <QFont>
+#include <QColor>
+#include <QPixmap>
+#include <QByteArray>
+#include <QStringList>
 
-class QPixmap;
+class QTranslator;
 
 #ifdef WIN32
 #pragma warning( disable:4251 )
 #endif
 
-/*!
-  Class: QtxResourceMgr
-*/
-
 class QTX_EXPORT QtxResourceMgr
 {
   class IniFormat;
@@ -50,14 +51,10 @@ class QTX_EXPORT QtxResourceMgr
 public:
   class Format;
 
-  template <class Key, class Value> class IMap;
-  template <class Key, class Value> class IMapIterator;
-  template <class Key, class Value> class IMapConstIterator;
-
 #ifdef QTX_NO_INDEXED_MAP
-  typedef QMap<QString, QString> Section;
+  typedef QMap<QString, QString> Section;   //!< resource section
 #else
-  typedef IMap<QString, QString> Section;
+  typedef IMap<QString, QString> Section;   //!< resource section
 #endif
 
 public:
@@ -165,25 +162,21 @@ private:
   typedef QMap<QString, TransList> TransListMap;
 
 private:
-  QString         myAppName;
-  QStringList     myDirList;
-  FormatList      myFormats;
-  OptionsMap      myOptions;
-  ResList         myResources;
-  bool            myCheckExist;
-  TransListMap    myTranslator;
-  QPixmap         myDefaultPix;
-  bool            myIsPixmapCached;
-
-  bool            myIsIgnoreUserValues;
+  QString         myAppName;                 //!< application name
+  QStringList     myDirList;                 //!< list of resources directories
+  FormatList      myFormats;                 //!< list of formats
+  OptionsMap      myOptions;                 //!< options map
+  ResList         myResources;               //!< resources list
+  bool            myCheckExist;              //!< "check existance" flag
+  TransListMap    myTranslator;              //!< map of loaded translators
+  QPixmap*        myDefaultPix;              //!< default icon
+  bool            myIsPixmapCached;          //!< "cached pixmaps" flag
+
+  bool            myIsIgnoreUserValues;      //!< "ignore user values" flag
 
   friend class QtxResourceMgr::Format;
 };
 
-/*!
-  Class: QtxResourceMgr::Format
-*/
-
 class QTX_EXPORT QtxResourceMgr::Format
 {
 public:
@@ -204,192 +197,8 @@ protected:
   virtual bool           save( const QString&, const QMap<QString, Section>& ) = 0;
 
 private:
-  QString                myFmt;
-  QMap<QString, QString> myOpt;
-};
-
-/*!
-  Class: QtxResourceMgr::IMapIterator
-*/
-
-template <class Key, class Value> class QtxResourceMgr::IMapIterator
-{
-public:
-  IMapIterator()                           : myMap( 0 ), myIndex( 0 )                                   { init(); }
-  IMapIterator( const IMap<Key,Value>* m ) : myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( 0 ) { init(); }
-  IMapIterator( const IMapIterator& i )    : myMap( i.myMap ), myIndex( i.myIndex )                     { init(); }
-
-  bool operator==( const IMapIterator& i ) { return !operator!=( i );                                   }
-  bool operator!=( const IMapIterator& i ) { return !myMap || myMap != i.myMap || myIndex != i.myIndex; }
-  
-  operator bool() const { return myIndex >= 0; }
-
-  const Key&   key() const  { return myMap->key( myIndex );   }
-  Value&       value()       { return myMap->value( myIndex ); }
-  const Value& value() const { return myMap->value( myIndex ); }
-
-  Value& operator*() { return value(); }
-
-  IMapIterator& operator++()      { myIndex++; init(); return *this;                     }
-  IMapIterator  operator++( int ) { IMapIterator i = *this; myIndex++; init(); return i; }
-  IMapIterator& operator--()      { myIndex--; init(); return *this;                     }
-  IMapIterator  operator--( int ) { IMapIterator i = *this; myIndex--; init(); return i; }
-
-private:
-  IMapIterator( const IMap<Key,Value>* m, const int index ) : myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( index ) { init(); }
-  void init() { if ( !myMap || myIndex >= myMap->count() ) myIndex = -1; }
-
-private:
-  IMap<Key,Value>* myMap;
-  int              myIndex;
-
-  friend class IMap<Key, Value>;
-  friend class IMapConstIterator<Key, Value>;
+  QString                myFmt;    //!< format name
+  QMap<QString, QString> myOpt;    //!< options map
 };
 
-/*!
-  Class: QtxResourceMgr::IMapConstIterator
-*/
-
-template <class Key, class Value> class QtxResourceMgr::IMapConstIterator
-{
-public:
-  IMapConstIterator()                                    : myMap( 0 ), myIndex( 0 )                                    { init(); }
-  IMapConstIterator( const IMap<Key,Value>* m )          : myMap( const_cast< IMap<Key,Value>* >( m )  ), myIndex( 0 ) { init(); }
-  IMapConstIterator( const IMapConstIterator& i )        : myMap( i.myMap ), myIndex( i.myIndex )                      { init(); }
-  IMapConstIterator( const IMapIterator<Key, Value>& i ) : myMap( i.myMap ), myIndex( i.myIndex )                      { init(); }
-  
-  bool operator==( const IMapConstIterator& i ) { return !operator!=( i );                                   }
-  bool operator!=( const IMapConstIterator& i ) { return !myMap || myMap != i.myMap || myIndex != i.myIndex; }
-  
-  operator bool() const { return myIndex >= 0; }
-  
-  const Key&   key() const  { return myMap->key( myIndex );   }
-  const Value value() const { return myMap->value( myIndex ); }
-  
-  const Value operator*() const { return value(); }
-
-  IMapConstIterator& operator++()      { myIndex++; init(); return *this;                          }
-  IMapConstIterator  operator++( int ) { IMapConstIterator i = *this; myIndex++; init(); return i; }
-  IMapConstIterator& operator--()      { myIndex--; init(); return *this;                          }
-  IMapConstIterator  operator--( int ) { IMapConstIterator i = *this; myIndex--; init(); return i; }
-  
-private:
-  IMapConstIterator( const IMap<Key,Value>* m, const int index ): myMap( const_cast< IMap<Key,Value>* >( m ) ), myIndex( index ) { init(); }
-  void init() { if ( !myMap || myIndex >= myMap->count() ) myIndex = -1; }
-  
-private:
-  IMap<Key,Value>* myMap;
-  int              myIndex;
-  
-  friend class IMap<Key,Value>;
-};
-
-/*!
-  Class: QtxResourceMgr::IMap
-*/
-
-template <class Key, class Value> class QtxResourceMgr::IMap
-{
-public:
-  typedef IMapIterator<Key,Value>      Iterator;
-  typedef IMapConstIterator<Key,Value> ConstIterator;
-
-public:
-  IMap() {}
-  IMap( const IMap& m ) : myKeys( m.myKeys ), myData( m.myData ) {}
-  IMap& operator=( const IMap& m ) { myKeys = m.myKeys; myData = m.myData; return *this; }
-  
-  int  count() const   { return myData.count(); }
-  int  size() const    { return myData.count(); }
-  bool empty() const   { return myData.empty(); }
-  bool isEmpty() const { return myData.empty(); }
-  
-  void clear() { myKeys.clear(); myData.clear(); }
-  
-  QList<Key>   keys()   const { return myKeys; }
-  QList<Value> values() const { QList<Value> l; for ( int i = 0; i < count(); i++ ) l.append( value( i ) ); return l; }
-  bool         contains ( const Key& key ) const { return myData.contains( key ); }
-  
-  Iterator      begin()       { return Iterator( this );               }
-  Iterator      end()         { return Iterator( this, count() );      }
-  ConstIterator begin() const { return ConstIterator( this );          }
-  ConstIterator end() const   { return ConstIterator( this, count() ); }
-  
-  Iterator insert( const Key& key, const Value& value, bool overwrite = true )
-  { 
-    if ( myData.find( key ) == myData.end() || overwrite )
-    {
-      if ( myData.find( key ) != myData.end() && overwrite )
-        myKeys.removeAt( myKeys.indexOf( key ) );
-      myKeys.append( key );
-      myData[key] = value;
-    }
-    return Iterator( this, index( key ) );
-  }
-
-  Iterator replace( const Key& key, const Value& value )
-  { 
-    if ( myData.find( key ) == myData.end() )
-      myKeys.append( key );
-    myData[ key ] = value;
-    return Iterator( this, index( key ) );
-  }
-
-  int           index( const Key& key ) const { return myKeys.indexOf( key );      }
-  Iterator      at( const int index )         { return Iterator( this, index );      }
-  ConstIterator at( const int index ) const   { return ConstIterator( this, index ); }
-
-  Key& key( const int index )
-  {
-    if ( index < 0 || index >= (int)myKeys.count() ) 
-      return dummyKey;
-    return myKeys[index];
-  }
-
-  Value value( const int index )
-  {
-    if ( index < 0 || index >= (int)myKeys.count() ) 
-      return dummyValue;
-    return myData[ myKeys[index] ];
-  }
-
-  Value operator[]( const Key& key )
-  {
-    if ( myData.find( key ) == myData.end() )
-      insert( key, Value() );
-    return myData[ key ];
-  }
-
-  const Value operator[]( const Key& key ) const
-  {
-    if ( myData.find( key ) == myData.end() )
-      return dummyValue;
-    return myData[key];
-  }
-
-  void erase( Iterator it )     { remove( it );    }
-  void erase( const Key& key )  { remove( key );   }
-  void erase( const int index ) { remove( index ); }
-  void remove( Iterator it )    { if ( it.myMap != this ) return; remove( it.myIndex ); }
-  void remove( const Key& key ) { remove( index( key ) ); }
-  void remove( const int index )
-  {
-    if ( index >= 0 && index < (int)myKeys.count() )
-    {
-      myData.remove( myKeys[index] );
-      myKeys.removeAt( index );
-    }
-  }
-
-private:
-  QList<Key>      myKeys;
-  QMap<Key,Value> myData;
-  Key             dummyKey;
-  Value           dummyValue;
-
-  friend class IMapIterator<Key,Value>;
-  friend class IMapConstIterator<Key,Value>;
-};
-
-#endif
+#endif // QTXRESOURCEMGR_H
diff --git a/src/Qtx/QtxSplash.cxx b/src/Qtx/QtxSplash.cxx
new file mode 100644 (file)
index 0000000..f99e36b
--- /dev/null
@@ -0,0 +1,922 @@
+// 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
+//
+// File:      QtxSplash.cxx
+// Author:    Vadim SANDLER
+
+#include "QtxSplash.h"
+
+#include <QApplication>
+#include <QPainter>
+#include <QMessageBox>
+#include <QDesktopWidget>
+
+/*!
+  \class ProgressEvent
+  \internal
+  \brief Progress change custom event.
+*/
+
+class ProgressEvent: public QEvent
+{
+public:
+  /*!
+    \brief Constructor.
+    \param msg progress message
+    \param progress current progress (for example, in %)
+  */
+  ProgressEvent( const QString& msg, const int progress = 0 )
+    : QEvent( (QEvent::Type)id() ),
+      myMessage( msg ),
+      myProgress( progress )
+  {}
+  /*!
+    \brief Get progress message.
+    \return message
+  */
+  QString    message()  const { return myMessage; } 
+  /*!
+    \brief Get current progress.
+    \return current progress
+  */
+  int        progress() const { return myProgress; }
+  /*!
+    \brief Get message identifier.
+    \return custom message ID
+  */
+  static int id()             { return QEvent::User + 10; }
+
+private:
+  QString myMessage;
+  int     myProgress;
+};
+
+/*!
+  \class QtxSplash
+  \brief The QtxSplash widget provides a splash screen that can be shown during application startup..
+
+  A splash screen is a widget that is usually displayed when an application is being started. 
+  Splash screens are often used for applications that have long start up times to provide 
+  the user with feedback that the application is loading.
+
+  Only one instance of the QtxSplash widget can be created. To access to the splash screen widget,
+  use static method QtxSplash::splash(), which creates and instance of the QtxSplash widget if
+  necessary and returns pointer to it. You should not destroy yhis instance - it is done automatically
+  after application main window is shown. Just use methods finish() to make splash screen wait untill 
+  main window is shown.
+
+  The splash screen appears in the center of the screen. The most common usage is to show a splash 
+  screen before the main widget is displayed on the screen. 
+  For example,
+  \code
+  int main(int argc, char *argv[])
+  {
+    QApplication app(argc, argv);
+    QPixmap pixmap(":/splash.png");
+    QtxSplash* splash = QtxsSplash::splash(pixmap);
+    splash->show();
+    app.processEvents();
+    ... // do application loading and initialization
+    MainWindow window;
+    window.show();
+    splash->finish(&window);
+    return app.exec();
+  }
+  \endcode
+  
+  The user can hide the splash screen by clicking on it with the mouse. Since the splash screen is 
+  typically displayed before the event loop has started running, it is necessary to periodically call 
+  QApplication::processEvents() to receive the mouse clicks.
+  This feature can be switched off by using method setHideOnClick() with \c false parameter.
+
+  It is sometimes useful to update the splash screen with messages and/or progress information, 
+  for example, announcing connections established or modules loaded as the application starts up.
+  QtxSplash class provides the functionality to show status messages and(or) progress bar.
+
+  \code
+  QPixmap pixmap(":/splash.png");
+  QtxSplash* splash = QtxSplash::splash(pixmap);
+  splash->setProgress(0, 5);
+  splash->show();
+  app.processEvents();
+  // doing first step
+  splash->message("Step 1");
+  splash->ress(1);
+  qApp->processEvents();
+  // ... perform some actions
+  // doing second step
+  splash->message("Step 2");
+  splash->setProgress(2);
+  qApp->processEvents();
+  // ... perform some actions
+  ... et cetera
+  \endcode
+
+  There is a static function QtxSplash::setStatus() which allows to put next status message
+  and progress with one call. It can substitue two calls: message() and setProgress().
+
+  QtxSplash class provides alos a lot of functions to set-up its behavior. Set progress
+  bar width with setProgressWidth() method, its position and direction with setProgressFlags().
+  It can be single-colored or gradient-colored. Use setProgressColors() method for this. 
+  You can even set your own gradient scale with QLinearGradient and use it for the progress
+  bar coloring: setProgressGradient().
+
+  To change the progress bar and status message transparency, use setOpacity() function.
+  The methods setTextAlignment(), setTextColor() and setTextColors() can be used to change
+  the attributes of the status message.
+*/
+
+//! The only one instance of splash screen
+QtxSplash* QtxSplash::mySplash = 0;
+
+/*!
+  \brief Constructor.
+  \brief Construct a splash screen that will display the \a pixmap.
+  \param pixmap splash screen pixmap
+*/
+QtxSplash::QtxSplash( const QPixmap& pixmap )
+: QWidget( 0, Qt::SplashScreen | Qt::WindowStaysOnTopHint ),
+  myAlignment( Qt::AlignBottom | Qt::AlignRight ),
+  myColor( Qt::white ),
+  myHideOnClick( false ),
+  myProgress( 0 ),
+  myTotal( 0 ),
+  myStartColor( Qt::red ),
+  myGradientType( Vertical ),
+  myProgressWidth( 10 ),
+  myProgressFlags( BottomSide | LeftToRight ),
+  myMargin( 5 ),
+  myOpacity( 1.0 ),
+  myError( 0 ),
+  myGradientUsed( false )
+{
+  setAttribute( Qt::WA_DeleteOnClose, true );
+  setPixmap( pixmap );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxSplash::~QtxSplash()
+{
+  mySplash = 0;
+}
+
+/*!
+  \brief Get the only instance of the splash screen widget.
+
+  If the splash screen widget does not exist yet, it is created with specified
+  pixmap. Otherwise, pixmap \a px is set to existing widget.
+
+  \param px splash screen pixmap
+  \return splash screen widget
+*/
+QtxSplash* QtxSplash::splash( const QPixmap& px )
+{
+  if ( !mySplash )
+    mySplash = new QtxSplash( px );
+  else if ( !px.isNull() )
+    mySplash->setPixmap( px );
+  return mySplash;
+}
+
+/*!
+  \brief Send the status message and (optionally) current progress 
+  to the splash screen.
+
+  This function can be used, for example, from an external thread
+  which checks the application loading progress.
+
+  \param msg progress status message
+  \param progress current progress
+  \sa message(), setProgress()
+*/
+void QtxSplash::setStatus( const QString& msg, const int progress )
+{
+  if ( mySplash ) {
+    QApplication::postEvent( mySplash, new ProgressEvent( msg, progress ) );
+    QApplication::instance()->processEvents();
+  }
+}
+
+/*!
+  \brief Set error status and show error message box to the user.
+  \param error error message
+  \param title message box title
+  \param code error code
+*/
+void QtxSplash::error( const QString& error, const QString& title, const int code )
+{
+  if ( mySplash ) {
+    mySplash->setError( code );
+    QMessageBox::critical( mySplash, 
+                          title.isEmpty() ? tr( "Error" ) : title,
+                          error,
+                          tr( "&OK" ) );
+  }
+  else {
+    printf( "QtxSplash::error: %s\n",error.toLatin1().constData() );
+  }
+}
+
+/*!
+  \brief Set the pixmap that will be used as the splash screen's image.
+  \param pixmap spash screen image pixmap
+  \sa pixmap()
+*/
+void QtxSplash::setPixmap( const QPixmap& pixmap )
+{
+  if ( pixmap.hasAlpha() ) {
+    QPixmap opaque( pixmap.size() );
+    QPainter p( &opaque );
+    p.fillRect( 0, 0, pixmap.width(), pixmap.height(), palette().background() );
+    p.drawPixmap( 0, 0, pixmap );
+    p.end();
+    myPixmap = opaque;
+  } 
+  else {
+    myPixmap = pixmap;
+  }
+  QRect r( 0, 0, myPixmap.size().width(), myPixmap.size().height() );
+  resize( myPixmap.size() );
+  move( QApplication::desktop()->screenGeometry().center() - r.center() );
+  if ( !isVisible() )
+    drawContents();
+  else
+    repaint();
+}
+
+/*!
+  \brief Get the pixmap that is used as the splash screen's image.
+  \return spash screen image pixmap
+  \sa setPixmap()
+*/
+QPixmap QtxSplash::pixmap() const
+{
+  return myPixmap;
+}
+
+/*!
+  \brief Set/clear the 'hide on mouse click' flag.
+
+  When this flag is set, user can hide the splash screen window
+  by clicking on it with mouse.
+  But for this to work it is necessary to call periodically
+  QApplication::processEvents() in order to allow event loop to process
+  events because usually main application loop is not yet started
+  at that moment.
+
+  By default this flag is set to \c false.
+
+  \param on new flag state
+  \sa hideOnClick()
+*/
+void QtxSplash::setHideOnClick( const bool on )
+{
+  myHideOnClick = on;
+}
+
+/*!
+  \brief Get the 'hide on mouse click' flag.
+  \return 'hide on mouse click' flag
+  \sa setHideOnClick()
+*/
+bool QtxSplash::hideOnClick() const
+{
+  return myHideOnClick;
+}
+
+/*!
+  \brief Set total progress steps to \a total.
+  \param total total number of progress steps
+  \sa totalSteps(), setProgress(), progress()
+*/
+void QtxSplash::setTotalSteps( const int total )
+{
+  myTotal = total;
+  repaint();
+}
+
+/*!
+  \brief Get total progress steps number.
+  \return total number of progress steps
+  \sa setTotalSteps(), setProgress(), progress()
+*/
+int QtxSplash::totalSteps() const
+{
+  return myTotal;
+}
+    
+/*!
+  \brief Set current progress.
+  \param progress current progress
+  \sa progress(), setTotalSteps(), setTotalSteps(), 
+*/
+void QtxSplash::setProgress( const int progress )
+{
+  myProgress = progress > 0 ? progress : 0;
+  repaint();
+}
+
+/*!
+  \brief Get current progress.
+  \return current progress
+  \sa setProgress(), setTotalSteps(), setTotalSteps(), 
+*/
+int QtxSplash::progress() const
+{
+  return myProgress;
+}
+
+/*!
+  \brief Set current progress to \a progress and total number of 
+  progress steps to \a total.
+  \param progress current progress
+  \param total total number of progress steps
+*/
+void QtxSplash::setProgress( const int progress, const int total )
+{
+  myTotal    = total;
+  myProgress = progress > 0 ? progress : 0;
+  repaint();
+}
+
+/*!
+  \brief Set margin (a border width).
+  \param margin new margin width
+  \sa margin()
+*/
+void QtxSplash::setMargin( const int margin )
+{
+  myMargin = margin > 0 ? margin : 0;
+  repaint();
+}
+
+/*!
+  \brief Get margin (a border width).
+  \return current margin width
+  \sa setMargin()
+*/
+int QtxSplash::margin() const
+{
+  return myMargin;
+}
+
+/*!
+  \brief Set progress bar width.
+  \param width new progress bar width
+  \sa progressWidth()
+*/
+void QtxSplash::setProgressWidth( const int width )
+{
+  myProgressWidth = width > 0 ? width : 0;
+  repaint();
+}
+
+/*!
+  \brief Get progress bar width.
+  \return current progress bar width
+  \sa setProgressWidth()
+*/
+int QtxSplash::progressWidth() const
+{
+  return myProgressWidth;
+}
+
+/*!
+  \brief Set progress bar position and direction.
+
+  By default, progress bar is displayed at the bottom side and
+  shows progress from left to right.
+
+  \param flags ORed progress bar flags (QtxSplash::ProgressBarFlags)
+  \sa progressFlags()
+*/
+void QtxSplash::setProgressFlags( const int flags )
+{
+  myProgressFlags = flags;
+  if ( !( myProgressFlags & ( LeftSide | RightSide | TopSide | BottomSide ) ) )
+    myProgressFlags |= BottomSide;
+  if ( !( myProgressFlags & ( LeftToRight | RightToLeft ) ) )
+    myProgressFlags |= LeftToRight ;
+  repaint();
+}
+
+/*!
+  \brief Get progress bar flags: position and direction.
+  \return ORed progress bar flags (QtxSplash::ProgressBarFlags)
+  \sa setProgressFlags()
+*/
+int QtxSplash::progressFlags() const
+{
+  return myProgressFlags;
+}
+
+/*!
+  \brief Set progress bar colors.
+
+  If the colors differ the gradient color bar is drawn.
+  
+  If the \a endColor is not valid, \a startColor is used instead
+  (no gradient coloring).
+  
+  The parameter \a gradientType defines the type of gradient 
+  to be drawn - horizontal or vertical. Default is vertical.
+
+  Note, that methods setProgressGradient() and setProgressColors() are
+  alternative. Only the latest used is taken into account.
+
+  \param startColor start gradient color (or mono-color)
+  \param endColor end gradient color
+  \param gradientType gradient type (QtxSplash::GradientType)
+  \sa progressColors(), setProgressGradient()
+*/
+void QtxSplash::setProgressColors( const QColor&      startColor, 
+                                  const QColor&      endColor,
+                                   const GradientType gradientType )
+{
+  if ( startColor.isValid() )
+    myStartColor = startColor;
+  myEndColor     = endColor;
+  myGradientType = gradientType;
+  myGradientUsed = false;
+  repaint();
+}
+
+/*!
+  \brief Get progress colors and gradient type.
+  \param startColor start gradient color (or mono-color)
+  \param endColor end gradient color
+  \return gradient type (QtxSplash::GradientType)
+  \sa setProgressColors()
+*/
+QtxSplash::GradientType QtxSplash::progressColors( QColor& startColor, 
+                                                  QColor& endColor ) const
+{
+  startColor = myStartColor;
+  endColor   = myEndColor;
+  return myGradientType;
+}
+
+/*!
+  \brief Set custom progress bar colors.
+
+  The gradient start and final stops are scaled to the actual progress
+  bar size. For example:
+  \code
+  QLinearGradient lg(0.5, 0, 1, 1);
+  lg.setColorAt(0.2, Qt::blue);
+  lg.setColorAt(0.6, Qt::red);
+  lg.setSpread(QGradient::RepeatSpread);
+  splash->setProgressGradient(lg);
+  \endcode
+  The above code creates linear gradient, which sets start stop to the
+  center of the progress bar; the final stop is always in the end of
+  the progress bar. The color scale (blue to red) is changed by the 
+  progress bar diagonal.
+
+  Note, that methods setProgressGradient() and setProgressColors() are
+  alternative. Only the latest used is taken into account.
+
+  \param gradient color gradient to be used for progress bar coloring
+  \sa progressGradient(), setProgressColors()
+*/
+void QtxSplash::setProgressGradient( const QLinearGradient& gradient )
+{
+  myGradient = gradient;
+  myGradientUsed = true;
+  repaint();
+}
+
+/*!
+  \brief Get custom progress bar colors.
+  \return color gradient used for progress bar coloring
+  \sa setProgressGradient()
+*/
+QLinearGradient QtxSplash::progressGradient() const
+{
+  return myGradient;
+}
+
+/*!
+  \brief Set progress bar and status text message opacity.
+
+  The value should be in the range 0.0 to 1.0, where 0.0 is fully 
+  transparent and 1.0 is fully opaque.
+
+  \param opacity new opacity value
+  \sa opacity()
+*/
+void QtxSplash::setOpacity( const double opacity )
+{
+  myOpacity = opacity < 0.0 ? 0.0 : ( opacity > 1.0 ? 1.0 : opacity );
+  repaint();
+}
+
+/*!
+  \brief Get progress bar and status text message opacity.
+  \return current opacity value
+  \sa setOpacity()
+*/
+double QtxSplash::opacity() const
+{
+  return myOpacity;
+}
+
+/*!
+  \brief Set message text alignment flags.
+
+  Default flags are Qt::AlignBottom | Qt::AlignRight.
+
+  \param alignment alignment flags (Qt::Alignment)
+  \sa textAlignment()
+*/
+void QtxSplash::setTextAlignment( const int alignment )
+{
+  myAlignment = alignment;
+  repaint();
+}
+
+/*!
+  \brief Get message text alignment flags.
+  \return alignment flags (Qt::Alignment)
+  \sa setTextAlignment()
+*/
+int QtxSplash::textAlignment() const
+{
+  return myAlignment;
+}
+
+/*!
+  \brief Set message text color.
+
+  Default message color is white.
+  
+  \param color message text color
+  \sa setTextColors()
+*/
+void QtxSplash::setTextColor( const QColor& color )
+{
+  if ( myColor.isValid() )
+    myColor = color;
+  myShadowColor = QColor();
+  repaint();
+}
+
+/*!
+  \brief Get message text color.
+  \return color message text color
+  \sa setTextColor()
+*/
+QColor QtxSplash::textColor() const
+{
+  return myColor;
+}
+
+/*!
+  \brief Set message text color and text shadow color.
+  \param color message text color
+  \param shadow message text shadow color
+  \sa textColors(), textColor(), setTextColor()
+*/
+void QtxSplash::setTextColors( const QColor& color, const QColor& shadow )
+{
+  if ( myColor.isValid() )
+    myColor = color;
+  myShadowColor = shadow;
+  repaint();
+}
+
+/*!
+  \brief Get message text color and text shadow color.
+  \param color message text color
+  \param shadow message text shadow color
+  \sa setTextColors(), textColor(), setTextColor()
+*/
+void QtxSplash::textColors( QColor& color, QColor& shadow ) const
+{
+  color  = myColor;
+  shadow = myShadowColor;
+}
+
+/*!
+  \brief Get current status message.
+  \return status message
+*/
+QString QtxSplash::message() const
+{
+  return myMessage;
+}
+
+/*!
+  \brief Get error code.
+
+  This function returns error code, set previoiusly with 
+  error(const QString&, const QString&, const int) method.
+  If no error code has been set, 0 is returned.
+
+  \return last error code
+*/
+int QtxSplash::error() const
+{
+  return myError;
+}
+
+/*!
+  \brief Wait until widget \a mainWin is displayed.
+
+  Makes the splash screen wait until the widget \a mainWin is displayed
+  and then hide and close splash window.
+
+  \param mainWin application main window 
+*/
+void QtxSplash::finish( QWidget* mainWin )
+{
+  if ( mainWin ) {
+#if defined(Q_WS_X11)
+    extern void qt_x11_wait_for_window_manager(QWidget *mainWin);
+    qt_x11_wait_for_window_manager(mainWin);
+#endif
+  }
+  close();
+}
+
+/*!
+  \brief Repaint the splash screen.
+*/
+void QtxSplash::repaint()
+{
+  drawContents();
+  QWidget::repaint();
+  QApplication::flush();
+}
+
+/*!
+  \brief Set status message for the splash screen and define its color 
+  and aligment flags.
+  \param msg status message
+  \param alignment message text alignment flags (Qt::Alignment)
+  \param color message text color
+*/
+void QtxSplash::message( const QString& msg, 
+                        int            alignment,
+                        const QColor&  color )
+{
+  myMessage   = msg;
+  myAlignment = alignment;
+  if ( color.isValid() )
+    myColor = color;
+  repaint();
+}
+
+/*!
+  \overload
+  \brief Set status message for the splash screen.
+  \param msg status message
+*/
+void QtxSplash::message( const QString& msg )
+{
+  myMessage = msg;
+  repaint();
+}
+
+/*!
+  \brief Remove the message being displayed on the splash screen.
+  \sa message()
+*/
+void QtxSplash::clear()
+{
+  myMessage = QString::null;
+  repaint();
+}
+
+/*!
+  \brief Draw the contents of the splash screen.
+  \param painter painter
+*/
+void QtxSplash::drawContents( QPainter* p )
+{
+  // draw progress bar
+  if ( myTotal > 0 ) {
+    p->save();
+    drawProgressBar( p );
+    p->restore();
+  }
+
+  // draw status message
+  if ( !myMessage.isEmpty() ) {
+    p->save();
+    drawMessage( p );
+    p->restore();
+  }
+}
+
+/*!
+  \brief Process mouse button pressing event.
+
+  Hides splash screen if the 'hide on mouse click' flag is set.
+
+  \param me mouse event (not used)
+  \sa hideOnClick(), setHideOnClick()
+*/
+void QtxSplash::mousePressEvent( QMouseEvent* /*me*/ )
+{
+  if ( myHideOnClick )
+    hide();
+}
+
+/*!
+  \brief Customize paint event.
+
+  This function is implemented to work-around the Qt bug
+  on some Linux distribututions when the drawing on the 
+  splash screen widget is not allowed.
+
+  \param pe paint event (not used)
+*/
+void QtxSplash::paintEvent( QPaintEvent* /*pe*/ )
+{
+  QPainter p( this );
+  QPixmap pix = palette().brush( backgroundRole() ).texture();
+  p.drawPixmap( 0, 0, pix );
+}
+
+/*!
+  \brief Process custom event sent by setStatus() method.
+  \param ce custom event
+  \sa setStatus().
+*/
+void QtxSplash::customEvent( QEvent* ce )
+{
+  if ( ce->type() == ProgressEvent::id() ) {
+    ProgressEvent* pe = (ProgressEvent*)ce;
+    pe->message().isEmpty() ? clear() : message( pe->message() );
+    setProgress( pe->progress() );
+    QApplication::instance()->processEvents();
+  }
+}
+
+/*!
+  \brief Draw progress bar.
+  \param p painter
+*/
+void QtxSplash::drawProgressBar( QPainter* p )
+{
+  // get rect, margin, progress bar width
+  QRect r = rect();
+  int m   = margin();
+  int pw  = progressWidth();
+
+  // calculate drawing rect
+  // ... first set default position (if none or wrong position is set)
+  if ( myProgressFlags & BottomSide )
+    r = QRect( r.x() + m, r.height() - (m + pw), r.width() - 2 * m, pw );
+  else if ( myProgressFlags & TopSide )
+    r = QRect( r.x() + m, r.y() + m, r.width() - 2 * m, pw );
+  else if ( myProgressFlags & LeftSide )
+    r = QRect( r.x() + m, r.y() + m, pw, r.height() - 2 * m );
+  else if ( myProgressFlags & RightSide )
+    r = QRect( r.width() - (m + pw), r.y() + m, pw, r.height() - 2 * m );
+
+  QRect cr = r;
+  if ( myProgressFlags & TopSide || myProgressFlags & BottomSide ) {
+    cr.setWidth( (int)( r.width() * ( myProgress > 0 ? myProgress : 0 ) / myTotal ) );
+    if ( myProgressFlags & RightToLeft )
+      cr.translate( r.width() - cr.width(), 0 );
+  }
+  else if ( myProgressFlags & LeftSide || myProgressFlags & RightSide ) {
+    cr.setHeight( (int)( r.height() * ( myProgress > 0 ? myProgress : 0 ) / myTotal ) );
+    if ( myProgressFlags & RightToLeft)
+      cr.translate( 0, r.height() - cr.height() );
+  }
+  int x1, x2, y1, y2;
+  if ( myGradientType == Horizontal ) {
+    x1 = r.left(); x2 = r.right(); y1 = y2 = 0;
+  }
+  else {
+    x1 = x2 = 0; y1 = r.top(); y2 = r.bottom();
+  }
+  QLinearGradient lg;
+  if ( myGradientUsed ) {
+    QPointF start = myGradient.start();
+    QPointF final = myGradient.finalStop();
+    qreal xd = final.x() - start.x();
+    qreal yd = final.y() - start.y();
+    lg.setStart( xd != 0 ? r.left() + r.width() * start.x() / xd : 0, 
+                 yd != 0 ? r.top() + r.height() * start.y() / yd : 0 );
+    lg.setFinalStop( xd != 0 ? r.right() : 0, yd != 0 ? r.bottom() : 0 );
+    lg.setStops( myGradient.stops() );
+    lg.setSpread( myGradient.spread() );
+  }
+  else {
+    lg.setStart( x1, y1 );
+    lg.setFinalStop( x2, y2 );
+    lg.setColorAt( 0, myStartColor );
+    lg.setColorAt( 1, myEndColor.isValid() ? myEndColor : myStartColor );
+  }
+  p->setOpacity( myOpacity );
+  p->setClipRect( cr );
+  p->fillRect( r, lg ); 
+  p->setClipping( false );
+
+  // draw progress bar outline rectangle
+  p->setPen( palette().color( QPalette::Dark ) );
+  p->drawLine( r.left(), r.top(), r.right(), r.top() );
+  p->drawLine( r.left(), r.top(), r.left(), r.bottom() );
+  p->setPen( palette().color( QPalette::Light ) );
+  p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() );
+  p->drawLine( r.right(), r.top(), r.right(), r.bottom() );
+}
+
+/*!
+  \brief Draw status message.
+  \param p painter
+*/
+void QtxSplash::drawMessage( QPainter* p )
+{
+  // get rect, margin, progress bar width
+  QRect r = rect();
+  int m   = margin();
+  int pw  = progressWidth();
+
+  // calculate drawing rect
+  QFontMetrics f( font() );
+  int spacing = f.lineSpacing();
+  // ... base rect
+  QRect r1( r.x() + m, r.y() + m, r.width() - 2 * m, r.height() - 2 * m );
+  r1.setY( r1.y() - f.leading() );
+  // ... take into account progress bar
+  if ( 1 ) {              // if ( myTotal > 0 ) : vsr changed: otherwise text is jumping
+    if ( myProgressFlags & BottomSide )
+      r1.setHeight( r1.height() - pw );
+    else if ( myProgressFlags & TopSide )
+      r1.setY( r1.y() + pw );
+    else if ( myProgressFlags & LeftSide )
+      r1.setX( r1.x() + pw );
+    else if ( myProgressFlags & RightSide )
+      r1.setWidth( r1.width() - pw );
+  }
+  
+  // ... take into account trailing '\n' symbols
+  int shift = 0;
+  int i = myMessage.length() - 1;
+  while( i >= 0 && myMessage[ i-- ] == '\n' )
+    shift += spacing;
+  r1.setHeight( r1.height() - shift );
+
+  p->setOpacity( myOpacity );
+
+  // draw shadow status text
+  if ( myShadowColor.isValid() ) {
+    QRect r2 = r1;
+    if ( myAlignment & Qt::AlignLeft   ) r2.setLeft  ( r2.left()   + 1 );
+    if ( myAlignment & Qt::AlignTop    ) r2.setTop   ( r2.top()    + 1 );
+    if ( myAlignment & Qt::AlignRight  ) r2.setRight ( r2.right()  + 1 );
+    if ( myAlignment & Qt::AlignBottom ) r2.setBottom( r2.bottom() + 1 );
+    p->setPen( myShadowColor );
+    p->drawText( r2, myAlignment, myMessage );
+  }
+
+  // draw foreground status text
+  p->setPen( myColor );
+  p->drawText( r1, myAlignment, myMessage );
+}
+
+/*!
+  \brief Draw the splash screen window contents.
+*/
+void QtxSplash::drawContents()
+{
+  QPixmap textPix = myPixmap;
+  QPainter painter( &textPix );
+  painter.initFrom( this );
+  drawContents( &painter );
+  QPalette pal = palette();
+  pal.setBrush( backgroundRole(), QBrush( textPix ) );
+  setPalette( pal );
+}
+
+/*!
+  \brief Sets error code.
+  \param code error code
+*/
+void QtxSplash::setError( const int code )
+{
+  myError = code;
+}
+
diff --git a/src/Qtx/QtxSplash.h b/src/Qtx/QtxSplash.h
new file mode 100644 (file)
index 0000000..bd95211
--- /dev/null
@@ -0,0 +1,158 @@
+// 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
+//
+// File:      QtxSplash.h
+// Author:    Vadim SANDLER
+
+#ifndef QTXSPLASH_H
+#define QTXSPLASH_H
+
+#include "Qtx.h"
+
+#include <QWidget>
+#include <QPixmap>
+#include <QLinearGradient>
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxSplash : public QWidget
+{
+  Q_OBJECT
+
+private:
+  QtxSplash( const QPixmap& );
+
+public:
+  //! Gradient type
+  typedef enum { 
+    Horizontal, //!< horizontal
+    Vertical    //!< vertical
+  } GradientType;
+  
+  //! Progress bar position and direction
+  typedef enum {
+    LeftSide     = 0x0001,      //!< progress bar is displayed at the left side
+    RightSide    = 0x0002,      //!< progress bar is displayed at the right side
+    TopSide      = 0x0004,      //!< progress bar is displayed at the top side
+    BottomSide   = 0x0008,      //!< progress bar is displayed at the bottom side
+    LeftToRight  = 0x0010,      //!< show progress from left to right (from top to bottom)
+    RightToLeft  = 0x0020       //!< show progress from right to left (from bottom to top)
+  } ProgressBarFlags;
+  
+  virtual ~QtxSplash();
+  
+  static QtxSplash* splash( const QPixmap& = QPixmap() );
+  
+  static void       setStatus( const QString&, const int = 0 );
+  static void       error( const QString&, const QString& = QString::null, const int = -1 );
+  
+  void              setPixmap( const QPixmap& );
+  QPixmap           pixmap() const;
+  
+  void              setHideOnClick( const bool );
+  bool              hideOnClick() const;
+  
+  void              setTotalSteps( const int );
+  int               totalSteps() const;
+  
+  void              setProgress( const int );
+  void              setProgress( const int, const int );
+  int               progress() const;
+  
+  void              setMargin( const int );
+  int               margin() const;
+  
+  void              setProgressWidth( const int );
+  int               progressWidth() const; 
+  
+  void              setProgressFlags( const int );
+  int               progressFlags() const;
+  
+  void              setProgressColors( const QColor&, 
+                                      const QColor& = QColor(),
+                                      const GradientType = Vertical );
+  GradientType      progressColors( QColor&, QColor& ) const;
+  
+  void              setProgressGradient( const QLinearGradient& );
+  QLinearGradient   progressGradient() const;
+  
+  void              setOpacity( const double );
+  double            opacity() const;
+  
+  void              setTextAlignment( const int );
+  int               textAlignment() const;
+  
+  void              setTextColor( const QColor& );
+  QColor            textColor() const;
+  void              setTextColors( const QColor&, const QColor& = QColor() );
+  void              textColors( QColor&, QColor& ) const;
+  
+  QString           message() const;
+  
+  int               error() const;
+  
+  void              finish( QWidget* );
+  void              repaint();
+  
+public slots:
+  void              message( const QString&, 
+                            const int,
+                            const QColor& = QColor() );
+  void              message( const QString& );
+  void              clear();
+  
+protected:
+  virtual void      mousePressEvent( QMouseEvent* );
+  virtual void      customEvent( QEvent* );
+  virtual void      paintEvent( QPaintEvent* );
+
+  virtual void      drawContents( QPainter* );
+  
+  virtual void      drawProgressBar( QPainter* );
+  virtual void      drawMessage( QPainter* );
+
+private:
+  void              drawContents();
+  void              setError( const int );
+
+private:
+  static QtxSplash* mySplash;
+  
+  QPixmap           myPixmap;           //!< splash pixmap
+  QString           myMessage;          //!< current status message
+  int               myAlignment;        //!< text alignment flags (Qt::Alignment)
+  QColor            myColor;            //!< text color
+  QColor            myShadowColor;      //!< text shadow color
+  bool              myHideOnClick;      //!< 'hide on click' flag
+  int               myProgress;         //!< current progress
+  int               myTotal;            //!< total progress steps
+  QColor            myStartColor;       //!< progress bar gradient starting color
+  QColor            myEndColor;         //!< progress bar gradient ending color
+  GradientType      myGradientType;     //!< progress bar gradient direction
+  QLinearGradient   myGradient;         //!< progress bar custom gradient
+  int               myProgressWidth;    //!< progress bar width
+  int               myProgressFlags;    //!< progress bar flags (QtxSplash::ProgressBarFlags)
+  int               myMargin;           //!< margin (for progress bar and status message)
+  double            myOpacity;          //!< progress bar / status message opacity
+  int               myError;            //!< error code
+  bool              myGradientUsed;     //!< 'use custom gradient color scale' flag
+};
+
+#endif
index f436f68a7191444f6a6288318df36085016b4ab1..50972d29a0e915055e42800a936f08ee3d2e4e1e 100644 (file)
 
 #include "QtxToolBar.h"
 
-#include <QtGui/qaction.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qmainwindow.h>
-#include <QtGui/qapplication.h>
+#include <QAction>
+#include <QMainWindow>
+#include <QApplication>
 
 /*!
-    Class: QtxToolBar::Watcher [Internal]
-    Descr: Internal object with event filter.
+  \class QtxToolBar::Watcher
+  \internal
+  \brief Internal class which goal is to watch parent toolbar state changing.
 */
 
 class QtxToolBar::Watcher : public QObject
@@ -38,7 +37,7 @@ public:
   Watcher( QtxToolBar* );
 
   void         shown( QtxToolBar* );
-  void         hided( QtxToolBar* );
+  void         hidden( QtxToolBar* );
 
   virtual bool eventFilter( QObject*, QEvent* );
 
@@ -64,18 +63,15 @@ private:
 };
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param cont toolbar to be watched
 */
 QtxToolBar::Watcher::Watcher( QtxToolBar* cont )
 : QObject( cont ),
-myCont( cont ),
-myState( true ),
-myEmpty( false )
+  myCont( cont ),
+  myState( true ),
+  myEmpty( false )
 {
-/*
-  if ( myCont->mainWindow() )
-    myState = myCont->mainWindow()->appropriate( myCont );
-*/
   myCont->installEventFilter( this );
   myVisible = myCont->isVisibleTo( myCont->parentWidget() );
 
@@ -83,7 +79,10 @@ myEmpty( false )
 }
 
 /*!
-  Custom event filter
+  \brief Custom event filter.
+  \param o event receiver object
+  \param e event sent to object
+  \return \c true if further event processing should be stopped
 */
 bool QtxToolBar::Watcher::eventFilter( QObject* o, QEvent* e )
 {
@@ -107,7 +106,8 @@ bool QtxToolBar::Watcher::eventFilter( QObject* o, QEvent* e )
 }
 
 /*!
-  Sets internal visibility state to true
+  \brief Set internal status to "shown"
+  \param tb toolbar
 */
 void QtxToolBar::Watcher::shown( QtxToolBar* tb )
 {
@@ -118,9 +118,10 @@ void QtxToolBar::Watcher::shown( QtxToolBar* tb )
 }
 
 /*!
-  Sets internal visibility state to false
+  \brief Set internal status to "hidden"
+  \param tb toolbar
 */
-void QtxToolBar::Watcher::hided( QtxToolBar* tb )
+void QtxToolBar::Watcher::hidden( QtxToolBar* tb )
 {
   if ( tb != myCont )
     return;
@@ -129,7 +130,7 @@ void QtxToolBar::Watcher::hided( QtxToolBar* tb )
 }
 
 /*!
-  Shows corresponding QtxToolBar
+  \brief Show the toolbar being watched
 */
 void QtxToolBar::Watcher::showContainer()
 {
@@ -143,7 +144,7 @@ void QtxToolBar::Watcher::showContainer()
 }
 
 /*!
-  Hides corresponding QtxToolBar
+  \brief Hide the toolbar being watched
 */
 void QtxToolBar::Watcher::hideContainer()
 {
@@ -157,7 +158,8 @@ void QtxToolBar::Watcher::hideContainer()
 }
 
 /*!
-  Event handler of custom events
+  \brief Proces custom events.
+  \param e custom event
 */
 void QtxToolBar::Watcher::customEvent( QEvent* e )
 {
@@ -165,13 +167,18 @@ void QtxToolBar::Watcher::customEvent( QEvent* e )
   {
   case Install:
     installFilters();
+    break;
   case Update:
     updateVisibility();
+    break;
+  default:
+    break;
   }
 }
 
 /*!
-  Installs event filters
+  \brief Install this object as event dilter to all children widgets
+         of the toolbar being watched.
 */
 void QtxToolBar::Watcher::installFilters()
 {
@@ -187,7 +194,8 @@ void QtxToolBar::Watcher::installFilters()
 }
 
 /*!
-  Update visibility state
+  \brief Update visibility state of all children widgets of the toolbar
+         being watched.
 */
 void QtxToolBar::Watcher::updateVisibility()
 {
@@ -196,18 +204,14 @@ void QtxToolBar::Watcher::updateVisibility()
 
   bool vis = false;
 
-  const QObjectList& objList = myCont->children();
-  for ( QObjectList::const_iterator it = objList.begin(); it != objList.end() && !vis; ++it )
-  {
-    QObject* obj = *it;
-    if ( !obj->isWidgetType() || !qstrcmp( "qt_dockwidget_internal", obj->objectName().toLatin1() ) )
-      continue;
+  QList<QAction*> actList = myCont->actions();
 
-    if ( obj->inherits( "QToolBarHandle" ) || obj->inherits( "QToolBarExtension" ) )
+  for ( QList<QAction*>::const_iterator it = actList.begin(); it != actList.end() && !vis; ++it )
+  {
+    if ( (*it)->isSeparator() )
       continue;
 
-    QWidget* wid = (QWidget*)*it;
-    vis = wid->isVisibleTo( wid->parentWidget() );
+    vis = (*it)->isVisible();
   }
 
   QMainWindow* mw = myCont->mainWindow();
@@ -229,94 +233,84 @@ void QtxToolBar::Watcher::updateVisibility()
 }
 
 /*!
-  Constructor
+  \class QtxToolBar
+  \brief Enhanced toolbar class.
+*/
+
+/*!
+  \brief Constructor.
+  \param watch if \c true the event filter is installed to watch toolbar state changes 
+         to update it properly
+  \param label toolbar title
+  \param parent parent widget
 */
 QtxToolBar::QtxToolBar( const bool watch, const QString& label, QWidget* parent )
 : QToolBar( label, parent ),
-myWatcher( 0 ),
-myStretch( false )
+  myWatcher( 0 ),
+  myStretch( false )
 {
   if ( watch )
     myWatcher = new Watcher( this );
+
+  if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
+    mw->addToolBar( this );
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param label toolbar title
+  \param parent parent widget
 */
 QtxToolBar::QtxToolBar( const QString& label, QWidget* parent )
 : QToolBar( label, parent ),
-myWatcher( 0 ),
-myStretch( false )
+  myWatcher( 0 ),
+  myStretch( false )
 {
+  if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
+    mw->addToolBar( this );
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param watch if \c true the event filter is installed to watch toolbar state changes 
+         to update it properly
+  \param parent parent widget
 */
 QtxToolBar::QtxToolBar( const bool watch, QWidget* parent )
 : QToolBar( parent ),
-myWatcher( 0 ),
-myStretch( false )
+  myWatcher( 0 ),
+  myStretch( false )
 {
   if ( watch )
     myWatcher = new Watcher( this );
+
+  if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
+    mw->addToolBar( this );
 }
 
 /*!
-  Constructor
+  \brief Constructor.
+  \param parent parent widget
 */
 QtxToolBar::QtxToolBar( QWidget* parent )
 : QToolBar( parent ),
-myWatcher( 0 ),
-myStretch( false )
+  myWatcher( 0 ),
+  myStretch( false )
 {
+  if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
+    mw->addToolBar( this );
 }
 
 /*!
-  Destructor
+  \brief Destructor.
 */
 QtxToolBar::~QtxToolBar()
 {
 }
 
 /*!
-  \return the recommended size for the widget
-*/
-QSize QtxToolBar::sizeHint() const
-{
-  QSize sz = QToolBar::sizeHint();
-/*
-  if ( place() == InDock && isStretchable() && area() )
-  {
-    if ( orientation() == Horizontal )
-      sz.setWidth( area()->width() );
-    else
-      sz.setHeight( area()->height() );
-  }
-*/
-  return sz;
-}
-
-/*!
-  \return the recommended minimum size for the widget
-*/
-QSize QtxToolBar::minimumSizeHint() const
-{
-  QSize sz = QToolBar::minimumSizeHint();
-/*
-  if ( place() == InDock && isStretchable() && area() )
-  {
-    if ( orientation() == Horizontal )
-      sz.setWidth( area()->width() );
-    else
-      sz.setHeight( area()->height() );
-  }
-*/
-  return sz;
-}
-
-/*!
-  Shows toolbar
+  \brief Show/hide the toolbar.
+  \param on new visibility state
 */
 void QtxToolBar::setVisible( bool visible )
 {
@@ -325,14 +319,15 @@ void QtxToolBar::setVisible( bool visible )
     if ( visible )
       myWatcher->shown( this );
     else
-      myWatcher->hided( this );
+      myWatcher->hidden( this );
   }
 
   QToolBar::setVisible( visible );
 }
 
 /*!
-  Returns the main window
+  \brief Get parent main window.
+  \return main window pointer
 */
 QMainWindow* QtxToolBar::mainWindow() const
 {
@@ -345,3 +340,11 @@ QMainWindow* QtxToolBar::mainWindow() const
   }
   return mw;
 }
+
+bool QtxToolBar::event( QEvent* e )
+{
+  if ( e->type() == QEvent::WindowTitleChange && objectName().isEmpty() )
+    setObjectName( windowTitle() );
+
+  return QToolBar::event( e );
+}
index e1757edf3ce6b6b03ba651040bc75bf49505c73a..56207f26bfc322c1021da41f04366b8883c60808 100644 (file)
 // File:      QtxToolBar.h
 // Author:    Sergey TELKOV
 
+#ifndef QTXTOOLBAR_H
+#define QTXTOOLBAR_H
+
 #include "Qtx.h"
 
-#include <QtGui/qtoolbar.h>
+#include <QToolBar>
 
 class QTX_EXPORT QtxToolBar : public QToolBar
 {
@@ -36,15 +39,17 @@ public:
   QtxToolBar( QWidget* = 0 );
   virtual ~QtxToolBar();
 
-  virtual QSize sizeHint() const;
-  virtual QSize minimumSizeHint() const;
-
   QMainWindow*  mainWindow() const;
 
 public slots:
   virtual void  setVisible( bool );
 
+protected:
+  virtual bool  event( QEvent* );
+
 private:
-  Watcher*      myWatcher;
-  bool          myStretch;
+  Watcher*      myWatcher;   //!< watcher object
+  bool          myStretch;   //!< stretching toolbar flag (not used)
 };
+
+#endif // QTXTOOLBAR_H
diff --git a/src/Qtx/QtxToolTip.cxx b/src/Qtx/QtxToolTip.cxx
new file mode 100755 (executable)
index 0000000..e7888a4
--- /dev/null
@@ -0,0 +1,272 @@
+// 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
+//
+// File:      QtxToolTip.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxToolTip.h"
+
+#include <QFont>
+#include <QTimer>
+#include <QCursor>
+#include <QFontMetrics>
+#include <QApplication>
+#include <QPalette>
+#include <QMouseEvent>
+
+#define TOOLTIP_SHOW_DELAY 0500
+#define TOOLTIP_HIDE_DELAY 7000
+
+/*!
+  Constructor
+*/
+QtxToolTip::QtxToolTip( QWidget* parent )
+: QLabel( parent, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::Tool | Qt::WindowStaysOnTopHint | Qt::Window )
+{
+  setObjectName( "" );
+  setIndent( 3 );
+  setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
+  QPalette palette;
+  palette.setColor( backgroundRole(), QColor( 255, 255, 231 ) );
+  setPalette( palette );
+
+       myWidgetRegion = QRect( -1, -1, -1, -1 );
+
+       setFrameShape( QFrame::Panel );
+       setFrameShadow( QFrame::Plain );
+
+  parent->setMouseTracking( true );
+       parent->installEventFilter( this );
+       installEventFilter( this );
+
+       mySleepTimer = new QTimer( this );
+        mySleepTimer->setSingleShot( true );
+       myWakeUpTimer = new QTimer( this );
+        myWakeUpTimer->setSingleShot( true );
+       connect( mySleepTimer,  SIGNAL( timeout() ), this, SLOT( onSleepTimeOut()  ) );
+       connect( myWakeUpTimer, SIGNAL( timeout() ), this, SLOT( onWakeUpTimeOut() ) );
+
+  myWakeUpDelayTime = 700;
+  myShowDelayTime = 5000;
+}
+
+/*!
+  Destructor
+*/
+QtxToolTip::~QtxToolTip()
+{
+}
+
+/*!
+  Custom event filter
+*/
+bool QtxToolTip::eventFilter( QObject* o, QEvent* e )
+{
+       if ( ( e->type() == QEvent::Destroy ) || ( e->type() == QEvent::Close ) || ( e->type() == QEvent::Hide ) )
+       {
+               hideTip();
+       }
+       if ( e->type() == QEvent::Leave )
+       {
+               if ( isVisible() && ( o == this ) )
+                       hideTip();
+               myWakeUpTimer->stop();
+       }
+       if ( e->type() == QEvent::MouseMove )
+       {
+               QMouseEvent* me = (QMouseEvent*)e;
+               QPoint thePos = parentWidget()->mapFromGlobal( me->globalPos() );
+               if ( myWakeUpTimer->isActive() )
+               {
+                       myWakeUpTimer->stop();
+                       myWakeUpTimer->start( myWakeUpDelayTime );
+               }
+               if ( isVisible() )
+               {
+                       if ( !myWidgetRegion.contains( thePos ) )
+      {
+                               hideTip();
+        myWidgetRegion = QRect( -1, -1, -1, -1 );
+      }
+               }
+               else
+               {
+                       if ( !myWidgetRegion.isValid() || myWidgetRegion.contains( thePos ) )
+                               myWakeUpTimer->start( myWakeUpDelayTime );
+               }
+       }
+       if ( e->type() == QEvent::KeyPress )
+       {
+               hideTip();
+       }
+       if ( o == parent() && ( e->type() == QEvent::MouseButtonPress ||
+                          e->type() == QEvent::MouseButtonRelease ) )
+       {
+               hideTip();
+       }
+       return false;
+}
+
+/*!
+  Shows tool tip
+  \param aPos - position
+  \param text - tooltip text
+  \param aWidgetRegion - rectangle
+*/
+void QtxToolTip::showTip( const QPoint& aPos, const QString& text, const QRect& aWidgetRegion )
+{
+       QFontMetrics theFM = fontMetrics();
+       int theHeight = theFM.height();
+       int theWidth = theFM.width( text ) + 2;
+       showTip( QRect( QPoint( aPos.x(), aPos.y() + 10 ), QSize( theWidth, theHeight ) ), text, aWidgetRegion );
+}
+
+/*!
+  Shows tool tip
+  \param aRegion - tooltip region
+  \param text - tooltip text
+  \param aWidgetRegion - widget rectangle
+*/
+void QtxToolTip::showTip( const QRect& aRegion, const QString& text, const QRect& aWidgetRegion )
+{
+       setText( text );
+       myWidgetRegion = aWidgetRegion;
+       setGeometry( aRegion );
+       if ( myShowDelayTime != 0 )
+               mySleepTimer->start( myShowDelayTime );
+       show();
+}
+
+/*!
+  Hides tooltip
+*/
+void QtxToolTip::hideTip()
+{
+       hide();
+  myWidgetRegion = QRect( -1, -1, -1, -1 );
+       mySleepTimer->stop();
+}
+
+/*!
+  It is called when there is a possibility that a tool tip should be shown and
+  must decide whether there is a tool tip for the point p in the widget that this QToolTip object relates to
+  \param pos - position
+*/
+void QtxToolTip::maybeTip( const QPoint& pos )
+{
+       QString text;
+       QRect textRegion, theRegion( -1, -1, -1, -1 );
+       QFont theFnt = font();
+
+    emit maybeTip( pos, text, theFnt, textRegion, theRegion );
+
+    if ( theRegion.isValid() )
+       {
+               setFont( theFnt );
+               int margin = lineWidth() + indent();
+               QRect dspRegion( QPoint( textRegion.x() - margin, textRegion.y() ),
+                                        QSize( textRegion.width() + 2 * margin, textRegion.height() ) );
+               QRect tipRegion( parentWidget()->mapToGlobal( dspRegion.topLeft() ), dspRegion.size() );
+               if ( tipRegion.left() < 0 )
+                       tipRegion.translate( -1 * tipRegion.left(), 0 );
+               showTip( tipRegion, text, theRegion );
+       }
+}
+
+/*!
+  SLOT: called when sleep time is out
+*/
+void QtxToolTip::onSleepTimeOut()
+{
+       mySleepTimer->stop();
+       hideTip();
+}
+
+/*!
+  SLOT: called when wake time is out
+*/
+void QtxToolTip::onWakeUpTimeOut()
+{
+       myWakeUpTimer->stop();
+  QPoint pos = QCursor::pos();
+  if ( parentWidget() )
+    pos = parentWidget()->mapFromGlobal( pos );
+  maybeTip( pos );
+}
+
+/*!
+  Custom mouse press event handler
+*/
+void QtxToolTip::mousePressEvent( QMouseEvent* e )
+{
+       hideTip();
+       QWidget* reciever = parentWidget();
+       QMouseEvent* me = new QMouseEvent( QEvent::MouseButtonPress,
+                                                                          reciever->mapFromGlobal( e->globalPos() ),
+                                                                          e->button(), e->buttons(), Qt::KeypadModifier );
+       QApplication::sendEvent( reciever, me );
+}
+
+/*!
+  Custom mouse double click event handler
+*/
+void QtxToolTip::mouseDoubleClickEvent( QMouseEvent* e )
+{
+       hideTip();
+       QWidget* reciever = parentWidget();
+       QMouseEvent* me = new QMouseEvent( QEvent::MouseButtonDblClick,
+                                                                          reciever->mapFromGlobal( e->globalPos() ),
+                                                                          e->button(), e->buttons(), Qt::KeypadModifier );
+       QApplication::sendEvent( reciever, me );
+}
+
+/*!
+  Sets wake delay time
+  \param theTime
+*/
+void QtxToolTip::setWakeUpDelayTime( int theTime )
+{
+  if( !(theTime < 0) )
+    myWakeUpDelayTime = theTime;
+}
+
+/*!
+  Sets show delay time
+  \param theTime
+*/
+void QtxToolTip::setShowDelayTime( int theTime )
+{
+  if( !(theTime < 0) )
+    myShowDelayTime = theTime;
+}
+
+/*!
+  \return timer measuring time of sleeping
+*/
+QTimer* QtxToolTip::sleepTimer() const
+{
+  return mySleepTimer;
+}
+
+/*!
+  \return timer measuring time of waking up
+*/
+QTimer* QtxToolTip::wakeUpTimer() const
+{
+  return myWakeUpTimer;
+}
diff --git a/src/Qtx/QtxToolTip.h b/src/Qtx/QtxToolTip.h
new file mode 100755 (executable)
index 0000000..d558f9c
--- /dev/null
@@ -0,0 +1,78 @@
+// 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
+//
+// File:      QtxToolTip.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXTOOLTIP_H
+#define QTXTOOLTIP_H
+
+#include "Qtx.h"
+
+#include <QLabel>
+
+class QTimer;
+
+class QTX_EXPORT QtxToolTip : public QLabel
+{
+       Q_OBJECT
+
+public:
+       QtxToolTip( QWidget* = 0 );
+       virtual ~QtxToolTip();
+
+       void          hideTip();
+  
+       virtual void  showTip( const QPoint& aPos,
+                         const QString& text, const QRect& aWidgetRegion );
+       virtual void  showTip( const QRect& aRegion,
+                         const QString& text, const QRect& aWidgetRegion );
+
+       virtual bool  eventFilter( QObject* o, QEvent* e );
+
+  void          setWakeUpDelayTime( int );
+  void          setShowDelayTime( int );
+
+  int           wakeUpDelayTime() const { return myWakeUpDelayTime; }
+  int           showDelayTime() const { return myShowDelayTime; }
+
+signals:
+  void          maybeTip( QPoint, QString&, QFont&, QRect&, QRect& );
+
+protected slots:
+       void          onSleepTimeOut();
+       void          onWakeUpTimeOut();
+
+protected:
+       virtual void  maybeTip( const QPoint& );
+       virtual void  mousePressEvent( QMouseEvent* );
+       virtual void  mouseDoubleClickEvent( QMouseEvent* );
+
+  QTimer*       sleepTimer() const;
+  QTimer*       wakeUpTimer() const;
+
+private:
+       QTimer*       myWakeUpTimer;
+       QTimer*       mySleepTimer;
+       QRect         myWidgetRegion;
+
+  int           myShowDelayTime;
+  int           myWakeUpDelayTime;
+};
+
+#endif
diff --git a/src/Qtx/QtxValidator.cxx b/src/Qtx/QtxValidator.cxx
new file mode 100644 (file)
index 0000000..6909865
--- /dev/null
@@ -0,0 +1,136 @@
+// 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
+//
+// File:      QtxValidator.cxx
+// Author:    Alexandre SOLOVYOV
+
+#include "QtxValidator.h"
+
+/*!
+  \class QtxIntValidator
+  \brief Validator for integer numbers with possibility to fix up the invalid value.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent object
+*/
+QtxIntValidator::QtxIntValidator( QObject* parent )
+: QIntValidator( parent )
+{
+}
+
+/*!
+  \brief Constructor.
+  \param bot minimum possible value
+  \param top maximum possible value
+  \param parent parent object
+*/
+QtxIntValidator::QtxIntValidator( const int bot, const int top, QObject* parent )
+: QIntValidator( bot, top, parent )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxIntValidator::~QtxIntValidator()
+{
+}
+
+/*!
+  \brief Validate the input and fixup it if necessary.
+
+  If the string represents integer value less then minimum value, it becomes equal to the minimum.
+  if the string represents integer value more then mazimum value, it becomes equal to the maximum.
+  If the string is not evaluated as integer it becomes equal to \c 0.
+
+  \param str the string to be validated
+*/
+void QtxIntValidator::fixup( QString& str ) const
+{
+  bool ok = false;
+  int i = str.toInt( &ok );
+  if ( ok )
+  {
+    if ( i < bottom() )
+      str = QString::number( bottom() );
+    else if( i > top() )
+      str = QString::number( top() );
+  }
+  else
+    str = QString ( "0" );
+}
+
+/*!
+  \class QtxDoubleValidator
+  \brief Validator for double numbers with possibility to fix up the invalid value.
+*/
+
+/*!
+  \brief Constructor
+  \param parent parent object
+*/
+QtxDoubleValidator::QtxDoubleValidator( QObject* parent )
+: QDoubleValidator( parent )
+{
+}
+
+/*!
+  \brief Constructor.
+  \param bot minimum possible value
+  \param top maximum possible value
+  \param dec precision (number of digits after dot)
+  \param parent parent object
+*/
+QtxDoubleValidator::QtxDoubleValidator( const double bot, const double top,
+                                       const int dec, QObject* parent )
+: QDoubleValidator( bot, top, dec, parent )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxDoubleValidator::~QtxDoubleValidator()
+{
+}
+
+/*!
+  \brief Validate the input and fixup it if necessary.
+
+  If the string represents double value less then minimum value, it becomes equal to the minimum.
+  if the string represents double value more then mazimum value, it becomes equal to the maximum.
+  If the string is not evaluated as double it becomes equal to \c 0.
+
+  \param str the string to be validated
+*/
+void QtxDoubleValidator::fixup( QString& str ) const
+{
+  bool ok = false;
+  double d = str.toDouble( &ok );
+  if ( ok )
+  {
+    if ( d < bottom() )
+      str = QString::number( bottom() );
+    else if ( d > top() )
+      str = QString::number( top() );
+  }
+  else
+    str = QString( "0" );
+}
diff --git a/src/Qtx/QtxValidator.h b/src/Qtx/QtxValidator.h
new file mode 100644 (file)
index 0000000..b6a6103
--- /dev/null
@@ -0,0 +1,53 @@
+// 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
+//
+// File:      QtxValidator.h
+// Author:    Alexandre SOLOVYOV
+
+#ifndef QTXVALIDATOR_H
+#define QTXVALIDATOR_H
+
+#include "Qtx.h"
+
+#include <QValidator>
+
+class QTX_EXPORT QtxIntValidator : public QIntValidator
+{
+  Q_OBJECT
+
+public:
+  QtxIntValidator( QObject* );
+  QtxIntValidator( const int, const int, QObject* );
+  virtual ~QtxIntValidator();
+
+  virtual void fixup( QString& ) const;
+};
+
+class QTX_EXPORT QtxDoubleValidator : public QDoubleValidator
+{
+  Q_OBJECT
+
+public:
+  QtxDoubleValidator( QObject* );
+  QtxDoubleValidator( const double, const double, const int, QObject* );
+  virtual ~QtxDoubleValidator();
+
+  virtual void fixup( QString& ) const;
+};
+
+#endif // QTXVALIDATOR_H
diff --git a/src/Qtx/QtxWorkspace.cxx b/src/Qtx/QtxWorkspace.cxx
new file mode 100644 (file)
index 0000000..dd303ed
--- /dev/null
@@ -0,0 +1,137 @@
+// 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
+//
+// File:      QtxWorkspace.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxWorkspace.h"
+
+#include <QWidgetList>
+
+/*!
+  \class QtxWorkspace
+  \brief A workspace widget which can be used in the MDI application
+         as top-level widget in the application main window.
+
+  Provides methods to tile child windows in horizontal or vertical
+  direction.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+QtxWorkspace::QtxWorkspace( QWidget* parent )
+: QWorkspace( parent )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxWorkspace::~QtxWorkspace()
+{
+}
+
+/*!
+  \brief Tiles child windows vertically.
+*/
+void QtxWorkspace::tileVertical()
+{
+  QWidgetList winList = windowList();
+  if ( winList.isEmpty() )
+    return;
+  
+  int count = 0;
+  for ( QWidgetList::const_iterator itr = winList.begin(); itr != winList.end(); ++itr )
+    if ( !( (*itr)->windowState() & Qt::WindowMinimized ) )
+      count++;
+
+  if ( !count )
+    return;
+
+  if ( activeWindow() && ( activeWindow()->windowState() & Qt::WindowMaximized ) )
+    activeWindow()->showNormal();
+
+  int y = 0;
+  int heightForEach = height() / count;
+  for ( QWidgetList::iterator it = winList.begin(); it != winList.end(); ++it )
+  {
+    QWidget* win = *it;
+    if ( win->windowState() & Qt::WindowMinimized )
+      continue;
+    
+    if ( win->windowState() & Qt::WindowMaximized )
+    {
+      win->hide();
+      win->showNormal();
+    }
+    
+//    QApplication::sendPostedEvents( 0, QEvent::ShowNormal );
+
+    int prefH = win->minimumHeight() + win->parentWidget()->baseSize().height();
+    int actualH = qMax( heightForEach, prefH );
+
+    win->parentWidget()->setGeometry( 0, y, width(), actualH );
+    y += actualH;
+  }
+}
+
+/*!
+  \brief Tiles child windows horizontally.
+*/
+void QtxWorkspace::tileHorizontal()
+{
+  QWidgetList winList = windowList();
+  if ( winList.isEmpty() )
+    return;
+
+  int count = 0;
+  for ( QWidgetList::const_iterator itr = winList.begin(); itr != winList.end(); ++itr )
+    if ( !( (*itr)->windowState() & Qt::WindowMinimized ) )
+      count++;
+
+  if ( !count )
+    return;
+
+  if ( activeWindow() && activeWindow()->windowState() & Qt::WindowMaximized )
+    activeWindow()->showNormal();
+  
+  int x = 0;
+  int widthForEach = width() / count;
+  for ( QWidgetList::iterator it = winList.begin(); it != winList.end(); ++it )
+  {
+    QWidget* win = *it;
+    if ( win->windowState() & Qt::WindowMinimized )
+      continue;
+    
+    if ( win->windowState() & Qt::WindowMaximized )
+    {
+      win->hide();
+      win->showNormal();
+    }
+
+//    QApplication::sendPostedEvents( 0, QEvent::ShowNormal );
+
+    int prefW = win->minimumWidth();
+    int actualW = qMax( widthForEach, prefW );
+    
+    win->parentWidget()->setGeometry( x, 0, actualW, height() );
+    x += actualW;
+  }
+}
diff --git a/src/Qtx/QtxWorkspace.h b/src/Qtx/QtxWorkspace.h
new file mode 100644 (file)
index 0000000..224d729
--- /dev/null
@@ -0,0 +1,50 @@
+// 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
+//
+// File:      QtxWorkspace.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXWORKSPACE_H
+#define QTXWORKSPACE_H
+
+#include "Qtx.h"
+
+#include <QWorkspace>
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxWorkspace : public QWorkspace
+{
+  Q_OBJECT
+
+public:
+  QtxWorkspace( QWidget* = 0 );
+  virtual ~QtxWorkspace();
+
+public slots:
+  void        tileVertical();
+  void        tileHorizontal();
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
diff --git a/src/Qtx/QtxWorkspaceAction.cxx b/src/Qtx/QtxWorkspaceAction.cxx
new file mode 100644 (file)
index 0000000..938b438
--- /dev/null
@@ -0,0 +1,413 @@
+// 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
+//
+// File:      QtxWorkspaceAction.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxWorkspaceAction.h"
+
+#include "QtxWorkspace.h"
+
+#include <QMenu>
+#include <QWidgetList>
+
+/*!
+  \class QtxWorkspaceAction
+  \brief Implements actions group for menu Windows with standard operations, like
+         "Cascade", "Tile", "Tile Horizontally", etc.
+*/
+
+/*!
+  \brief Constructor.
+  \param ws parent workspace
+  \param parent parent object (owner of the action)
+*/
+QtxWorkspaceAction::QtxWorkspaceAction( QtxWorkspace* ws, QObject* parent )
+: QtxActionSet( parent ),
+  myWorkspace( ws ),
+  myWindowsFlag( true )
+{
+  insertAction( new QtxAction( tr( "Arranges the windows as overlapping tiles" ),
+                               tr( "Cascade" ), 0, this ), Cascade );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping tiles" ),
+                               tr( "Tile" ), 0, this ), Tile );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping horizontal tiles" ),
+                               tr( "Tile horizontally" ), 0, this ), HTile );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping vertical tiles" ),
+                               tr( "Tile vertically" ), 0, this ), VTile );
+
+  connect( this, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
+
+  setMenuActions( Standard );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxWorkspaceAction::~QtxWorkspaceAction()
+{
+}
+
+/*!
+  \brief Get workspace.
+  \return parent workspace
+*/
+QtxWorkspace* QtxWorkspaceAction::workspace() const
+{
+  return myWorkspace;
+}
+
+/*!
+  \brief Set actions to be visible in the menu.
+  
+  Actions, which IDs are set in \a flags parameter, will be shown in the 
+  menu bar. Other actions will not be shown.
+
+  \param flags ORed together actions flags
+*/
+void QtxWorkspaceAction::setMenuActions( const int flags )
+{
+  action( Cascade )->setVisible( flags & Cascade );
+  action( Tile )->setVisible( flags & Tile );
+  action( VTile )->setVisible( flags & VTile );
+  action( HTile )->setVisible( flags & HTile );
+  myWindowsFlag = flags & Windows;
+}
+
+/*!
+  \brief Get menu actions which are currently visible in the menu bar.
+  \return ORed together actions flags
+  \sa setMenuActions()
+*/
+int QtxWorkspaceAction::menuActions() const
+{
+  int ret = 0;
+  ret = ret | ( action( Cascade )->isVisible() ? Cascade : 0 );
+  ret = ret | ( action( Tile )->isVisible() ? Tile : 0 );
+  ret = ret | ( action( VTile )->isVisible() ? VTile : 0 );
+  ret = ret | ( action( HTile )->isVisible() ? HTile : 0 );
+  ret = ret | ( myWindowsFlag ? Windows : 0 );
+  return ret;
+}
+
+/*!
+  \brief Get keyboard accelerator for the specified action.
+  \param id menu action ID
+  \return keyboard accelerator of menu item or 0 if there is no such action
+*/
+int QtxWorkspaceAction::accel( const int id ) const
+{
+  int a = 0;
+  if ( action( id ) )
+    a = action( id )->shortcut();
+  return a;
+}
+
+/*!
+  \brief Get icon for the specified action.
+
+  If \a id is invalid, null icon is returned.
+
+  \param id menu action ID
+  \return menu item icon
+*/
+QIcon QtxWorkspaceAction::icon( const int id ) const
+{
+  QIcon ico;
+  if ( action( id ) )
+    ico = action( id )->icon();
+  return ico;
+}
+
+/*!
+  \brief Get menu item text for the specified action.
+  \param id menu action ID
+  \return menu item text or null QString if there is no such action
+*/
+QString QtxWorkspaceAction::text( const int id ) const
+{
+  QString txt;
+  if ( action( id ) )
+    txt = action( id )->text();
+  return txt;
+}
+
+/*!
+  \brief Get status bar tip for the specified action.
+  \param id menu action ID
+  \return status bar tip menu item or null QString if there is no such action
+*/
+QString QtxWorkspaceAction::statusTip( const int id ) const
+{
+  QString txt;
+  if ( action( id ) )
+    txt = action( id )->statusTip();
+  return txt;
+}
+
+/*!
+  \brief Set keyboard accelerator for the specified action.
+  \param id menu action ID
+  \param a new keyboard accelerator
+*/
+void QtxWorkspaceAction::setAccel( const int id, const int a )
+{
+  if ( action( id ) )
+    action( id )->setShortcut( a );
+}
+
+/*!
+  \brief Set menu item icon for the specified action.
+  \param id menu action ID
+  \param ico new menu item icon
+*/
+void QtxWorkspaceAction::setIcon( const int id, const QIcon& icon )
+{
+  if ( action( id ) )
+    action( id )->setIcon( icon );
+}
+
+/*!
+  \brief Set menu item text for the specified action.
+  \param id menu action ID
+  \param txt new menu item text
+*/
+void QtxWorkspaceAction::setText( const int id, const QString& txt )
+{
+  if ( action( id ) )
+    action( id )->setText( txt );
+}
+
+/*!
+  \brief Set menu item status bar tip for the specified action.
+  \param id menu action ID
+  \param txt new menu item status bar tip
+*/
+void QtxWorkspaceAction::setStatusTip( const int id, const QString& txt )
+{
+  if ( action( id ) )
+    action( id )->setStatusTip( txt );
+}
+
+/*!
+  \brief Process action activated by the user.
+  \param type action ID
+*/
+void QtxWorkspaceAction::perform( const int type )
+{
+  switch ( type )
+  {
+  case Cascade:
+    cascade();
+    break;
+  case Tile:
+    tile();
+    break;
+  case VTile:
+    tileVertical();
+    break;
+  case HTile:
+    tileHorizontal();
+    break;
+  }
+}
+
+/*!
+  \brief Tile child windows in the workspace.
+*/
+void QtxWorkspaceAction::tile()
+{
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tile();
+}
+
+/*!
+  \brief Cascade child windows in the workspace.
+*/
+void QtxWorkspaceAction::cascade()
+{
+  QtxWorkspace* ws = workspace();
+  if ( !ws )
+    return;
+
+  ws->cascade();
+
+       int w = ws->width();
+       int h = ws->height();
+
+       QWidgetList winList = ws->windowList();
+  for ( QWidgetList::iterator it = winList.begin(); it != winList.end(); ++it )
+               (*it)->resize( int( w * 0.8 ), int( h * 0.8 ) );
+}
+
+/*!
+  \brief Tile child windows in the workspace in the vertical direction.
+*/
+void QtxWorkspaceAction::tileVertical()
+{
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tileVertical();
+}
+
+/*!
+  \brief Tile child windows in the workspace in the horizontal direction.
+*/
+void QtxWorkspaceAction::tileHorizontal()
+{
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tileHorizontal();
+}
+
+/*!
+  \brief Called when action is added to the menu bar.
+  \param w menu bar widget this action is being added to
+*/
+void QtxWorkspaceAction::addedTo( QWidget* w )
+{
+  QtxActionSet::addedTo( w );
+
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
+    connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
+}
+
+/*!
+  \brief Called when action is removed from the menu bar.
+  \param w menu bar widget this action is being removed from
+*/
+void QtxWorkspaceAction::removedFrom( QWidget* w )
+{
+  QtxActionSet::removedFrom( w );
+
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
+    disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
+}
+
+/*!
+  \brief Update all menu action state.
+*/
+void QtxWorkspaceAction::updateContent()
+{
+  bool count = workspace() ? workspace()->windowList().count() : 0;
+  action( Cascade )->setEnabled( count );
+  action( Tile )->setEnabled( count );
+  action( HTile )->setEnabled( count );
+  action( VTile )->setEnabled( count );
+
+  updateWindows();
+}
+
+/*!
+  \brief Update actions which refer to the opened child windows.
+*/
+void QtxWorkspaceAction::updateWindows()
+{
+  QtxWorkspace* ws = workspace();
+  if ( !ws )
+    return;
+
+  QList<QAction*> lst = actions();
+  for ( QList<QAction*>::iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    int id = actionId( *it );
+    if ( id >= Windows )
+      removeAction( *it );
+  }
+
+  bool base = action( Cascade )->isVisible() || action( Tile )->isVisible() ||
+              action( HTile )->isVisible() || action( VTile )->isVisible();
+
+  QList<QAction*> items;
+  QMap<QAction*, int> map;
+  if ( menuActions() & Windows )
+  {
+    int index = 1;
+    QWidgetList wList = ws->windowList();
+    for ( QWidgetList::iterator it = wList.begin(); it != wList.end(); ++it, index++ )
+    {
+      QWidget* wid = *it;
+      QAction* a = new QtxAction( wid->windowTitle(), wid->windowTitle(), 0, this, true );
+      a->setChecked( wid == ws->activeWindow() );
+      items.append( a );
+      map.insert( a, Windows + index );
+    }
+
+    if ( base && !items.isEmpty() )
+    {
+      QAction* sep = new QtxAction( this );
+      sep->setSeparator( true );
+      items.prepend( sep );
+      map.insert( sep, Windows );
+    }
+  }
+
+  if ( !items.isEmpty() )
+    insertActions( items );
+
+  for ( QMap<QAction*, int>::const_iterator itr = map.begin(); itr != map.end(); ++itr )
+    setActionId( itr.key(), itr.value() );
+}
+
+/*!
+  \brief Called when parent menu is about to show.
+
+  Updates all menu items.
+*/
+void QtxWorkspaceAction::onAboutToShow()
+{
+  QMenu* pm = ::qobject_cast<QMenu*>( sender() );
+  if ( pm )
+    updateContent();
+}
+
+/*!
+  \brief Called when menu item corresponding to some child window is activated.
+
+  Activates correposponding child window.
+
+  \param idx menu item index
+*/
+void QtxWorkspaceAction::activateItem( const int idx )
+{
+  QtxWorkspace* ws = workspace();
+  if ( !ws )
+    return;
+
+  QWidgetList wList = ws->windowList();
+  if ( idx >= 0 && idx < (int)wList.count() )
+    wList.at( idx )->setFocus();
+}
+
+/*!
+  \brief Called when menu item is activated by the user.
+  
+  Perform the corresponding action.
+
+  \param id menu item identifier
+*/
+void QtxWorkspaceAction::onTriggered( int id )
+{
+  if ( id < Windows )
+    perform( id );
+  else
+    activateItem( id - Windows - 1 );
+}
diff --git a/src/Qtx/QtxWorkspaceAction.h b/src/Qtx/QtxWorkspaceAction.h
new file mode 100644 (file)
index 0000000..a4ade9c
--- /dev/null
@@ -0,0 +1,97 @@
+// 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
+//
+// File:      QtxWorkspaceAction.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXWORKSPACEACTION_H
+#define QTXWORKSPACEACTION_H
+
+#include "QtxActionSet.h"
+
+class QtxWorkspace;
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxWorkspaceAction : public QtxActionSet
+{
+  Q_OBJECT
+
+public:
+  //! Actions (menu items) ID
+  enum { Cascade    = 0x0001,   //!< "Cascade child windows" operation
+         Tile       = 0x0002,   //!< "Tile child windows" operation
+         VTile      = 0x0004,   //!< "Tile child windows vertically" operation
+         HTile      = 0x0008,   //!< "Tile child windows horizontally" operation
+         Windows    = 0x0010,   //!< A list of child windows menu items
+         Standard   = Cascade | Tile | Windows,
+         Operations = Cascade | Tile | VTile | HTile,
+         All        = Standard | HTile | VTile };
+
+public:
+  QtxWorkspaceAction( QtxWorkspace*, QObject* = 0 );
+  virtual ~QtxWorkspaceAction();
+
+  QtxWorkspace* workspace() const;
+
+  int           menuActions() const;
+  void          setMenuActions( const int );
+
+  QIcon         icon( const int ) const;
+  QString       text( const int ) const;
+  int           accel( const int ) const;
+  QString       statusTip( const int ) const;
+
+  void          setAccel( const int, const int );
+  void          setIcon( const int, const QIcon& );
+  void          setText( const int, const QString& );
+  void          setStatusTip( const int, const QString& );
+
+  void          perform( const int );
+
+public slots:
+  void          tile();
+  void          cascade();
+  void          tileVertical();
+  void          tileHorizontal();
+
+private slots:
+  void          onAboutToShow();
+  void          onTriggered( int );
+
+protected:
+  virtual void  addedTo( QWidget* );
+  virtual void  removedFrom( QWidget* );
+
+private:
+  void          updateContent();
+  void          updateWindows();
+  void          activateItem( const int );
+
+private:
+  QtxWorkspace* myWorkspace;       //!< parent workspace
+  bool          myWindowsFlag;     //!< "show child windows items" flag
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif
index e98cd5123880bbd52ebbced142435167b3497df7..0d72eb2ec2e8eeecf7d50acfe88633b5e591ae37 100644 (file)
@@ -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
 
 #include "QtxAction.h"
 
-#include <QtCore/qregexp.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qicon.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qstyle.h>
-#include <QtGui/qimage.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qpainter.h>
-#include <QtGui/qsplitter.h>
-#include <QtGui/qrubberband.h>
-#include <QtGui/qpushbutton.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qinputdialog.h>
-#include <QtGui/qstackedwidget.h>
+#include <QRegExp>
+#include <QMenu>
+#include <QFocusEvent>
+#include <QMouseEvent>
+#include <QStyle>
+#include <QLayout>
+#include <QSplitter>
+#include <QRubberBand>
+#include <QPushButton>
+#include <QApplication>
+#include <QInputDialog>
+#include <QStackedWidget>
 
 #define DARK_COLOR_LIGHT 250
 
 /*!
-  Constructor
+  \class QtxWorkstackArea::WidgetEvent
+  \internal
+  \brief Internal class used to forward child widgets events to the workarea
 */
-QtxWorkstack::QtxWorkstack( QWidget* parent )
-: QWidget( parent ),
-myWin( 0 ),
-myArea( 0 ),
-myWorkWin( 0 ),
-myWorkArea( 0 )
+
+class QtxWorkstackArea::WidgetEvent : public QEvent
 {
-  myActionsMap.insert( SplitVertical,   new QtxAction( QString(), tr( "Split vertically" ), 0, this ) );
-  myActionsMap.insert( SplitHorizontal, new QtxAction( QString(), tr( "Split horizontally" ), 0, this ) );
-  myActionsMap.insert( Close,           new QtxAction( QString(), tr( "Close" ), 0, this ) );
-  myActionsMap.insert( Rename,          new QtxAction( QString(), tr( "Rename" ), 0, this ) );
+public:
+  WidgetEvent( Type t, QWidget* w = 0 ) : QEvent( t ), myWidget( w ) {};
 
-  connect( myActionsMap[SplitVertical], SIGNAL( triggered( bool ) ), this, SLOT( splitVertical() ) );
-  connect( myActionsMap[SplitHorizontal], SIGNAL( triggered( bool ) ), this, SLOT( splitHorizontal() ) );
-  connect( myActionsMap[Close], SIGNAL( triggered( bool ) ), this, SLOT( onCloseWindow() ) );
-  connect( myActionsMap[Rename], SIGNAL( triggered( bool ) ), this, SLOT( onRename() ) );
+  QWidget* widget() const { return myWidget; }
 
-  QVBoxLayout* base = new QVBoxLayout( this );
-  base->setMargin( 0 );
+private:
+  QWidget* myWidget;   // event receiver widget
+};
 
-  mySplit = new QSplitter( this );
-  mySplit->setChildrenCollapsible( false );
-  base->addWidget( mySplit );
-}
+/*!
+  \class QtxWorkstackDrag
+  \internal
+  \brief Workstack drag object
+*/
 
 /*!
-  Destructor
+  \brief Constructor.
+  \param ws parent workstack
+  \param child child widget container
 */
-QtxWorkstack::~QtxWorkstack()
+QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child )
+: QObject( 0 ),
+  myWS( ws ),
+  myChild( child ),
+  myTab( -1 ),
+  myArea( 0 ),
+  myTabRect( 0 ),
+  myAreaRect( 0 )
 {
+  QApplication::instance()->installEventFilter( this );
 }
 
 /*!
-  \return list of all widgets in all areas
+  \brief Destructor.
 */
-QWidgetList QtxWorkstack::windowList() const
+QtxWorkstackDrag::~QtxWorkstackDrag()
 {
-  QList<QtxWorkstackArea*> lst;
-  areas( mySplit, lst, true );
-
-  QWidgetList widList;
-  for ( QList<QtxWorkstackArea*>::iterator it = lst.begin(); it != lst.end(); ++it )
-  {
-    QWidgetList wids = (*it)->widgetList();
-    for ( QWidgetList::iterator itr = wids.begin(); itr != wids.end(); ++itr )
-      widList.append( *itr );
-  }
+  QApplication::instance()->removeEventFilter( this );
 
-  return widList;
+  endDrawRect();
 }
 
 /*!
-  \return list of all widgets in active area
+  \brief Custom event filter.
+  \param o event receiver widget
+  \param e event
+  \return \c true if event should be filtered (stop further processing)
 */
-QWidgetList QtxWorkstack::splitWindowList() const
+bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e )
 {
-  return myArea ? myArea->widgetList() : QWidgetList();
+  switch ( e->type() )
+  {
+  case QEvent::MouseMove:
+    updateTarget( ((QMouseEvent*)e)->globalPos() );
+    break;
+  case QEvent::MouseButtonRelease:
+    drawRect();
+    endDrawRect();
+    dropWidget();
+    deleteLater();
+    break;
+  default:
+    return false;
+  }
+  return true;
 }
 
 /*!
-  \return active widget
+  \brief Detect and set dropping target widget.
+  \param p current dragging position
 */
-QWidget* QtxWorkstack::activeWindow() const
+void QtxWorkstackDrag::updateTarget( const QPoint& p )
 {
-  return myWin;
+  int tab = -1;
+  QtxWorkstackArea* area = detectTarget( p, tab );
+  setTarget( area, tab );
 }
 
 /*!
-  Splits widgets
-  \param o - orientation (Qt::Orientation)
+  \brief Detect dropping target.
+  \param p current dragging position
+  \param tab resulting target tab page index
+  \return target workarea or 0 if there is no correct drop target
 */
-void QtxWorkstack::split( const int o )
+QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const
 {
-  QtxWorkstackArea* area = myWorkArea;
-  if ( !area )
-    area = activeArea();
-  if ( !area )
-    return;
-
-  if ( area->widgetList().count() < 2 )
-    return;
-
-  QWidget* curWid = area->activeWidget();
-  if ( !curWid )
-    return;
-
-  QSplitter* s = splitter( area );
-  QList<QtxWorkstackArea*> areaList;
-  areas( s, areaList );
-
-  QList<QSplitter*> splitList;
-  splitters( s, splitList );
-
-  QSplitter* trg = 0;
-  if ( areaList.count() + splitList.count() < 2 || s->orientation() == o )
-    trg = s;
+  if ( p.isNull() )
+    return 0;
 
-  if ( !trg )
-    trg = wrapSplitter( area );
+  QtxWorkstackArea* area = myWS->areaAt( p );
+  if ( area )
+    tab = area->tabAt( p );
+  return area;
+}
 
-  if ( !trg )
+/*!
+  \brief Set dropping target.
+  \param area new target workarea
+  \param tab target workarea's tab page index
+*/
+void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab )
+{
+  if ( !area || ( myArea == area && tab == myTab ) )
     return;
 
-  trg->setOrientation( (Qt::Orientation)o );
+  startDrawRect();
 
-  QtxWorkstackArea* newArea = createArea( 0 );
-  trg->insertWidget( trg->indexOf( area ) + 1, newArea );
+  if ( myArea )
+    drawRect();
 
-  area->removeWidget( curWid );
-  newArea->insertWidget( curWid );
+  myTab = tab;
+  myArea = area;
 
-  distributeSpace( trg );
+  if ( myArea )
+    drawRect();
+}
 
-  curWid->show();
-  curWid->setFocus();
+/*!
+  \brief Called when drop operation is finished.
+  
+  Inserts dropped widget to the target workarea.
+*/
+void QtxWorkstackDrag::dropWidget()
+{
+  if ( myArea )
+    myArea->insertWidget( myChild->widget(), myTab );
 }
 
 /*!
- \brief Split workarea of the given widget on two parts.
- \param wid  - widget, belonging to this workstack
- \param o    - orientation of splitting (Qt::Horizontal or Qt::Vertical)
- \param type - type of splitting, see <VAR>SplitType</VAR> enumeration
+  \brief Draw floating rectangle.
 */
-void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType type )
+void QtxWorkstackDrag::drawRect()
 {
-  if (!wid) return;
+  if ( !myArea )
+    return;
 
-  // find area of the given widget
-  QtxWorkstackArea* area = NULL;
-  QList<QtxWorkstackArea*> allAreas;
-  areas(mySplit, allAreas, true);
+  QRect r = myArea->floatRect();
+  int m = 2;
 
-  
-  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it )
+  r.setTop( r.top() + m + 2 );
+  r.setLeft( r.left() + m + 2 );
+  r.setRight( r.right() - m - 2 );
+  r.setBottom( r.bottom() - m - 2 );
+
+  if ( myAreaRect )
   {
-    if ( (*it)->contains( wid ) )
-      area = *it;
+    myAreaRect->setGeometry( r );
+    myAreaRect->setVisible( r.isValid() );
   }
 
-  if ( !area )
-    return;
-
-  QWidgetList wids = area->widgetList();
-  if ( wids.count() < 2 )
-    return;
+  QRect tr = myArea->floatTab( myTab );
 
-  QSplitter* s = splitter( area );
-  QList<QtxWorkstackArea*> areaList;
-  areas( s, areaList );
+  tr.setTop( tr.top() + m );
+  tr.setLeft( tr.left() + m );
+  tr.setRight( tr.right() - m );
+  tr.setBottom( tr.bottom() - m );
 
-  QList<QSplitter*> splitList;
-  splitters(s, splitList);
+  if ( myTabRect )
+  {
+    myTabRect->setGeometry( tr );
+    myTabRect->setVisible( tr.isValid() );
+  }
+}
 
-  QSplitter* trg = 0;
-  if (areaList.count() + splitList.count() < 2 || s->orientation() == o)
-    trg = s;
+/*!
+  \brief Delete rubber band on the end on the dragging operation.
+*/
+void QtxWorkstackDrag::endDrawRect()
+{
+  delete myAreaRect;
+  myAreaRect = 0;
 
-  if (!trg) trg = wrapSplitter(area);
-  if (!trg) return;
+  delete myTabRect;
+  myTabRect = 0;
+}
 
-  trg->setOrientation(o);
+/*!
+  \brief Create rubber band to be drawn on the dragging operation.
+*/
+void QtxWorkstackDrag::startDrawRect()
+{
+  if ( !myTabRect )
+    myTabRect = new QRubberBand( QRubberBand::Rectangle );
 
-  QtxWorkstackArea* newArea = createArea(0);
-  insertWidget(newArea, trg, area);
+  myTabRect->hide();
 
-  switch ( type )
-  {
-  case SPLIT_STAY:
-    for ( QWidgetList::iterator itr = wids.begin(); itr != wids.end(); ++itr )
-    {
-      QWidget* wid_i = *itr;
-      if ( wid_i != wid )
-      {
-        area->removeWidget( wid_i );
-        newArea->insertWidget( wid_i );
-      }
-    }
-    break;
-  case SPLIT_AT:
-    {
-      QWidgetList::iterator itr = wids.begin();
-      for ( ; itr != wids.end() && *itr != wid; ++itr )
-      {
-      }
-      for ( ; itr != wids.end(); ++itr )
-      {
-        area->removeWidget( *itr );
-        newArea->insertWidget( *itr );
-      }
-    }
-    break;
-  case SPLIT_MOVE:
-    area->removeWidget( wid );
-    newArea->insertWidget( wid );
-    break;
-  }
+  if ( !myAreaRect )
+    myAreaRect = new QRubberBand( QRubberBand::Rectangle );
 
-  distributeSpace( trg );
+  myAreaRect->hide();
 }
 
 /*!
- \brief Move widget(s) from source workarea into target workarea
-        or just reorder widgets inside one workarea.
- \param wid1 - widget from target workarea
- \param wid2 - widget from source workarea
- \param all  - if this parameter is TRUE, all widgets from source workarea will
-               be moved into the target one, else only the \a wid2 will be moved
+  \class QtxWorkstackArea
+  \internal
+  \brief Workstack widget workarea.
+*/
 
- Move \a wid2 in target workarea. Put it right after \a wid1.
- If value of boolean argument is TRUE, all widgets from source workarea
- will be moved together with \a wid2, source workarea will be deleted.
- If \a wid1 and \a wid2 belongs to one workarea, simple reordering will take place.
+/*!
+  \brief Constructor.
+  \param parent parent widget
 */
-void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all )
+QtxWorkstackArea::QtxWorkstackArea( QWidget* parent )
+: QFrame( parent )
 {
-  if ( !wid1 || !wid2 )
-    return;
+  setFrameStyle( QFrame::Panel | QFrame::Sunken );
 
-  // find area of the widgets
-  QtxWorkstackArea *area1 = 0, *area2 = 0;
-  QList<QtxWorkstackArea*> allAreas;
-  areas( mySplit, allAreas, true );
-  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !( area1 && area2 ); ++it )
-  {
-    if ( (*it)->contains( wid1 ) )
-      area1 = *it;
+  QVBoxLayout* base = new QVBoxLayout( this );
+  base->setMargin( frameWidth() );
 
-    if ( (*it)->contains( wid2 ) )
-      area2 = *it;
-  }
+  QWidget* top = new QWidget( this );
+  base->addWidget( top );
 
-  if ( !area1 || !area2 )
-    return;
+  QHBoxLayout* tl = new QHBoxLayout( top );
+  tl->setMargin( 0 );
 
-  QWidget* curWid = area1->activeWidget();
-  if ( !curWid )
-    return;
+  myBar = new QtxWorkstackTabBar( top );
+  tl->addWidget( myBar, 1 );
 
-  if ( area1 == area2 )
-  {
-    if ( all )
-    {
-      // Set wid1 at first position, wid2 at second
-      area1->insertWidget( wid1 );
-      area1->insertWidget( wid2, 1 );
-    }
-    else
-    {
-      // Set wid2 right after wid1
-      area1->removeWidget( wid2 );
-      int wid1_ind = 0;
-      QWidgetList wids1 = area1->widgetList();
-      for ( QWidgetList::iterator itr1 = wids1.begin(); itr1 != wids1.end() && *itr1 != wid1; ++itr1, ++wid1_ind );
-      area1->insertWidget( wid2, wid1_ind + 1 );
-    }
-  }
-  else
-  {
-    int wid1_ind = 0;
-    QWidgetList wids1 = area1->widgetList();
-    for ( QWidgetList::iterator itr1 = wids1.begin(); itr1 != wids1.end() && *itr1 != wid1; ++itr1, ++wid1_ind );
-    if ( all )
-    {
-      // Set wid2 right after wid1, other widgets from area2 right after wid2
-      QWidgetList wids2 = area2->widgetList();
-      QWidgetList::iterator itr2 = wids2.begin();
-      for ( int ind = wid1_ind + 1; itr2 != wids2.end(); ++itr2, ++ind )
-      {
-        area2->removeWidget( *itr2 );
-        if ( *itr2 == wid2 )
-          area1->insertWidget( *itr2, wid1_ind + 1 );
-        else
-          area1->insertWidget( *itr2, ind );
-      }
-    }
-    else
-    {
-      // Set wid2 right after wid1
-      area2->removeWidget( wid2 );
-      area1->insertWidget( wid2, wid1_ind + 1 );
-    }
-  }
+  QPushButton* close = new QPushButton( top );
+  close->setIcon( style()->standardIcon( QStyle::SP_TitleBarCloseButton ) );
+  close->setAutoDefault( true );
+  close->setFlat( true );
+  myClose = close;
+  tl->addWidget( myClose );
 
-  area1->setActiveWidget( curWid );
+  myStack = new QStackedWidget( this );
+
+  base->addWidget( myStack, 1 );
+
+  connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) );
+  connect( myBar, SIGNAL( currentChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) );
+  connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) );
+  connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) );
+
+  updateState();
+
+  updateActiveState();
+
+  QApplication::instance()->installEventFilter( this );
 }
 
-static void setSizes (QIntList& szList, const int item_ind,
-                      const int new_near, const int new_this, const int new_farr)
+/*!
+  \brief Destructor.
+*/
+QtxWorkstackArea::~QtxWorkstackArea()
 {
-  // set size to all items before an item # <item_ind>
-  int cur_pos = 0;
-  QIntList::iterator its = szList.begin();
-  for (; its != szList.end() && cur_pos < item_ind; ++its, ++cur_pos) {
-    *its = new_near;
-  }
-  if (its == szList.end()) return;
-  // set size to item # <item_ind>
-  *its = new_this;
-  ++its;
-  // set size to all items after an item # <item_ind>
-  for (; its != szList.end(); ++its) {
-    *its = new_farr;
-  }
+  QApplication::instance()->removeEventFilter( this );
 }
 
 /*!
-* \brief Set position of the widget relatively its splitter.
-* \param wid - widget to set position of
-* \param pos - position relatively splitter. Value in range [0..1].
-*
-* Orientation of positioning will correspond to the splitter orientation.
+  \brief Check if workarea contains visible widgets.
+  \return \c true if area is empty (all child widgets are removed or now shown)
 */
-void QtxWorkstack::SetRelativePositionInSplitter( QWidget* wid, const double position )
+bool QtxWorkstackArea::isEmpty() const
 {
-  if ( position < 0.0 || 1.0 < position)
-    return;
+  bool res = false;
+  for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it )
+    res = it.value().vis;
+  return !res;
+}
 
+/*!
+  \brief Add widget to the workarea.
+  \param wid widget to be added
+  \param idx position in the area widget to be added to
+  \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 )
+{
   if ( !wid )
-    return;
+    return 0;
 
-  // find area of the given widget
-  QtxWorkstackArea* area = NULL;
-  QList<QtxWorkstackArea*> allAreas;
-  areas( mySplit, allAreas, true );
-  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it )
+  int pos = myList.indexOf( wid );
+  if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) )
+    return 0;
+
+  myList.removeAll( wid );
+  pos = idx < 0 ? myList.count() : idx;
+  myList.insert( qMin( pos, (int)myList.count() ), wid );
+  if ( !myInfo.contains( wid ) )
   {
-    if ( (*it)->contains( wid ) )
-      area = *it;
+    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() );
+
+    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* ) ) );
+    connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) );
   }
 
-  if ( !area )
-    return;
+  updateState();
 
-  QSplitter* split = splitter( area );
-  if ( !split )
-    return;
+  setWidgetActive( wid );
+  wid->setFocus();
 
-  // find index of the area in its splitter
-  int item_ind = -1;
-  bool isFound = false;
-  const QObjectList& was = split->children();
-  for ( QObjectList::const_iterator ito = was.begin(); ito != was.end() && !isFound; ++ito, ++item_ind )
-  {
-    if ( *ito == area )
-      isFound = true;
-  }
+  return myChild[wid];
+}
 
-  if ( !isFound || item_ind == 0 )
+/*!
+  \brief Create and show popup menu for the area.
+  \param p mouse pointer position at which popup menu should be shown
+*/
+void QtxWorkstackArea::onContextMenuRequested( QPoint p )
+{
+  const QtxWorkstackTabBar* bar = ::qobject_cast<const QtxWorkstackTabBar*>( sender() );
+  if ( !bar )
     return;
 
-  QIntList szList = split->sizes();
-  int splitter_size = ( split->orientation() == Qt::Horizontal ? split->width() : split->height());
-  int nb = szList.count();
+  QWidget* wid = 0;
+  int idx = tabAt( p );
+  if ( idx != -1 )
+    wid = widget( myBar->tabId( idx ) );
 
-  int new_prev = int( splitter_size * position / item_ind );
-  int new_next = int( splitter_size * ( 1.0 - position ) / ( nb - item_ind ) );
-  setSizes( szList, item_ind, new_prev, new_next, new_next );
-  split->setSizes( szList );
+  emit contextMenuRequested( wid, p );
 }
 
 /*!
-* \brief Set position of the widget relatively the entire workstack.
-* \param wid - widget to set position of
-* \param o   - orientation of positioning (Qt::Horizontal or Qt::Vertical).
-*              If o = Qt::Horizontal, horizontal position of \a wid will be changed.
-*              If o = Qt::Vertical, vertical position of \a wid will be changed.
-* \param pos - position relatively workstack. Value in range [0..1].
+  \brief Called when area's child widget is destroyed.
+
+  Removes child widget from the area.
 */
-void QtxWorkstack::SetRelativePosition( QWidget* wid, const Qt::Orientation o,
-                                        const double position )
+void QtxWorkstackArea::onWidgetDestroyed()
 {
-  if ( position < 0.0 || 1.0 < position )
-    return;
+  if ( sender() )
+    removeWidget( (QWidget*)sender(), false );
+}
 
-  if ( !wid )
+/*!
+  \brief Remove widget from workarea.
+  \param wid widget to be removed
+  \param del if \c true the widget should be also deleted
+*/
+void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del )
+{
+  if ( !myList.contains( wid ) )
     return;
 
-  int splitter_size = o == Qt::Horizontal ? mySplit->width() : mySplit->height();
-  int need_pos = int( position * splitter_size );
-  int splitter_pos = 0;
+  if ( myBar->indexOf( widgetId( wid ) ) != -1 )
+    myBar->removeTab( myBar->indexOf( widgetId( wid ) ) );
 
-  if ( setPosition( wid, mySplit, o, need_pos, splitter_pos ) != 0 )
+  myStack->removeWidget( child( wid ) );
+
+  myList.removeAll( wid );
+  myInfo.remove( wid );
+  myChild.remove( wid );
+
+  if ( del )
   {
-    // impossible to set required position
+    delete child( wid );
+    if ( myList.isEmpty() )
+      delete this;
+    else
+      updateState();
   }
+  else
+    updateState();
 }
 
 /*!
-* \brief Sets the action's accelerator key to accel. 
-* \param id - the key of the action in the actions map.
-* \param accel - action's accelerator key.
+  \brief Get all visible child widgets.
+  \return list of visible child widgets
 */
-void QtxWorkstack::setAccel( const int id, const int accel )
+QWidgetList QtxWorkstackArea::widgetList() const
 {
-  if ( !myActionsMap.contains( id ) )
-    return;
-
-  myActionsMap[id]->setShortcut( accel );
+  QWidgetList lst;
+  for ( QWidgetList::const_iterator it = myList.begin(); it != myList.end(); ++it )
+  {
+    if ( widgetVisibility( *it ) )
+      lst.append( *it );
+  }
+  return lst;
 }
 
 /*!
-* \brief Returns the action's accelerator key.
-* \param id - the key of the action in the actions map.
-* \retval int  - action's accelerator key.
+  \brief Get active child widget.
+  \return active widget
 */
-int QtxWorkstack::accel( const int id ) const
+QWidget* QtxWorkstackArea::activeWidget() const
 {
-  int res = 0;
-  if ( myActionsMap.contains( id ) )
-    res = myActionsMap[id]->shortcut();
-  return res;
+  return widget( myBar->tabId( myBar->currentIndex() ) );
 }
 
-bool QtxWorkstack::isActionEnabled( const int id ) const
+/*!
+  \brief Set active widget.
+  \param wid widget to be made active
+*/
+void QtxWorkstackArea::setActiveWidget( QWidget* wid )
 {
-  bool res = false;
-  if ( myActionsMap.contains( id ) )
-    res = myActionsMap[id]->isEnabled();
-  return res;
+  myBar->setCurrentIndex( myBar->indexOf( widgetId( wid ) ) );
 }
 
-void QtxWorkstack::setActionEnabled( const int id, const bool on )
+/*!
+  \brief Check if area owns the specified widget.
+  \param wid widget to be checked
+  \return \c true if area contains widget
+*/
+bool QtxWorkstackArea::contains( QWidget* wid ) const
 {
-  if ( myActionsMap.contains( id ) )
-    myActionsMap[id]->setEnabled( on );
+  return myList.contains( wid );
 }
 
-static int positionSimple (QIntList& szList, const int nb, const int splitter_size,
-                           const int item_ind, const int item_rel_pos,
-                           const int need_pos, const int splitter_pos)
+/*!
+  \brief Show/hide workarea.
+  \param on new visibility state
+*/
+void QtxWorkstackArea::setVisible( bool on )
 {
-  if (item_ind == 0) { // cannot move in this splitter
-    return (need_pos - splitter_pos);
-  }
-
-  int delta = 0;
-  int new_prev = 0;
-  int new_this = szList[item_ind];
-  int new_next = 0;
+  QMap<QWidget*, bool> map;
+  for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it )
+  {
+    map.insert( *it, isBlocked( *it ) );
+    setBlocked( *it, true );
+  }
 
-  bool isToCheck = false;
+  QFrame::setVisible( on );
 
-  if (need_pos < splitter_pos) {
-    // Set size of all previous workareas to zero <--
-    if (item_ind == nb - 1) {
-      // item iz last in the splitter, it will occupy all the splitter
-      new_this = splitter_size;
-    } else {
-      // recompute size of next items in splitter
-      new_next = (splitter_size - new_this) / (nb - item_ind - 1);
-    }
-    delta = need_pos - splitter_pos;
+  for ( QWidgetList::iterator itr = myList.begin(); itr != myList.end(); ++itr )
+    setBlocked( *itr, map.contains( *itr ) ? map[*itr] : false );
+}
 
-  } else if (need_pos > (splitter_pos + splitter_size)) {
-    // Set size of all next workareas to zero -->
-    // recompute size of previous items in splitter
-    new_this = 0;
-    new_prev = (splitter_size - new_this) / item_ind;
-    delta = need_pos - (splitter_pos + splitter_size - new_this);
+/*!
+  \brief Check if workarea is active.
+  \return \c true if area is active
+*/
+bool QtxWorkstackArea::isActive() const
+{
+  QtxWorkstack* ws = workstack();
+  if ( !ws )
+    return false;
 
-  } else { // required position lays inside this splitter
-    // Move workarea inside splitter into required position <->
-    int new_item_rel_pos = need_pos - splitter_pos;
-    new_prev = new_item_rel_pos / item_ind;
-    if (need_pos < (splitter_pos + item_rel_pos)) {
-      // Make previous workareas smaller, next - bigger
-      // No problem to keep old size of the widget
-    } else {
-      // Make previous workareas bigger, next - smaller
-      if (new_this > splitter_size - new_item_rel_pos) {
-        new_this = splitter_size - new_item_rel_pos;
-      }
-      // jfa to do: in this case fixed size of next widgets could prevent right resizing
-      isToCheck = true;
-    }
-    if (item_ind == nb - 1) {
-      new_this = splitter_size - new_item_rel_pos;
-    } else {
-      new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
-    }
-    delta = 0;
-  }
+  return ws->activeArea() == this;
+}
 
-  setSizes (szList, item_ind, new_prev, new_this, new_next);
-  return delta;
+/*!
+  \brief Update active tab bar state (active/inactive).
+*/
+void QtxWorkstackArea::updateActiveState()
+{
+  myBar->setActive( isActive() );
 }
 
 /*!
-* \brief Set position of given widget.
-* \param wid          - widget to be moved
-* \param split        - currently processed splitter (goes from more common
-*                       to more particular splitter in recursion calls)
-* \param o            - orientation of positioning
-* \param need_pos     - required position of the given widget in pixels
-*                       (from top/left side of workstack area)
-* \param splitter_pos - position of the splitter \a split
-*                       (from top/left side of workstack area)
-* \retval int - returns difference between a required and a distinguished position.
-* 
-* Internal method. Recursively calls itself.
-* Is called from <VAR>SetRelativePosition</VAR> public method.
+  \brief Get parent workstack
+  \return workstack owning this workarea
 */
-int QtxWorkstack::setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
-                               const int need_pos, const int splitter_pos )
+QtxWorkstack* QtxWorkstackArea::workstack() const
 {
-  if ( !wid || !split )
-    return need_pos - splitter_pos;
+  QtxWorkstack* ws = 0;
+  QWidget* wid = parentWidget();
+  while ( wid && !ws )
+  {
+    if ( wid->inherits( "QtxWorkstack" ) )
+      ws = (QtxWorkstack*)wid;
+    wid = wid->parentWidget();
+  }
+  return ws;
+}
 
-  // Find corresponding sub-splitter.
-  // Find also index of appropriate item in current splitter.
-  int cur_ind = 0, item_ind = 0;
-  bool isBottom = false, isFound = false;
-  QSplitter* sub_split = NULL;
-  const QObjectList& objs = split->children();
-  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end() && !isFound; ++it )
+/*!
+  \brief Custom event filter.
+
+  Process events from child widgets.
+
+  \param o event receiver widget
+  \param e event
+  \return \c true if event should be filtered (stop further processing)
+*/
+bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e )
+{
+  if ( o->isWidgetType() )
   {
-    QtxWorkstackArea* area = ::qobject_cast<QtxWorkstackArea*>( *it );
-    if ( area )
+    QWidget* wid = (QWidget*)o;
+    if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress )
     {
-      if ( area->contains( wid ) )
+      bool ok = false;
+      while ( !ok && wid && wid != myClose )
       {
-        item_ind = cur_ind;
-        isBottom = true;
-        isFound = true;
+        ok = wid == this;
+        wid = wid->parentWidget();
       }
-      cur_ind++;
+      if ( ok )
+        QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) );
     }
-    else if ( (*it)->inherits( "QSplitter" ) )
+  }
+  return false;
+}
+
+/*!
+  \brief Get rectangle to be drawn when highlighting drop area.
+  \return area drop rectangle
+*/
+QRect QtxWorkstackArea::floatRect() const
+{
+  QRect r = myStack->geometry();
+  return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) );
+}
+
+/*!
+  \brief Get rectangle to be drawn when highlighting drop area on tab bar.
+  \param idx tab index
+  \return tab bar drop rectrangle
+*/
+QRect QtxWorkstackArea::floatTab( const int idx ) const
+{
+  QRect r = myBar->tabRect( idx );
+  return QRect( myBar->mapToGlobal( r.topLeft() ), r.size() );
+}
+
+/*!
+  \brief Get tab index by point.
+  \param p point
+  \return tab covering point or -1 if there is no tab covering point
+*/
+int QtxWorkstackArea::tabAt( const QPoint& pnt ) const
+{
+  int idx = -1;
+  QPoint p = myBar->mapFromGlobal( pnt );
+  for ( int i = 0; i < myBar->count() && idx == -1; i++ )
+  {
+    QRect r = myBar->tabRect( i );
+    if ( r.isValid() && r.contains( p ) )
+      idx = i;
+  }
+  return idx;
+}
+
+/*!
+  \brief Event handler for custom events.
+  \param e custom event
+*/
+void QtxWorkstackArea::customEvent( QEvent* e )
+{
+  WidgetEvent* we = (WidgetEvent*)e;
+
+  switch ( we->type() )
+  {
+  case ActivateWidget:
+    emit activated( activeWidget() );
+    break;
+  case FocusWidget:
+    if ( activeWidget() )
     {
-      QList<QtxWorkstackArea*> areaList;
-      areas( (QSplitter*)(*it), areaList, true );
-      for ( QList<QtxWorkstackArea*>::iterator ita = areaList.begin(); ita != areaList.end() && !isFound; ++ita )
+      if ( !activeWidget()->focusWidget() )
+        activeWidget()->setFocus();
+      else
       {
-        if ( (*ita)->contains( wid ) )
+        if ( activeWidget()->focusWidget()->hasFocus() )
         {
-          item_ind = cur_ind;
-          isFound = true;
-          sub_split = (QSplitter*)*it;
-        }
+          QFocusEvent in( QEvent::FocusIn );
+               QApplication::sendEvent( this, &in );
+             }
+        else
+          activeWidget()->focusWidget()->setFocus();
       }
-      cur_ind++;
     }
+    break;
+  case RemoveWidget:
+    removeWidget( we->widget() );
+    break;
+  default:
+    break;
   }
+}
 
-  if ( !isFound )
-    return ( need_pos - splitter_pos );
+/*!
+  \brief Customize focus in event handler.
+  \param e focus in event
+*/
+void QtxWorkstackArea::focusInEvent( QFocusEvent* e )
+{
+  QFrame::focusInEvent( e );
 
-  if ( split->orientation() == o )
-  {
-    // Find coordinates of near and far sides of the appropriate item relatively current splitter
-    int splitter_size = ( o == Qt::Horizontal ? split->width() : split->height() );
-    QIntList szList = split->sizes();
-    int nb = szList.count();
-    int item_rel_pos = 0; // position of near side of item relatively this splitter
-    for (int i = 0; i < item_ind; i++) {
-      item_rel_pos += szList[i];
-    }
-    int item_size = szList[item_ind]; // size of item
-    int item_pos = splitter_pos + item_rel_pos;
+  emit activated( activeWidget() );
+}
 
-    // Resize splitter items to complete the conditions
-    if (isBottom) {
-      // I. Bottom of splitters stack reached
+/*!
+  \brief Customize mouse press event handler.
+  \param e mouse press event
+*/
+void QtxWorkstackArea::mousePressEvent( QMouseEvent* e )
+{
+  QFrame::mousePressEvent( e );
 
-      int delta = positionSimple(szList, nb, splitter_size, item_ind, item_rel_pos, need_pos, splitter_pos);
-      split->setSizes(szList);
-      // Recompute delta, as some windows can reject given size
-      int new_item_rel_pos = 0;
-      QIntList szList1 = split->sizes();
-      for (int i = 0; i < item_ind; i++) {
-        new_item_rel_pos += szList1[i];
-      }
-      delta = need_pos - (splitter_pos + new_item_rel_pos);
-      return delta;
+  emit activated( activeWidget() );
+}
 
-    } else {
-      // II. Bottom of splitters stack is not yet reached
+/*!
+  \brief Called when user presses "Close" button.
+*/
+void QtxWorkstackArea::onClose()
+{
+  QWidget* wid = activeWidget();
+  if ( wid )
+    wid->close();
+}
 
-      if (item_ind == 0) { // cannot move in this splitter
-        // Process in sub-splitter
-        return setPosition(wid, sub_split, o, need_pos, splitter_pos);
-      }
+/*!
+  \brief Called when user selects any tab page.
+  \param idx tab page index (not used)
+*/
+void QtxWorkstackArea::onCurrentChanged( int /*idx*/ )
+{
+  updateCurrent();
 
-      int new_prev = 0;
-      int new_this = szList[item_ind];
-      int new_next = 0;
+  emit activated( activeWidget() );
+}
 
-      if (need_pos < splitter_pos) {
-        // Set size of all previous workareas to zero <--
-        if (item_ind == nb - 1) {
-          new_this = splitter_size;
-        } else {
-          new_next = (splitter_size - new_this) / (nb - item_ind - 1);
-        }
-        setSizes (szList, item_ind, new_prev, new_this, new_next);
-        split->setSizes(szList);
-        // Recompute splitter_pos, as some windows can reject given size
-        int new_item_rel_pos = 0;
-        QIntList szList1 = split->sizes();
-        for (int i = 0; i < item_ind; i++) {
-          new_item_rel_pos += szList1[i];
-        }
-        // Process in sub-splitter
-        return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
-      } else if (need_pos > (splitter_pos + splitter_size)) {
-        // Set size of all next workareas to zero -->
-        new_prev = (splitter_size - new_this) / item_ind;
-        setSizes (szList, item_ind, new_prev, new_this, new_next);
-        split->setSizes(szList);
-        // Recompute splitter_pos, as some windows can reject given size
-        int new_item_rel_pos = 0;
-        QIntList szList1 = split->sizes();
-        for (int i = 0; i < item_ind; i++) {
-          new_item_rel_pos += szList1[i];
-        }
-        // Process in sub-splitter
-        return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
-      } else {
-        // Set appropriate size of all previous/next items <->
-        int new_item_rel_pos = item_rel_pos;
-        if (need_pos < item_pos || (item_pos + item_size) < need_pos) {
-          // Move item inside splitter into required position <->
-          int new_this = szList[item_ind];
-          int new_next = 0;
-          new_item_rel_pos = need_pos - splitter_pos;
-          if ((item_pos + item_size) < need_pos) {
-            //new_item_rel_pos = need_pos - (item_pos + item_size);
-            new_item_rel_pos = item_rel_pos + (need_pos - (item_pos + item_size));
-          }
-          int new_prev = new_item_rel_pos / item_ind;
-          if (need_pos < (splitter_pos + item_rel_pos)) {
-            // Make previous workareas smaller, next - bigger
-            // No problem to keep old size of the widget
-          } else {
-            // Make previous workareas bigger, next - smaller
-            if (new_this > splitter_size - new_item_rel_pos) {
-              new_this = splitter_size - new_item_rel_pos;
-            }
-          }
-          if (item_ind == nb - 1) {
-            new_this = splitter_size - new_item_rel_pos;
-          } else {
-            new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
-          }
-          setSizes (szList, item_ind, new_prev, new_this, new_next);
-          split->setSizes(szList);
-          // Recompute new_item_rel_pos, as some windows can reject given size
-          new_item_rel_pos = 0;
-          QIntList szList1 = split->sizes();
-          for (int i = 0; i < item_ind; i++) {
-            new_item_rel_pos += szList1[i];
-          }
-        } else {
-          // Do nothing
-        }
-        // Process in sub-splitter
-        int add_pos = setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
-        if (add_pos == 0)
-          return 0;
+/*!
+  \brief Called when user starts tab page dragging.
+*/
+void QtxWorkstackArea::onDragActiveTab()
+{
+  QtxWorkstackChild* c = child( activeWidget() );
+  if ( !c )
+    return;
 
-        // this can be if corresponding workarea is first in sub-splitter
-        // or sub-splitter has another orientation
+  new QtxWorkstackDrag( workstack(), c );
+}
 
-        // Resize ones again to reach precize position <->
-        int need_pos_1 = splitter_pos + new_item_rel_pos + add_pos;
+/*!
+  \brief Called when area's child widget container is destroyed.
+  \param obj widget container being destroyed
+*/
+void QtxWorkstackArea::onChildDestroyed( QObject* obj )
+{
+  QtxWorkstackChild* child = (QtxWorkstackChild*)obj;
+  myStack->removeWidget( child );
 
-        // Move workarea inside splitter into required position <->
-        int delta_1 = positionSimple(szList, nb, splitter_size, item_ind,
-                                     new_item_rel_pos, need_pos_1, splitter_pos);
-        split->setSizes(szList);
-        // Recompute new_item_rel_pos, as some windows can reject given size
-        new_item_rel_pos = 0;
-        QIntList szList1 = split->sizes();
-        for (int i = 0; i < item_ind; i++) {
-          new_item_rel_pos += szList1[i];
-        }
-        delta_1 = need_pos_1 - (splitter_pos + new_item_rel_pos);
-        return delta_1;
-      }
-    }
-  } else {
-    return setPosition(wid, sub_split, o, need_pos, splitter_pos);
+  QWidget* wid = 0;
+  for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it )
+  {
+    if ( it.value() == child )
+      wid = it.key();
   }
 
-  return 0;
+  myChild.remove( wid );
+
+  QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)RemoveWidget, wid ) );
 }
 
 /*!
-  Redistributes space among widgets equally
+  \brief Called when child widget container is shown.
+  \param c child widget container being shown
 */
-void QtxWorkstack::distributeSpace( QSplitter* split ) const
+void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
 {
-  if ( !split )
+  setWidgetShown( c->widget(), true );
+}
+
+/*!
+  \brief Called when child widget container is hidden.
+  \param c child widget container being hidden
+*/
+void QtxWorkstackArea::onChildHidden( QtxWorkstackChild* c )
+{
+  setWidgetShown( c->widget(), false );
+}
+
+/*!
+  \brief Called when child widget container is activated.
+  \param c child widget container being activated
+*/
+void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c )
+{
+  setWidgetActive( c->widget() );
+}
+
+/*!
+  \brief Called when child widget container's title is changed.
+  \param c child widget container which title is changed
+*/
+void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c )
+{
+  updateTab( c->widget() );
+}
+
+/*!
+  \brief Update current child widget container.
+
+  Raises widget when active tab page is changed.
+*/
+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 );
+}
+
+/*!
+  \brief Update tab bar.
+  \param wid tab page widget
+*/
+void QtxWorkstackArea::updateTab( QWidget* wid )
+{
+  int idx = myBar->indexOf( widgetId( wid ) );
+  if ( idx < 0 )
     return;
 
-  QIntList szList = split->sizes();
-  int size = ( split->orientation() == Qt::Horizontal ?
-               split->width() : split->height() ) / szList.count();
-  for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it )
-    *it = size;
-  split->setSizes( szList );
+  myBar->setTabIcon( idx, wid->windowIcon() );
+  myBar->setTabText( idx, wid->windowTitle() );
 }
 
 /*!
-  Splits widgets vertically
+  \brief Get child widget by specified identifier.
+  \param id widget ID
+  \return widget or 0, if identifier in invalid
 */
-void QtxWorkstack::splitVertical()
+QWidget* QtxWorkstackArea::widget( const int id ) const
 {
-  split( Qt::Horizontal );
+  QWidget* wid = 0;
+  for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it )
+  {
+    if ( it.value().id == id )
+      wid = it.key();
+  }
+  return wid;
 }
 
 /*!
-  Splits widgets horizontally
+  \brief Get child widget identifier.
+  \param wid widget
+  \return widget ID or -1 if widget is not found
 */
-void QtxWorkstack::splitHorizontal()
+int QtxWorkstackArea::widgetId( QWidget* wid ) const
 {
-  split( Qt::Vertical );
+  int id = -1;
+  if ( myInfo.contains( wid ) )
+    id = myInfo[wid].id;
+  return id;
 }
 
 /*!
-  SLOT: called if action "Rename" is activated, changes caption of widget
+  \brief Get child widget's visibility.
+  \param wid widget
+  \return \c true if widget is visible
 */
-void QtxWorkstack::onRename()
+bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const
 {
-  if ( !myWorkWin )
+  bool res = false;
+  if ( myInfo.contains( wid ) )
+    res = myInfo[wid].vis;
+  return res;
+}
+
+/*!
+  \brief Set active child widget.
+  \param wid widget to be set active
+*/
+void QtxWorkstackArea::setWidgetActive( QWidget* wid )
+{
+  int id = widgetId( wid );
+  if ( id < 0 )
     return;
 
-  bool ok = false;
-  QString newName = QInputDialog::getText( topLevelWidget(),  tr( "Rename" ), tr( "Enter new name:" ),
-                                           QLineEdit::Normal, myWorkWin->windowTitle(), &ok );
-  if ( ok && !newName.isEmpty() )
-    myWorkWin->setWindowTitle( newName );
+  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.
+*/
+void QtxWorkstackArea::updateState()
+{
+  bool updBar = myBar->updatesEnabled();
+  bool updStk = myStack->updatesEnabled();
+  myBar->setUpdatesEnabled( false );
+  myStack->setUpdatesEnabled( false );
+
+  bool block = myBar->signalsBlocked();
+  myBar->blockSignals( true );
+
+  QWidget* prev = activeWidget();
+
+  int idx = 0;
+  for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it )
+  {
+    QWidget* wid = *it;
+    int id = widgetId( wid );
+
+    if ( id < 0 )
+      continue;
+
+    bool vis = widgetVisibility( wid );
+
+    int cIdx = myBar->indexOf( id );
+    if ( cIdx != -1 && ( !vis || myBar->indexOf( id ) != idx ) )
+      myBar->removeTab( cIdx );
+
+    if ( myBar->indexOf( id ) == -1 && vis )
+      myBar->setTabId( myBar->insertTab( idx, wid->windowTitle() ), id );
+
+    updateTab( wid );
+
+    bool block = isBlocked( wid );
+    setBlocked( wid, true );
+
+    QtxWorkstackChild* cont = child( wid );
+
+    if ( !vis )
+      myStack->removeWidget( cont );
+    else if ( myStack->indexOf( cont ) < 0 )
+      myStack->addWidget( cont );
+
+    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-- )
+    {
+      if ( widgetVisibility( myList.at( i ) ) )
+        wid = myList.at( i );
+    }
+
+    for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ )
+    {
+      if ( widgetVisibility( myList.at( j ) ) )
+        wid = myList.at( j );
+    }
+
+    if ( wid )
+      curId = widgetId( wid );
+  }
+
+  myBar->setCurrentIndex( myBar->indexOf( curId ) );
+
+  myBar->blockSignals( block );
+
+  updateCurrent();
+
+  myBar->updateActiveState();
+
+  myBar->setUpdatesEnabled( updBar );
+  myStack->setUpdatesEnabled( updStk );
+  if ( updBar )
+    myBar->update();
+  if ( updStk )
+    myStack->update();
+
+  QResizeEvent re( myBar->size(), myBar->size() );
+  QApplication::sendEvent( myBar, &re );
+
+  if ( isEmpty() )
+  {
+    hide();
+    emit deactivated( this );
+  }
+  else
+  {
+    show();
+    if ( prev != activeWidget() )
+      emit activated( activeWidget() );
+  }
 }
 
 /*!
-  Wraps area into new splitter
-  \return new splitter
+  \brief Generate unique widget identifier.
+  \return first non shared widget ID
 */
-QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area )
+int QtxWorkstackArea::generateId() const
 {
-  if ( !area )
-    return 0;
-
-  QSplitter* pSplit = splitter( area );
-  if ( !pSplit )
-    return 0;
-
-  bool upd = pSplit->updatesEnabled();
-  pSplit->setUpdatesEnabled( false );
-
-  QIntList szList = pSplit->sizes();
-
-  QSplitter* wrap = new QSplitter( 0 );
-#if defined QT_VERSION && QT_VERSION >= 0x30200
-  wrap->setChildrenCollapsible( false );
-#endif
-  pSplit->insertWidget( pSplit->indexOf( area ) + 1, wrap );
-  wrap->setVisible( true );
-  wrap->addWidget( area );
+  QMap<int, int> map;
 
-  pSplit->setSizes( szList );
+  for ( WidgetInfoMap::const_iterator it = myInfo.begin(); it != myInfo.end(); ++it )
+    map.insert( it.value().id, 0 );
 
-  pSplit->setUpdatesEnabled( upd );
+  int id = 0;
+  while ( map.contains( id ) )
+    id++;
 
-  return wrap;
+  return id;
 }
 
 /*!
-  Reparenst and adds widget
-  \param wid - widget
-  \param pWid - parent widget
-  \param after - after widget
+  \brief Check if the child wiget is blocked.
+  \param wid widget
+  \return \c true if the widget is blocked
 */
-void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after )
+bool QtxWorkstackArea::isBlocked( QWidget* wid ) const
 {
-  if ( !wid || !pWid )
-    return;
-
-  QWidgetList moveList;
-  const QObjectList& lst = pWid->children();
-  bool found = false;
-  for ( QObjectList::const_iterator it = lst.begin(); it != lst.end(); ++it )
-  {
-    if ( found && ( (*it)->inherits( "QSplitter" ) ||
-                    (*it)->inherits( "QtxWorkstackArea" ) ) )
-      moveList.append( (QWidget*)(*it) );
-    if ( *it == after )
-      found = true;
-  }
-
-  QMap<QWidget*, bool> map;
-  for ( QWidgetList::iterator it = moveList.begin(); it != moveList.end(); ++it )
-  {
-    map.insert( *it, (*it)->isVisibleTo( (*it)->parentWidget() ) );
-    (*it)->setParent( 0 );
-    (*it)->hide();
-  }
-
-  wid->setParent( pWid );
-
-  for ( QWidgetList::iterator itr = moveList.begin(); itr != moveList.end(); ++itr )
-  {
-    (*itr)->setParent( pWid );
-    (*itr)->setShown( map.contains( *itr ) ? map[*itr] : false );
-  }
+  return myBlock.contains( wid );
 }
 
 /*!
-* \brief Closes the active window.
+  \brief Block widget.
+  \param wid widget
+  \param on new blocked state
 */
-void QtxWorkstack::onCloseWindow()
+void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on )
 {
-  if ( myWorkWin )
-    myWorkWin->close();
-  else if( activeWindow() )
-    activeWindow()->close();
+  if ( on )
+    myBlock.insert( wid, 0 );
+  else
+    myBlock.remove( wid );
 }
 
 /*!
-  SLOT: called on area is destroyed
-  Sets focus to neighbour area
+  \brief Get child widget container.
+  \param wid child widget
+  \return child widget container corresponding to the \a wid
 */
-void QtxWorkstack::onDestroyed( QObject* obj )
+QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const
 {
-  QtxWorkstackArea* area = (QtxWorkstackArea*)obj;
+  QtxWorkstackChild* res = 0;
+  if ( myChild.contains( wid ) )
+    res = myChild[wid];
+  return res;
+}
 
-  if ( area == myArea )
-    myArea = 0;
+/*!
+  \fn void QtxWorkstackArea::activated( QWidget* w )
+  \brief Emitted when child widget is activated.
+  \param w child widget being activated
+*/
 
-  if ( !myArea )
-  {
-    QtxWorkstackArea* cur = neighbourArea( area );
-    if ( cur )
-      cur->setFocus();
-  }
+/*!
+  \fn void QtxWorkstackArea::contextMenuRequested( QWidget* w, QPoint p )
+  \brief Emitted when context popup menu is requested.
+  \param w child widget popup menu requested for
+  \param p point popup menu to be shown at
+*/
 
-  QApplication::postEvent( this, new QEvent( QEvent::User ) );
-}
+/*!
+  \fn void QtxWorkstackArea::deactivated( QtxWorkstackArea* wa )
+  \brief Emitted when workarea is deactivated.
+  \param wa workarea being deactivated
+*/
+
+/*!
+  \class QtxWorkstackChild
+  \internal
+  \brief Workarea child widget container.
+*/
 
 /*!
-  SLOT: called on window activating
+  \brief Constructor.
+  \param wid child widget
+  \param parent parent widget
+  \param f widget flags
 */
-void QtxWorkstack::onWindowActivated( QWidget* )
+QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent, Qt::WindowFlags f )
+: QWidget( parent ),
+  myWidget( wid )
 {
-  const QObject* obj = sender();
-  if ( !obj->inherits( "QtxWorkstackArea" ) )
-    return;
+  myWidget->setParent( this, f );
+  myWidget->installEventFilter( this );
+  QVBoxLayout* base = new QVBoxLayout( this );
+  base->addWidget( myWidget );
 
-  setActiveArea( (QtxWorkstackArea*)obj );
+  connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
 }
 
 /*!
-  SLOT: called on window deactivating
+  \brief Destructor.
 */
-void QtxWorkstack::onDeactivated( QtxWorkstackArea* area )
+QtxWorkstackChild::~QtxWorkstackChild()
 {
-  if ( myArea != area )
-    return;
-
-  QList<QtxWorkstackArea*> lst;
-  areas( mySplit, lst, true );
+  QApplication::instance()->removeEventFilter( this );
 
-  int idx = lst.indexOf( area );
-  if ( idx == -1 )
+  if ( !widget() )
     return;
 
-  myWin = 0;
-  myArea = 0;
+  disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
 
-  QtxWorkstackArea* newArea = neighbourArea( area );
-  if ( newArea && newArea->activeWidget() )
-    newArea->activeWidget()->setFocus();
+  widget()->hide();
+  widget()->removeEventFilter( this );
 
-  QApplication::postEvent( this, new QEvent( QEvent::User ) );
+  widget()->setParent( 0 );
 }
 
 /*!
-  Creates and shows popup menu for area
-  \param w - area
-  \param p - popup position
+  \brief Get child widget.
+  \return child widget
 */
-void QtxWorkstack::onContextMenuRequested( QWidget* w, QPoint p )
+QWidget* QtxWorkstackChild::widget() const
 {
-  QtxWorkstackArea* anArea = ::qobject_cast<QtxWorkstackArea*>( (QObject*)sender() );
-  if ( !anArea )
-    anArea = activeArea();
-
-  if ( !anArea )
-    return;
-
-  QWidgetList lst = anArea->widgetList();
-  if ( lst.isEmpty() )
-    return;
+  return myWidget;
+}
 
-  myWorkWin = w;
-  myWorkArea = anArea;
+/*!
+  \brief Custom event filter.
 
-  QMenu* pm = new QMenu();
-  
-  if ( lst.count() > 1 )
-  {
-    if ( myActionsMap[SplitVertical]->isEnabled() )
-      pm->addAction( myActionsMap[SplitVertical] );
-    if ( myActionsMap[SplitHorizontal]->isEnabled() )
-      pm->addAction( myActionsMap[SplitHorizontal] );
-    pm->addSeparator();
-  }
+  Process events from child widgets.
 
-  if ( w )
+  \param o event receiver widget
+  \param e event
+  \return \c true if event should be filtered (stop further processing)
+*/
+bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e )
+{
+  if ( o->isWidgetType() )
   {
-    if ( myActionsMap[Close]->isEnabled() )
-      pm->addAction( myActionsMap[Close] );
-    if ( myActionsMap[Rename]->isEnabled() )
-      pm->addAction( myActionsMap[Rename] );
-  }
-
-  Qtx::simplifySeparators( pm );
+    if ( e->type() == QEvent::WindowTitleChange || e->type() == QEvent::WindowIconChange )
+      emit captionChanged( this );
 
-  if ( !pm->actions().isEmpty() )
-    pm->exec( p );
+    if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
+      emit shown( this );
 
-  delete pm;
+    if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
+      emit hidden( this );
 
-  myWorkWin = 0;
-  myWorkArea = 0;
+    if ( e->type() == QEvent::FocusIn )
+      emit activated( this );
+  }
+  return QWidget::eventFilter( o, e );
 }
 
-QWidget* QtxWorkstack::addWindow( QWidget* w, Qt::WindowFlags f )
+/*!
+  \brief Called when child widget is destroyed.
+  \param obj child widget being destroyed
+*/
+void QtxWorkstackChild::onDestroyed( QObject* obj )
 {
-  if ( !w )
-    return 0;
+  if ( obj != widget() )
+    return;
 
-  return targetArea()->insertWidget( w, -1, f );
+  myWidget = 0;
+  deleteLater();
 }
 
 /*!
-  Handler of custom events
+  \brief Customize child event handler.
+  \param e child event
 */
-void QtxWorkstack::customEvent( QEvent* )
+void QtxWorkstackChild::childEvent( QChildEvent* e )
 {
-  updateState();
+  if ( e->removed() && e->child() == widget() )
+  {
+    myWidget = 0;
+    deleteLater();
+  }
+  QWidget::childEvent( e );
 }
 
 /*!
-  \return splitter corresponding to area
-  \param area
+  \fn void QtxWorkstackChild::shown( QtxWorkstackChild* w )
+  \brief Emitted when child widget is shown.
+  \param w child widget container
 */
-QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const
-{
-  if ( !area )
-    return 0;
 
-  QSplitter* split = 0;
+/*!
+  \fn void QtxWorkstackChild::hidden( QtxWorkstackChild* w )
+  \brief Emitted when child widget is hidden.
+  \param w child widget container
+*/
 
-  QWidget* wid = area->parentWidget();
-  if ( wid && wid->inherits( "QSplitter" ) )
-    split = (QSplitter*)wid;
+/*!
+  \fn void QtxWorkstackChild::activated( QtxWorkstackChild* w )
+  \brief Emitted when child widget is activated.
+  \param w child widget container
+*/
 
-  return split;
-}
+/*!
+  \fn void QtxWorkstackChild::captionChanged( QtxWorkstackChild* w )
+  \brief Emitted when child widget's title is changed.
+  \param w child widget container
+*/
 
 /*!
-  Fills list with children splitters
-  \param split - parent splitter
-  \param splitList - list to be filled with
-  \param rec - recursive search of children
+  \class QtxWorkstackTabBar
+  \internal
+  \brief Workstack tab bar widget
 */
-void QtxWorkstack::splitters( QSplitter* split, QList<QSplitter*>& splitList, const bool rec ) const
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
+: QTabBar( parent ),
+  myId( -1 )
 {
-  if ( !split )
-    return;
+  setDrawBase( true );
+  setElideMode( Qt::ElideNone );
 
-  const QObjectList& objs = split->children();
-  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
-  {
-    if ( rec )
-      splitters( (QSplitter*)*it, splitList, rec );
-    if ( (*it)->inherits( "QSplitter" ) )
-      splitList.append( (QSplitter*)*it );
-  }
+  connect( this, SIGNAL( currentChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) );
 }
 
 /*!
-  Fills list with children areas
-  \param split - parent splitter
-  \param areaList - list to be filled with
-  \param rec - recursive search of children
+  \brief Destructor.
 */
-void QtxWorkstack::areas( QSplitter* split, QList<QtxWorkstackArea*>& areaList, const bool rec ) const
+QtxWorkstackTabBar::~QtxWorkstackTabBar()
 {
-  if ( !split )
-    return;
+}
 
-  const QObjectList& objs = split->children();
-  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
-  {
-    if ( (*it)->inherits( "QtxWorkstackArea" ) )
-      areaList.append( (QtxWorkstackArea*)*it );
-    else if ( rec && (*it)->inherits( "QSplitter" ) )
-      areas( (QSplitter*)*it, areaList, rec );
-  }
+/*!
+  \brief Get tab page identifier.
+  \param index tab page index
+  \return tab page ID or -1 if \a index is out of range
+*/
+int QtxWorkstackTabBar::tabId( const int index ) const
+{
+  QVariant v = tabData( index );
+  if ( !v.canConvert( QVariant::Int ) )
+    return -1;
+  return v.toInt();
 }
 
 /*!
-  \return active area
+  \brief Set tab page identifier.
+  \param index tab page index
+  \param id tab page ID
 */
-QtxWorkstackArea* QtxWorkstack::activeArea() const
+void QtxWorkstackTabBar::setTabId( const int index, const int id )
 {
-  return myArea;
+  setTabData( index, id );
 }
 
 /*!
-  \return active area or current area or create new area of there is no one
+  \brief Get tab page index by specified identifier.
+  \param id tab page ID
+  \return tab page index or -1 if not found
 */
-QtxWorkstackArea* QtxWorkstack::targetArea()
+int QtxWorkstackTabBar::indexOf( const int id ) const
 {
-  QtxWorkstackArea* area = activeArea();
-  if ( !area )
-    area = currentArea();
-  if ( !area )
+  int index = -1;
+  for ( int i = 0; i < (int)count() && index < 0; i++ )
   {
-    QList<QtxWorkstackArea*> lst;
-    areas( mySplit, lst );
-    if ( !lst.isEmpty() )
-      area = lst.first();
+    if ( tabId( i ) == id )
+      index = i;
   }
-
-  if ( !area )
-    area = createArea( mySplit );
-
-  return area;
+  return index;
 }
 
 /*!
-  \return current area (that has focus)
+  \brief Check if the tab bar is active.
+  \return \c true if tab bar is active
 */
-QtxWorkstackArea* QtxWorkstack::currentArea() const
+bool QtxWorkstackTabBar::isActive() const
 {
-  QtxWorkstackArea* area = 0;
-  QWidget* wid = focusWidget();
-  while ( wid && !area )
-  {
-    if ( wid->inherits( "QtxWorkstackArea" ) )
-      area = (QtxWorkstackArea*)wid;
-    wid = wid->parentWidget();
-  }
-
-  return area;
+  return myActive;
 }
 
 /*!
-  Creates new area
+  \brief Set tab bar active/inactive.
+  \param on new active state
 */
-QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const
+void QtxWorkstackTabBar::setActive( const bool on )
 {
-  QtxWorkstackArea* area = new QtxWorkstackArea( parent );
-
-  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 ) ) );
-  connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) );
+  if ( myActive == on )
+    return;
 
-  return area;
+  myActive = on;
+  updateActiveState();
 }
 
 /*!
-  Sets area as active
-  \param area
+  \brief Update tab bar according to the 'active' state.
 */
-void QtxWorkstack::setActiveArea( QtxWorkstackArea* area )
+void QtxWorkstackTabBar::updateActiveState()
 {
-  QWidget* oldCur = myWin;
-
-  QtxWorkstackArea* oldArea = myArea;
-
-  myArea = area;
-
-  if ( myArea != oldArea )
-  {
-    if ( oldArea )
-      oldArea->updateActiveState();
-    if ( myArea )
-      myArea->updateActiveState();
-  }
-
-  if ( myArea )
-    myWin = myArea->activeWidget();
-
-  if ( myWin && oldCur != myWin )
-    emit windowActivated( myWin );
+  QColor bc = palette().color( QPalette::Text );
+  QColor ac = isActive() ? palette().color( QPalette::Highlight ) : bc;
+  for ( int i = 0; i < (int)count(); i++ )
+    setTabTextColor( i, currentIndex() == i ? ac : bc );
 }
 
 /*!
-  \return neighbour area
-  \param area - area to search neighbour
+  \brief Called when current tab page is changed.
+  \param idx tab page index (not used)
 */
-QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const
+void QtxWorkstackTabBar::onCurrentChanged( int /*index*/ )
 {
-  QList<QtxWorkstackArea*> lst;
-  areas( mySplit, lst, true );
-  int pos = lst.indexOf( area );
-  if ( pos < 0 )
-    return 0;
-
-  QtxWorkstackArea* na = 0;
-  for ( int i = pos - 1; i >= 0 && !na; i-- )
-  {
-    if ( !lst.at( i )->isEmpty() )
-      na = lst.at( i );
-  }
-
-  for ( int j = pos + 1; j < (int)lst.count() && !na; j++ )
-  {
-    if ( !lst.at( j )->isEmpty() )
-        na = lst.at( j );
-  }
-  return na;
+  updateActiveState();
 }
 
 /*!
-  \return area covering point
-  \param p - point
+  \brief Customize mouse move event handler.
+  \param e mouse event
 */
-QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const
+void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e )
 {
-  QtxWorkstackArea* area = 0;
-  QList<QtxWorkstackArea*> lst;
-  areas( mySplit, lst, true );
-  for ( QList<QtxWorkstackArea*>::iterator it = lst.begin(); it != lst.end() && !area; ++it )
+  if ( myId != -1 && !tabRect( indexOf( myId ) ).contains( e->pos() ) )
   {
-    QtxWorkstackArea* cur = *it;
-    QRect r = cur->geometry();
-    if ( cur->parentWidget() )
-      r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() );
-    if ( r.contains( p ) )
-      area = cur;
+    myId = -1;
+    emit dragActiveTab();
   }
-  return area;
+
+  QTabBar::mouseMoveEvent( e );
 }
 
 /*!
-  Update
+  \brief Customize mouse press event handler.
+  \param e mouse event
 */
-void QtxWorkstack::updateState()
+void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e )
 {
-  updateState( mySplit );
+  QTabBar::mousePressEvent( e );
+
+  if ( e->button() == Qt::LeftButton )
+    myId = tabId( currentIndex() );
 }
 
 /*!
-  Update splitters
+  \brief Customize mouse release event handler.
+  \param e mouse event
 */
-void QtxWorkstack::updateState( QSplitter* split )
+void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e )
 {
-  QList<QSplitter*> recList;
-  splitters( split, recList, false );
-  for ( QList<QSplitter*>::iterator itr = recList.begin(); itr != recList.end(); ++itr )
-    updateState( *itr );
-
-  QList<QSplitter*> splitList;
-  splitters( split, splitList, false );
-
-  QList<QtxWorkstackArea*> areaList;
-  areas( split, areaList, false );
-
-  bool vis = false;
-  for ( QList<QtxWorkstackArea*>::iterator it = areaList.begin(); it != areaList.end(); ++it )
-  {
-    if ( (*it)->isEmpty() )
-      (*it)->hide();
-    else
-    {
-      (*it)->show();
-      vis = true;
-    }
-  }
-
-  if ( split == mySplit )
-    return;
+  QTabBar::mouseReleaseEvent( e );
 
-  for ( QList<QSplitter*>::iterator iter = splitList.begin(); iter != splitList.end() && !vis; ++iter )
-    vis = (*iter)->isVisibleTo( (*iter)->parentWidget() );
+  myId = -1;
 
-  if ( areaList.isEmpty() && splitList.isEmpty() )
-    delete split;
-  else if ( vis )
-    split->show();
-  else
-    split->hide();
+  if ( e->button() == Qt::RightButton )
+    emit contextMenuRequested( e->globalPos() );
 }
 
 /*!
-  Gets splitter info for debug
-  \param split - splitter
-  \param info - string to be filled with info
+  \brief Customize context menu event handler.
+  \param e context menu event
 */
-void QtxWorkstack::splitterInfo( QSplitter* split, QString& info ) const
+void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e )
 {
-  if ( !split )
-    return;
-
-  const QObjectList& objs = split->children();
+  if ( e->reason() != QContextMenuEvent::Mouse )
+    emit contextMenuRequested( e->globalPos() );
+}
 
-  QString sizesStr;
-  QList<int> sizes = split->sizes();
-  for ( QList<int>::iterator sIt = sizes.begin(); sIt != sizes.end(); ++sIt )
+/*
+void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
+{
+  if ( currentTab() != t->identifier() )
   {
-    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
+    QFont fnt = p->font();
+    fnt.setUnderline( false );
+    p->setFont( fnt );
   }
+  QTabBar::paintLabel( p, br, t, has_focus );
+}
+*/
 
-  if ( !sizesStr.isEmpty() ) // cut the first ':'
-    sizesStr = sizesStr.right( sizesStr.length() - 1 );
+/*!
+  \fn void QtxWorkstackTabBar::dragActiveTab()
+  \brief Emitted when dragging operation is started.
+*/
 
-  info += QString( "(splitter orientation=%1 sizes=%3 " ).arg( split->orientation() ).arg( sizesStr );
-    
-  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
-  {
-    if ( (*it)->inherits( "QSplitter" ) )
-           splitterInfo( (QSplitter*)*it, info );
-    else if ( (*it)->inherits( "QtxWorkstackArea" ) )
-    {
-           QtxWorkstackArea* area = (QtxWorkstackArea*)*it;
-           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 += ')';
-    }
-  }
+/*!
+  \fn void QtxWorkstackTabBar::contextMenuRequested( QPoint p )
+  \brief Emitted when context popup menu is requested.
+  \param p point popup menu to be shown at
+*/
 
-  info += ')';
-  printf( (const char*)QString( info + '\n' ).toLatin1() );
-}
+/*!
+  \class QtxWorkstack
+  \brief Workstack widget.
 
+  Organizes the child widgets in the tabbed space.
+  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.
 
-//Cuts starting '(' symbol and ending '(' symbol
-void cutBrackets( QString& parameters )
-{
-  QChar c1 = parameters[0];
-  QChar c2 = parameters[int(parameters.length()-1)];
-  if ( !parameters.isEmpty() && c1 == '(' && c2 == ')' )
-    parameters = parameters.mid( 1, parameters.length()-2 );
-}
+  This widget can be used as workspace of the application main window, 
+  for example, as kind of implementation of multi-document interface.
+*/
 
-/*
-  for strings like "(splitter orientation=0 children=2 sizes=332:478" returns values of
-  parameters.  For example, getValue( example, "children" ) returns "2"
-  getValue( example, "sizes" ) returns "332:478"
+/*!
+  \brief Constructor.
+  \param parent parent widget
 */
-QString getValue( const QString& str, const QString& valName )
+QtxWorkstack::QtxWorkstack( QWidget* parent )
+: QWidget( parent ),
+  myWin( 0 ),
+  myArea( 0 ),
+  myWorkWin( 0 ),
+  myWorkArea( 0 )
 {
-  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();
+  myActionsMap.insert( SplitVertical,   new QtxAction( QString(), tr( "Split vertically" ), 0, this ) );
+  myActionsMap.insert( SplitHorizontal, new QtxAction( QString(), tr( "Split horizontally" ), 0, this ) );
+  myActionsMap.insert( Close,           new QtxAction( QString(), tr( "Close" ), 0, this ) );
+  myActionsMap.insert( Rename,          new QtxAction( QString(), tr( "Rename" ), 0, this ) );
+
+  connect( myActionsMap[SplitVertical], SIGNAL( triggered( bool ) ), this, SLOT( splitVertical() ) );
+  connect( myActionsMap[SplitHorizontal], SIGNAL( triggered( bool ) ), this, SLOT( splitHorizontal() ) );
+  connect( myActionsMap[Close], SIGNAL( triggered( bool ) ), this, SLOT( onCloseWindow() ) );
+  connect( myActionsMap[Rename], SIGNAL( triggered( bool ) ), this, SLOT( onRename() ) );
+
+  QVBoxLayout* base = new QVBoxLayout( this );
+  base->setMargin( 0 );
+
+  mySplit = new QSplitter( this );
+  mySplit->setChildrenCollapsible( false );
+  base->addWidget( mySplit );
 }
 
-/*
-  checks format of splitter parameters string
+/*!
+  \brief Destructor.
 */
-bool checkFormat( const QString& parameters )
+QtxWorkstack::~QtxWorkstack()
 {
-  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;
 }
 
-/*
-  Returns children of splitter in a list.  Children are separated by '(' and ')' symbols
+/*!
+  \brief Get all child widgets in all workareas.
+  \return list of widgets in all workareas
 */
-QStringList getChildren( const QString& str )
+QWidgetList QtxWorkstack::windowList() 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() )
+  QList<QtxWorkstackArea*> lst;
+  areas( mySplit, lst, true );
+
+  QWidgetList widList;
+  for ( QList<QtxWorkstackArea*>::iterator it = lst.begin(); it != lst.end(); ++it )
   {
-    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++;
+    QWidgetList wids = (*it)->widgetList();
+    for ( QWidgetList::iterator itr = wids.begin(); itr != wids.end(); ++itr )
+      widList.append( *itr );
   }
 
-  return lst;
+  return widList;
 }
 
-// for a string like "views active='AnotherView' 'GLView' 'AnotherView'"
-// getViewName( example, 0 ) returns "GLView", 
-// getViewName( example, 1 ) -> "AnotherView", etc.
-QString getViewName( const QString& str, int i )
+/*!
+  \brief Get all child widgets in the active workarea.
+  \return list of widgets in active workarea
+*/
+QWidgetList QtxWorkstack::splitWindowList() const
 {
-  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 )
-  {
-    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();
+  return myArea ? myArea->widgetList() : QWidgetList();
 }
 
-// returns widget with given name
-QWidget* getView( const QWidget* parent, const QString& aName )
+/*!
+  \brief Get active widget.
+  \return active widget
+*/
+QWidget* QtxWorkstack::activeWindow() const
 {
-  QWidget* view = 0;
-  QList<QWidget*> l = qFindChildren<QWidget*>( parent->topLevelWidget(), aName );
-  if ( !l.isEmpty() )
-    view = ::qobject_cast<QWidget*>( l.first() );
-  return view;
+  return myWin;
 }
 
 /*!
-  Installs a splitter described by given parameters string
+  \brief Split workstack.
+
+  Splitting is possible only if there are two or more widgets in the workarea.
+  This function splits current workarea to two new ones.
+
+  \param o splitting orientation (Qt::Orientation)
 */
-void QtxWorkstack::setSplitter( QSplitter* splitter, const QString& parameters, QMap<QSplitter*, QList<int> >& sMap )
+void QtxWorkstack::split( const int o )
 {
-  printf( QString( parameters + '\n' ).toLatin1() );
-  if ( !::checkFormat( parameters ) ) {
-    printf( "\nInvalid format of workstack parameters.  Positions of viewers can not be restored.\n" );
+  QtxWorkstackArea* area = myWorkArea;
+  if ( !area )
+    area = activeArea();
+  if ( !area )
     return;
-  }
 
-  QString params( parameters );
-  ::cutBrackets( params );
+  if ( area->widgetList().count() < 2 )
+    return;
 
-  // 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;
+  QWidget* curWid = area->activeWidget();
+  if ( !curWid )
+    return;
 
-  // set orientation of splitter
-  int orient = ::getValue( params, "orientation" ).toInt();
-  splitter->setOrientation( (Qt::Orientation)orient );
+  QSplitter* s = splitter( area );
+  QList<QtxWorkstackArea*> areaList;
+  areas( s, areaList );
 
-  // get children
-  QString options = params.left( params.indexOf( '(' ) );
-  QString childrenStr = params.right( params.length()-options.length() );
-  QStringList children = ::getChildren( childrenStr );
+  QList<QSplitter*> splitList;
+  splitters( s, splitList );
 
-  // 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() );
+  QSplitter* trg = 0;
+  if ( areaList.count() + splitList.count() < 2 || s->orientation() == o )
+    trg = s;
 
-  for ( it = children.begin(); it != children.end(); ++it )
-  {
-    if ( (*it).startsWith( "(splitter" ) )
-    {
-      QSplitter* newSplitter = new QSplitter( splitter );
-      setSplitter( newSplitter, *it, sMap );
-    }
-    else if ( (*it).startsWith( "(views" ) )
-    {
-      QtxWorkstackArea* 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 );
-    }
-  }
+  if ( !trg )
+    trg = wrapSplitter( area );
+
+  if ( !trg )
+    return;
+
+  trg->setOrientation( (Qt::Orientation)o );
+
+  QtxWorkstackArea* newArea = createArea( 0 );
+  trg->insertWidget( trg->indexOf( area ) + 1, newArea );
+
+  area->removeWidget( curWid );
+  newArea->insertWidget( curWid );
+
+  distributeSpace( trg );
+
+  curWid->show();
+  curWid->setFocus();
 }
 
 /*!
-  Restore workstack's configuration stored in 'parameters' string
+  \brief Split workarea of the given widget on two parts.
+
+  Splitting is possible only if there are two or more widgets in the workarea.
+  This function splits current workarea to two new ones.
+
+  \param wid widget belonging to the workstack
+  \param o splitting orientation type (Qt::Orientation)
+  \param type splitting type (QtxWorkstack::SplitType)
 */
-QtxWorkstack& QtxWorkstack::operator<<( const QString& parameters )
+void QtxWorkstack::Split( QWidget* wid, const Qt::Orientation o, const SplitType type )
 {
-  // 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;
+  if (!wid) return;
 
-  for ( QList<QtxWorkstackArea*>::iterator it = areaList.begin(); it != areaList.end(); ++it )
+  // find area of the given widget
+  QtxWorkstackArea* area = NULL;
+  QList<QtxWorkstackArea*> allAreas;
+  areas(mySplit, allAreas, true);
+
+
+  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it )
   {
-    if ( (*it)->isEmpty() )
-      delete *it;
+    if ( (*it)->contains( wid ) )
+      area = *it;
   }
 
-  // restore splitter recursively
-  QMap< QSplitter*, QList<int> > sMap;
-  setSplitter( mySplit, parameters, sMap );  
+  if ( !area )
+    return;
 
-  // 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 )
+  QWidgetList wids = area->widgetList();
+  if ( wids.count() < 2 )
+    return;
+
+  QSplitter* s = splitter( area );
+  QList<QtxWorkstackArea*> areaList;
+  areas( s, areaList );
+
+  QList<QSplitter*> splitList;
+  splitters(s, splitList);
+
+  QSplitter* trg = 0;
+  if (areaList.count() + splitList.count() < 2 || s->orientation() == o)
+    trg = s;
+
+  if (!trg) trg = wrapSplitter(area);
+  if (!trg) return;
+
+  trg->setOrientation(o);
+
+  QtxWorkstackArea* newArea = createArea(0);
+  insertWidget(newArea, trg, area);
+
+  switch ( type )
   {
-    if ( (*delIt)->isEmpty() )
-      delete *delIt;
+  case SplitStay:
+    for ( QWidgetList::iterator itr = wids.begin(); itr != wids.end(); ++itr )
+    {
+      QWidget* wid_i = *itr;
+      if ( wid_i != wid )
+      {
+        area->removeWidget( wid_i );
+        newArea->insertWidget( wid_i );
+      }
+    }
+    break;
+  case SplitAt:
+    {
+      QWidgetList::iterator itr = wids.begin();
+      for ( ; itr != wids.end() && *itr != wid; ++itr )
+      {
+      }
+      for ( ; itr != wids.end(); ++itr )
+      {
+        area->removeWidget( *itr );
+        newArea->insertWidget( *itr );
+      }
+    }
+    break;
+  case SplitMove:
+    area->removeWidget( wid );
+    newArea->insertWidget( wid );
+    break;
   }
 
-  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);
+  distributeSpace( trg );
 }
 
 /*!
-  Example of string produced by operator>> :
-  "(splitter orientation=0 sizes=186:624 (views active='OCCViewer_0_0' 'OCCViewer_0_0')
-/ (views active='VTKViewer_0_0' 'VTKViewer_0_0'))"
-*/
-QtxWorkstack& QtxWorkstack::operator>>( QString& outParameters )
-{
-  splitterInfo( mySplit, outParameters );
-  return (*this);
-}
-
-
-class QtxWorkstackArea::WidgetEvent : public QEvent
-{
-public:
-  WidgetEvent( Type t, QWidget* w = 0 ) : QEvent( t ), myWidget( w ) {};
+ \brief Move widget(s) from the source workarea into the target workarea
+        or reorder widgets inside one workarea.
 
-  QWidget* widget() const { return myWidget; }
+ Move \a wid2 in target workarea. Put it right after \a wid1.
+ If \a all parameter is \c true, all widgets from source workarea
+ will be moved including \a wid2 and source workarea will be deleted then.
 
-private:
-  QWidget* myWidget;
-};
+ If \a wid1 and \a wid2 belongs to one workarea, widgets will be just reordered
+ in that workarea.
 
-/*!
-  Constructor
+ \param wid1 widget from target workarea
+ \param wid2 widget from source workarea
+ \param all  if \c true, all widgets from source workarea will
+             be moved into the target one, else only the \a wid2 will be moved
 */
-QtxWorkstackArea::QtxWorkstackArea( QWidget* parent )
-: QFrame( parent )
+void QtxWorkstack::Attract( QWidget* wid1, QWidget* wid2, const bool all )
 {
-  setFrameStyle( QFrame::Panel | QFrame::Sunken );
-
-  QVBoxLayout* base = new QVBoxLayout( this );
-  base->setMargin( frameWidth() );
-
-  QWidget* top = new QWidget( this );
-  base->addWidget( top );
-
-  QHBoxLayout* tl = new QHBoxLayout( top );
-  tl->setMargin( 0 );
-
-  myBar = new QtxWorkstackTabBar( top );
-  tl->addWidget( myBar, 1 );
-
-  QPushButton* close = new QPushButton( top );
-  close->setIcon( style()->standardIcon( QStyle::SP_TitleBarCloseButton ) );
-  close->setAutoDefault( true );
-  close->setFlat( true );
-  myClose = close;
-  tl->addWidget( myClose );
+  if ( !wid1 || !wid2 )
+    return;
 
-  myStack = new QStackedWidget( this );
+  // find area of the widgets
+  QtxWorkstackArea *area1 = 0, *area2 = 0;
+  QList<QtxWorkstackArea*> allAreas;
+  areas( mySplit, allAreas, true );
+  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !( area1 && area2 ); ++it )
+  {
+    if ( (*it)->contains( wid1 ) )
+      area1 = *it;
 
-  base->addWidget( myStack, 1 );
+    if ( (*it)->contains( wid2 ) )
+      area2 = *it;
+  }
 
-  connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) );
-  connect( myBar, SIGNAL( currentChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) );
-  connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) );
-  connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) );
+  if ( !area1 || !area2 )
+    return;
 
-  updateState();
+  QWidget* curWid = area1->activeWidget();
+  if ( !curWid )
+    return;
 
-  updateActiveState();
+  if ( area1 == area2 )
+  {
+    if ( all )
+    {
+      // Set wid1 at first position, wid2 at second
+      area1->insertWidget( wid1 );
+      area1->insertWidget( wid2, 1 );
+    }
+    else
+    {
+      // Set wid2 right after wid1
+      area1->removeWidget( wid2 );
+      int wid1_ind = 0;
+      QWidgetList wids1 = area1->widgetList();
+      for ( QWidgetList::iterator itr1 = wids1.begin(); itr1 != wids1.end() && *itr1 != wid1; ++itr1, ++wid1_ind );
+      area1->insertWidget( wid2, wid1_ind + 1 );
+    }
+  }
+  else
+  {
+    int wid1_ind = 0;
+    QWidgetList wids1 = area1->widgetList();
+    for ( QWidgetList::iterator itr1 = wids1.begin(); itr1 != wids1.end() && *itr1 != wid1; ++itr1, ++wid1_ind );
+    if ( all )
+    {
+      // Set wid2 right after wid1, other widgets from area2 right after wid2
+      QWidgetList wids2 = area2->widgetList();
+      QWidgetList::iterator itr2 = wids2.begin();
+      for ( int ind = wid1_ind + 1; itr2 != wids2.end(); ++itr2, ++ind )
+      {
+        area2->removeWidget( *itr2 );
+        if ( *itr2 == wid2 )
+          area1->insertWidget( *itr2, wid1_ind + 1 );
+        else
+          area1->insertWidget( *itr2, ind );
+      }
+    }
+    else
+    {
+      // Set wid2 right after wid1
+      area2->removeWidget( wid2 );
+      area1->insertWidget( wid2, wid1_ind + 1 );
+    }
+  }
 
-  QApplication::instance()->installEventFilter( this );
+  area1->setActiveWidget( curWid );
 }
 
 /*!
-  Destructor
+  \brief Calculate sizes of the splitter widget for the workarea.
+  \internal
 */
-QtxWorkstackArea::~QtxWorkstackArea()
+static void setSizes (QIntList& szList, const int item_ind,
+                      const int new_near, const int new_this, const int new_farr)
 {
-  QApplication::instance()->removeEventFilter( this );
+  // set size to all items before an item # <item_ind>
+  int cur_pos = 0;
+  QIntList::iterator its = szList.begin();
+  for (; its != szList.end() && cur_pos < item_ind; ++its, ++cur_pos) {
+    *its = new_near;
+  }
+  if (its == szList.end()) return;
+  // set size to item # <item_ind>
+  *its = new_this;
+  ++its;
+  // set size to all items after an item # <item_ind>
+  for (; its != szList.end(); ++its) {
+    *its = new_farr;
+  }
 }
 
 /*!
-  \return true if area is empty
-*/
-bool QtxWorkstackArea::isEmpty() const
-{
-  bool res = false;
-  for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it )
-    res = it.value().vis;
-  return !res;
-}
+  \brief Set position of the widget relatively to its parent splitter.
 
-/*!
-  Adds widget to area
-  \param wid widget
-  \param idx - index
+  Orientation of positioning will correspond to the splitter orientation.
+
+  \param wid widget
+  \param pos position relatively to the splitter; value in the range [0..1]
 */
-QWidget* QtxWorkstackArea::insertWidget( QWidget* wid, const int idx, Qt::WindowFlags f )
+void QtxWorkstack::SetRelativePositionInSplitter( QWidget* wid, const double position )
 {
-  if ( !wid )
-    return 0;
+  if ( position < 0.0 || 1.0 < position)
+    return;
 
-  int pos = myList.indexOf( wid );
-  if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) )
-    return 0;
+  if ( !wid )
+    return;
 
-  myList.removeAll( wid );
-  pos = idx < 0 ? myList.count() : idx;
-  myList.insert( qMin( pos, (int)myList.count() ), wid );
-  if ( !myInfo.contains( wid ) )
+  // find area of the given widget
+  QtxWorkstackArea* area = NULL;
+  QList<QtxWorkstackArea*> allAreas;
+  areas( mySplit, allAreas, true );
+  for ( QList<QtxWorkstackArea*>::iterator it = allAreas.begin(); it != allAreas.end() && !area; ++it )
   {
-    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() );
-
-    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( hided( QtxWorkstackChild* ) ), this, SLOT( onChildHided( QtxWorkstackChild* ) ) );
-    connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) );
-    connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) );
+    if ( (*it)->contains( wid ) )
+      area = *it;
   }
 
-  updateState();
+  if ( !area )
+    return;
 
-  setWidgetActive( wid );
-  wid->setFocus();
+  QSplitter* split = splitter( area );
+  if ( !split )
+    return;
 
-  return myChild[wid];
-}
+  // find index of the area in its splitter
+  int item_ind = -1;
+  bool isFound = false;
+  const QObjectList& was = split->children();
+  for ( QObjectList::const_iterator ito = was.begin(); ito != was.end() && !isFound; ++ito, ++item_ind )
+  {
+    if ( *ito == area )
+      isFound = true;
+  }
 
-/*!
-  Creates and shows popup menu for area
-  \param p - popup position
-*/
-void QtxWorkstackArea::onContextMenuRequested( QPoint p )
-{
-  const QtxWorkstackTabBar* bar = ::qobject_cast<const QtxWorkstackTabBar*>( sender() );
-  if ( !bar )
+  if ( !isFound || item_ind == 0 )
     return;
 
-  QWidget* wid = 0;
-  int idx = tabAt( p );
-  if ( idx != -1 )
-    wid = widget( myBar->tabId( idx ) );
+  QIntList szList = split->sizes();
+  int splitter_size = ( split->orientation() == Qt::Horizontal ? split->width() : split->height());
+  int nb = szList.count();
 
-  emit contextMenuRequested( wid, p );
+  int new_prev = int( splitter_size * position / item_ind );
+  int new_next = int( splitter_size * ( 1.0 - position ) / ( nb - item_ind ) );
+  setSizes( szList, item_ind, new_prev, new_next, new_next );
+  split->setSizes( szList );
 }
 
 /*!
-  SLOT: called when widget added to area is destroyed, removes widget from area
-*/
-void QtxWorkstackArea::onWidgetDestroyed()
-{
-  if ( sender() )
-    removeWidget( (QWidget*)sender(), false );
-}
+  \brief Set position of the widget relatively to the entire workstack.
 
-/*!
-  Removes widget from area
-  \param wid - widget
-  \param del - auto deleting
+  If \a o is \c Qt::Horizontal, the horizontal position of \a wid will be changed.
+  If \a o is \c Qt::Vertical, the vertical position of \a wid will be changed.
+
+  \param wid widget
+  \param o   orientation of positioning (\c Qt::Horizontal or \c Qt::Vertical)
+  \param pos position relatively to the workstack; value in range [0..1]
 */
-void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del )
+void QtxWorkstack::SetRelativePosition( QWidget* wid, const Qt::Orientation o,
+                                        const double position )
 {
-  if ( !myList.contains( wid ) )
+  if ( position < 0.0 || 1.0 < position )
     return;
 
-  if ( myBar->indexOf( widgetId( wid ) ) != -1 )
-    myBar->removeTab( myBar->indexOf( widgetId( wid ) ) );
-
-  myStack->removeWidget( child( wid ) );
-
-  myList.removeAll( wid );
-  myInfo.remove( wid );
-  myChild.remove( wid );
+  if ( !wid )
+    return;
 
-  if ( del )
-  {
-    delete child( wid );
-    if ( myList.isEmpty() )
-      delete this;
-    else
-      updateState();
+  int splitter_size = o == Qt::Horizontal ? mySplit->width() : mySplit->height();
+  int need_pos = int( position * splitter_size );
+  int splitter_pos = 0;
+
+  if ( setPosition( wid, mySplit, o, need_pos, splitter_pos ) != 0 )
+  {
+    // impossible to set required position
   }
-  else
-    updateState();
 }
 
 /*!
-  \return list of visible widgets
+  \brief Set accelerator key-combination for the action with specified \a id.
+  \param id action ID
+  \param accel action accelerator
 */
-QWidgetList QtxWorkstackArea::widgetList() const
+void QtxWorkstack::setAccel( const int id, const int accel )
 {
-  QWidgetList lst;
-  for ( QWidgetList::const_iterator it = myList.begin(); it != myList.end(); ++it )
-  {
-    if ( widgetVisibility( *it ) )
-      lst.append( *it );
-  }
-  return lst;
+  if ( !myActionsMap.contains( id ) )
+    return;
+
+  myActionsMap[id]->setShortcut( accel );
 }
 
 /*!
-  \return active widget
+  \brief Get the action's accelerator key-combination.
+  \param id action ID
+  \return action accelerator
 */
-QWidget* QtxWorkstackArea::activeWidget() const
+int QtxWorkstack::accel( const int id ) const
 {
-  return widget( myBar->tabId( myBar->currentIndex() ) );
+  int res = 0;
+  if ( myActionsMap.contains( id ) )
+    res = myActionsMap[id]->shortcut();
+  return res;
 }
 
 /*!
-  Sets widget as active
-  \param wid - widget
+  \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 
+  context popup menu. Other actions will not be shown.
+
+  \param flags ORed together actions flags
 */
-void QtxWorkstackArea::setActiveWidget( QWidget* wid )
+void QtxWorkstack::setMenuActions( const int flags )
 {
-  myBar->setCurrentIndex( myBar->indexOf( widgetId( wid ) ) );
+  myActionsMap[SplitVertical]->setVisible( flags & SplitVertical );
+  myActionsMap[SplitHorizontal]->setVisible( flags & SplitHorizontal );
+  myActionsMap[Close]->setVisible( flags & Close );
+  myActionsMap[Rename]->setVisible( flags & Rename );
 }
 
 /*!
-  \return true if area contains widget
-  \param wid - widget
+  \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 
+  context popup menu. Other actions will not be shown.
+
+  \param flags ORed together actions flags
 */
-bool QtxWorkstackArea::contains( QWidget* wid ) const
+int QtxWorkstack::menuActions() const
 {
-  return myList.contains( wid );
+  int ret = 0;
+  ret = ret | ( myActionsMap[SplitVertical]->isVisible() ? SplitVertical : 0 );
+  ret = ret | ( myActionsMap[SplitHorizontal]->isVisible() ? SplitHorizontal : 0 );
+  ret = ret | ( myActionsMap[Close]->isVisible() ? Close : 0 );
+  ret = ret | ( myActionsMap[Rename]->isVisible() ? Rename : 0 );
+  return ret;
 }
 
 /*!
-  Shows area
+  \brief Calculate sizes of the splitter widget for the workarea.
+  \internal
 */
-void QtxWorkstackArea::setVisible( bool on )
+static int positionSimple (QIntList& szList, const int nb, const int splitter_size,
+                           const int item_ind, const int item_rel_pos,
+                           const int need_pos, const int splitter_pos)
 {
-  QMap<QWidget*, bool> map;
-  for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it )
-  {
-    map.insert( *it, isBlocked( *it ) );
-    setBlocked( *it, true );
+  if (item_ind == 0) { // cannot move in this splitter
+    return (need_pos - splitter_pos);
   }
 
-  QFrame::setVisible( on );
-
-  for ( QWidgetList::iterator itr = myList.begin(); itr != myList.end(); ++itr )
-    setBlocked( *itr, map.contains( *itr ) ? map[*itr] : false );
-}
+  int delta = 0;
+  int new_prev = 0;
+  int new_this = szList[item_ind];
+  int new_next = 0;
 
-/*!
-  \return true if area is active
-*/
-bool QtxWorkstackArea::isActive() const
-{
-  QtxWorkstack* ws = workstack();
-  if ( !ws )
-    return false;
+  bool isToCheck = false;
 
-  return ws->activeArea() == this;
-}
+  if (need_pos < splitter_pos) {
+    // Set size of all previous workareas to zero <--
+    if (item_ind == nb - 1) {
+      // item iz last in the splitter, it will occupy all the splitter
+      new_this = splitter_size;
+    } else {
+      // recompute size of next items in splitter
+      new_next = (splitter_size - new_this) / (nb - item_ind - 1);
+    }
+    delta = need_pos - splitter_pos;
 
-/*!
-  Update active state of tab bar
-*/
-void QtxWorkstackArea::updateActiveState()
-{
-  myBar->setActive( isActive() );
-}
+  } else if (need_pos > (splitter_pos + splitter_size)) {
+    // Set size of all next workareas to zero -->
+    // recompute size of previous items in splitter
+    new_this = 0;
+    new_prev = (splitter_size - new_this) / item_ind;
+    delta = need_pos - (splitter_pos + splitter_size - new_this);
 
-/*!
-  \return corresponding workstack
-*/
-QtxWorkstack* QtxWorkstackArea::workstack() const
-{
-  QtxWorkstack* ws = 0;
-  QWidget* wid = parentWidget();
-  while ( wid && !ws )
-  {
-    if ( wid->inherits( "QtxWorkstack" ) )
-      ws = (QtxWorkstack*)wid;
-    wid = wid->parentWidget();
+  } else { // required position lays inside this splitter
+    // Move workarea inside splitter into required position <->
+    int new_item_rel_pos = need_pos - splitter_pos;
+    new_prev = new_item_rel_pos / item_ind;
+    if (need_pos < (splitter_pos + item_rel_pos)) {
+      // Make previous workareas smaller, next - bigger
+      // No problem to keep old size of the widget
+    } else {
+      // Make previous workareas bigger, next - smaller
+      if (new_this > splitter_size - new_item_rel_pos) {
+        new_this = splitter_size - new_item_rel_pos;
+      }
+      // jfa to do: in this case fixed size of next widgets could prevent right resizing
+      isToCheck = true;
+    }
+    if (item_ind == nb - 1) {
+      new_this = splitter_size - new_item_rel_pos;
+    } else {
+      new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
+    }
+    delta = 0;
   }
-  return ws;
+
+  setSizes (szList, item_ind, new_prev, new_this, new_next);
+  return delta;
 }
 
 /*!
-  Custom event filter
+  \brief Set position of the widget.
+
+  Called from SetRelativePosition() public method.
+
+  \param wid   widget to be moved
+  \param split currently processed splitter (goes from more common
+               to more particular splitter in recursion calls)
+  \param o     orientation of positioning
+  \param need_pos required position of the given widget in pixels
+               (from top/left side of workstack area)
+  \param splitter_pos position of the splitter \a split
+               (from top/left side of workstack area)
+  \return difference between a required and a distinguished position
 */
-bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e )
+int QtxWorkstack::setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
+                               const int need_pos, const int splitter_pos )
 {
-  if ( o->isWidgetType() )
+  if ( !wid || !split )
+    return need_pos - splitter_pos;
+
+  // Find corresponding sub-splitter.
+  // Find also index of appropriate item in current splitter.
+  int cur_ind = 0, item_ind = 0;
+  bool isBottom = false, isFound = false;
+  QSplitter* sub_split = NULL;
+  const QObjectList& objs = split->children();
+  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end() && !isFound; ++it )
   {
-    QWidget* wid = (QWidget*)o;
-    if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress )
+    QtxWorkstackArea* area = ::qobject_cast<QtxWorkstackArea*>( *it );
+    if ( area )
     {
-      bool ok = false;
-      while ( !ok && wid && wid != myClose )
+      if ( area->contains( wid ) )
       {
-        ok = wid == this;
-        wid = wid->parentWidget();
+        item_ind = cur_ind;
+        isBottom = true;
+        isFound = true;
       }
-      if ( ok )
-        QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) );
+      cur_ind++;
+    }
+    else if ( (*it)->inherits( "QSplitter" ) )
+    {
+      QList<QtxWorkstackArea*> areaList;
+      areas( (QSplitter*)(*it), areaList, true );
+      for ( QList<QtxWorkstackArea*>::iterator ita = areaList.begin(); ita != areaList.end() && !isFound; ++ita )
+      {
+        if ( (*ita)->contains( wid ) )
+        {
+          item_ind = cur_ind;
+          isFound = true;
+          sub_split = (QSplitter*)*it;
+        }
+      }
+      cur_ind++;
     }
   }
-  return false;
-}
 
-/*!
-  \return rectangle of area in order to draw drop rectangle on area
-*/
-QRect QtxWorkstackArea::floatRect() const
-{
-  QRect r = myStack->geometry();
-  return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) );
-}
+  if ( !isFound )
+    return ( need_pos - splitter_pos );
 
-/*!
-  \return rectangle of tab in order to draw drop rectangle on tab
-  \param idx - tab index
-*/
-QRect QtxWorkstackArea::floatTab( const int idx ) const
-{
-  QRect r = myBar->tabRect( idx );
-  return QRect( myBar->mapToGlobal( r.topLeft() ), r.size() );
-}
+  if ( split->orientation() == o )
+  {
+    // Find coordinates of near and far sides of the appropriate item relatively current splitter
+    int splitter_size = ( o == Qt::Horizontal ? split->width() : split->height() );
+    QIntList szList = split->sizes();
+    int nb = szList.count();
+    int item_rel_pos = 0; // position of near side of item relatively this splitter
+    for (int i = 0; i < item_ind; i++) {
+      item_rel_pos += szList[i];
+    }
+    int item_size = szList[item_ind]; // size of item
+    int item_pos = splitter_pos + item_rel_pos;
+
+    // Resize splitter items to complete the conditions
+    if (isBottom) {
+      // I. Bottom of splitters stack reached
+
+      int delta = positionSimple(szList, nb, splitter_size, item_ind, item_rel_pos, need_pos, splitter_pos);
+      split->setSizes(szList);
+      // Recompute delta, as some windows can reject given size
+      int new_item_rel_pos = 0;
+      QIntList szList1 = split->sizes();
+      for (int i = 0; i < item_ind; i++) {
+        new_item_rel_pos += szList1[i];
+      }
+      delta = need_pos - (splitter_pos + new_item_rel_pos);
+      return delta;
+
+    } else {
+      // II. Bottom of splitters stack is not yet reached
+
+      if (item_ind == 0) { // cannot move in this splitter
+        // Process in sub-splitter
+        return setPosition(wid, sub_split, o, need_pos, splitter_pos);
+      }
+
+      int new_prev = 0;
+      int new_this = szList[item_ind];
+      int new_next = 0;
+
+      if (need_pos < splitter_pos) {
+        // Set size of all previous workareas to zero <--
+        if (item_ind == nb - 1) {
+          new_this = splitter_size;
+        } else {
+          new_next = (splitter_size - new_this) / (nb - item_ind - 1);
+        }
+        setSizes (szList, item_ind, new_prev, new_this, new_next);
+        split->setSizes(szList);
+        // Recompute splitter_pos, as some windows can reject given size
+        int new_item_rel_pos = 0;
+        QIntList szList1 = split->sizes();
+        for (int i = 0; i < item_ind; i++) {
+          new_item_rel_pos += szList1[i];
+        }
+        // Process in sub-splitter
+        return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
+      } else if (need_pos > (splitter_pos + splitter_size)) {
+        // Set size of all next workareas to zero -->
+        new_prev = (splitter_size - new_this) / item_ind;
+        setSizes (szList, item_ind, new_prev, new_this, new_next);
+        split->setSizes(szList);
+        // Recompute splitter_pos, as some windows can reject given size
+        int new_item_rel_pos = 0;
+        QIntList szList1 = split->sizes();
+        for (int i = 0; i < item_ind; i++) {
+          new_item_rel_pos += szList1[i];
+        }
+        // Process in sub-splitter
+        return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
+      } else {
+        // Set appropriate size of all previous/next items <->
+        int new_item_rel_pos = item_rel_pos;
+        if (need_pos < item_pos || (item_pos + item_size) < need_pos) {
+          // Move item inside splitter into required position <->
+          int new_this = szList[item_ind];
+          int new_next = 0;
+          new_item_rel_pos = need_pos - splitter_pos;
+          if ((item_pos + item_size) < need_pos) {
+            //new_item_rel_pos = need_pos - (item_pos + item_size);
+            new_item_rel_pos = item_rel_pos + (need_pos - (item_pos + item_size));
+          }
+          int new_prev = new_item_rel_pos / item_ind;
+          if (need_pos < (splitter_pos + item_rel_pos)) {
+            // Make previous workareas smaller, next - bigger
+            // No problem to keep old size of the widget
+          } else {
+            // Make previous workareas bigger, next - smaller
+            if (new_this > splitter_size - new_item_rel_pos) {
+              new_this = splitter_size - new_item_rel_pos;
+            }
+          }
+          if (item_ind == nb - 1) {
+            new_this = splitter_size - new_item_rel_pos;
+          } else {
+            new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
+          }
+          setSizes (szList, item_ind, new_prev, new_this, new_next);
+          split->setSizes(szList);
+          // Recompute new_item_rel_pos, as some windows can reject given size
+          new_item_rel_pos = 0;
+          QIntList szList1 = split->sizes();
+          for (int i = 0; i < item_ind; i++) {
+            new_item_rel_pos += szList1[i];
+          }
+        } else {
+          // Do nothing
+        }
+        // Process in sub-splitter
+        int add_pos = setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
+        if (add_pos == 0)
+          return 0;
 
-/*!
-  \return tab covering point 
-  \param p - point
-*/
-int QtxWorkstackArea::tabAt( const QPoint& pnt ) const
-{
-  int idx = -1;
-  QPoint p = myBar->mapFromGlobal( pnt );
-  for ( int i = 0; i < myBar->count() && idx == -1; i++ )
-  {
-    QRect r = myBar->tabRect( i );
-    if ( r.isValid() && r.contains( p ) )
-      idx = i;
-  }
-  return idx;
-}
+        // this can be if corresponding workarea is first in sub-splitter
+        // or sub-splitter has another orientation
 
-/*!
-  Event handler for custom events
-*/
-void QtxWorkstackArea::customEvent( QEvent* e )
-{
-  WidgetEvent* we = (WidgetEvent*)e;
+        // Resize ones again to reach precize position <->
+        int need_pos_1 = splitter_pos + new_item_rel_pos + add_pos;
 
-  switch ( we->type() )
-  {
-  case ActivateWidget:
-    emit activated( activeWidget() );
-    break;
-  case FocusWidget:
-    if ( activeWidget() )
-    {
-      if ( !activeWidget()->focusWidget() )
-        activeWidget()->setFocus();
-      else
-      {
-        if ( activeWidget()->focusWidget()->hasFocus() )
-        {
-          QFocusEvent in( QEvent::FocusIn );
-               QApplication::sendEvent( this, &in );
-             }
-        else
-          activeWidget()->focusWidget()->setFocus();
+        // Move workarea inside splitter into required position <->
+        int delta_1 = positionSimple(szList, nb, splitter_size, item_ind,
+                                     new_item_rel_pos, need_pos_1, splitter_pos);
+        split->setSizes(szList);
+        // Recompute new_item_rel_pos, as some windows can reject given size
+        new_item_rel_pos = 0;
+        QIntList szList1 = split->sizes();
+        for (int i = 0; i < item_ind; i++) {
+          new_item_rel_pos += szList1[i];
+        }
+        delta_1 = need_pos_1 - (splitter_pos + new_item_rel_pos);
+        return delta_1;
       }
     }
-    break;
-  case RemoveWidget:
-    removeWidget( we->widget() );
-    break;
-  default:
-    break;
+  } else {
+    return setPosition(wid, sub_split, o, need_pos, splitter_pos);
   }
-}
-
-/*!
-  Custom focus in event handler
-*/
-void QtxWorkstackArea::focusInEvent( QFocusEvent* e )
-{
-  QFrame::focusInEvent( e );
 
-  emit activated( activeWidget() );
+  return 0;
 }
 
 /*!
-  Custom mouse press event handler
+  \brief Redistribute space among widgets equally.
+  \param split splitter
 */
-void QtxWorkstackArea::mousePressEvent( QMouseEvent* e )
+void QtxWorkstack::distributeSpace( QSplitter* split ) const
 {
-  QFrame::mousePressEvent( e );
+  if ( !split )
+    return;
 
-  emit activated( activeWidget() );
+  QIntList szList = split->sizes();
+  int size = ( split->orientation() == Qt::Horizontal ?
+               split->width() : split->height() ) / szList.count();
+  for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it )
+    *it = size;
+  split->setSizes( szList );
 }
 
 /*!
-  SLOT: called if button close is pressed
+  \brief Split widgets vertically.
 */
-void QtxWorkstackArea::onClose()
+void QtxWorkstack::splitVertical()
 {
-  QWidget* wid = activeWidget();
-  if ( wid )
-    wid->close();
+  split( Qt::Horizontal );
 }
 
 /*!
-  SLOT: called if tab page is selected
+  \brief Split widgets horizontally.
 */
-void QtxWorkstackArea::onCurrentChanged( int )
+void QtxWorkstack::splitHorizontal()
 {
-  updateCurrent();
-
-  emit activated( activeWidget() );
+  split( Qt::Vertical );
 }
 
 /*!
-  SLOT: called if active tab page is dragged
+  \brief Called when user activates "Rename" menu item.
+
+  Changes widget title.
 */
-void QtxWorkstackArea::onDragActiveTab()
+void QtxWorkstack::onRename()
 {
-  QtxWorkstackChild* c = child( activeWidget() );
-  if ( !c )
+  if ( !myWorkWin )
     return;
 
-  new QtxWorkstackDrag( workstack(), c );
+  bool ok = false;
+  QString newName = QInputDialog::getText( topLevelWidget(),  tr( "Rename" ), tr( "Enter new name:" ),
+                                           QLineEdit::Normal, myWorkWin->windowTitle(), &ok );
+  if ( ok && !newName.isEmpty() )
+    myWorkWin->setWindowTitle( newName );
 }
 
 /*!
-  SLOT: called on child is destroyed, removes from area
+  \brief Wrap area into the new splitter.
+  \param workarea
+  \return new splitter
 */
-void QtxWorkstackArea::onChildDestroyed( QObject* obj )
+QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area )
 {
-  QtxWorkstackChild* child = (QtxWorkstackChild*)obj;
-  myStack->removeWidget( child );
+  if ( !area )
+    return 0;
 
-  QWidget* wid = 0;
-  for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it )
-  {
-    if ( it.value() == child )
-      wid = it.key();
-  }
+  QSplitter* pSplit = splitter( area );
+  if ( !pSplit )
+    return 0;
 
-  myChild.remove( wid );
+  bool upd = pSplit->updatesEnabled();
+  pSplit->setUpdatesEnabled( false );
 
-  QApplication::postEvent( this, new WidgetEvent( (QEvent::Type)RemoveWidget, wid ) );
-}
+  QIntList szList = pSplit->sizes();
 
-/*!
-  SLOT: called on child is shown
-*/
-void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
-{
-  setWidgetShown( c->widget(), true );
-}
+  QSplitter* wrap = new QSplitter( 0 );
+  wrap->setChildrenCollapsible( false );
+  pSplit->insertWidget( pSplit->indexOf( area ) + 1, wrap );
+  wrap->setVisible( true );
+  wrap->addWidget( area );
 
-/*!
-  SLOT: called on child is hidden
-*/
-void QtxWorkstackArea::onChildHided( QtxWorkstackChild* c )
-{
-  setWidgetShown( c->widget(), false );
-}
+  pSplit->setSizes( szList );
 
-/*!
-  SLOT: called on child is activated
-*/
-void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c )
-{
-  setWidgetActive( c->widget() );
-}
+  pSplit->setUpdatesEnabled( upd );
 
-/*!
-  SLOT: called on child caption is changed
-*/
-void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c )
-{
-  updateTab( c->widget() );
+  return wrap;
 }
 
 /*!
-  Raises widget when active tab is changed
+  \brief Reparent and add widget.
+  \param wid widget
+  \param pWid parent widget
+  \param after widget after which \a wid should be added
 */
-void QtxWorkstackArea::updateCurrent()
+void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after )
 {
-  QMap<QWidget*, bool> map;
-  for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it )
+  if ( !wid || !pWid )
+    return;
+
+  QWidgetList moveList;
+  const QObjectList& lst = pWid->children();
+  bool found = false;
+  for ( QObjectList::const_iterator it = lst.begin(); it != lst.end(); ++it )
   {
-    map.insert( *it, isBlocked( *it ) );
-    setBlocked( *it, true );
+    if ( found && ( (*it)->inherits( "QSplitter" ) ||
+                    (*it)->inherits( "QtxWorkstackArea" ) ) )
+      moveList.append( (QWidget*)(*it) );
+    if ( *it == after )
+      found = 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 );
-}
-
-/*!
-  Updates tab
-  \param wid - tab widget
-*/
-void QtxWorkstackArea::updateTab( QWidget* wid )
-{
-  int idx = myBar->indexOf( widgetId( wid ) );
-  if ( idx < 0 )
-    return;
+  QMap<QWidget*, bool> map;
+  for ( QWidgetList::iterator it = moveList.begin(); it != moveList.end(); ++it )
+  {
+    map.insert( *it, (*it)->isVisibleTo( (*it)->parentWidget() ) );
+    (*it)->setParent( 0 );
+    (*it)->hide();
+  }
 
-  myBar->setTabIcon( idx, wid->windowIcon() );
-  myBar->setTabText( idx, wid->windowTitle() );
-}
+  wid->setParent( pWid );
 
-/*!
-  \return widget
-  \param id - widget id
-*/
-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();
+  for ( QWidgetList::iterator itr = moveList.begin(); itr != moveList.end(); ++itr )
+  {
+    (*itr)->setParent( pWid );
+    (*itr)->setShown( map.contains( *itr ) ? map[*itr] : false );
   }
-  return wid;
 }
 
 /*!
-  \return widget id
-  \param wid - widget
+  \brief Close active window.
 */
-int QtxWorkstackArea::widgetId( QWidget* wid ) const
+void QtxWorkstack::onCloseWindow()
 {
-  int id = -1;
-  if ( myInfo.contains( wid ) )
-    id = myInfo[wid].id;
-  return id;
+  if ( myWorkWin )
+    myWorkWin->close();
+  else if( activeWindow() )
+    activeWindow()->close();
 }
 
 /*!
-  \return true if widget is visible
-  \param wid - widget
-*/
-bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const
-{
-  bool res = false;
-  if ( myInfo.contains( wid ) )
-    res = myInfo[wid].vis;
-  return res;
-}
+  \brief Called when workarea is destroyed.
 
-/*!
-  Sets widget as active
-  \param wid - widget
+  Set input focus to the neighbour area.
+
+  \param obj workarea being destroyed
 */
-void QtxWorkstackArea::setWidgetActive( QWidget* wid )
+void QtxWorkstack::onDestroyed( QObject* obj )
 {
-  int id = widgetId( wid );
-  if ( id < 0 )
-    return;
+  QtxWorkstackArea* area = (QtxWorkstackArea*)obj;
 
-  myBar->setCurrentIndex( myBar->indexOf( id ) );
+  if ( area == myArea )
+    myArea = 0;
+
+  if ( !myArea )
+  {
+    QtxWorkstackArea* cur = neighbourArea( area );
+    if ( cur )
+      cur->setFocus();
+  }
+
+  QApplication::postEvent( this, new QEvent( QEvent::User ) );
 }
 
 /*!
-  Shows/hides widget
-  \param wid - widget
-  \param on - new shown state
+  \brief Called on window activating.
+  \param area workarea being activated (not used)
 */
-void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on )
+void QtxWorkstack::onWindowActivated( QWidget* /*area*/ )
 {
-  if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on )
+  const QObject* obj = sender();
+  if ( !obj->inherits( "QtxWorkstackArea" ) )
     return;
 
-  myInfo[wid].vis = on;
-  updateState();
+  setActiveArea( (QtxWorkstackArea*)obj );
 }
 
 /*!
-  Update
+  \brief Called on window deactivating.
+  \param area workarea being deactivated
 */
-void QtxWorkstackArea::updateState()
+void QtxWorkstack::onDeactivated( QtxWorkstackArea* area )
 {
-  bool updBar = myBar->updatesEnabled();
-  bool updStk = myStack->updatesEnabled();
-  myBar->setUpdatesEnabled( false );
-  myStack->setUpdatesEnabled( false );
-
-  bool block = myBar->signalsBlocked();
-  myBar->blockSignals( true );
-
-  QWidget* prev = activeWidget();
+  if ( myArea != area )
+    return;
 
-  int idx = 0;
-  for ( QWidgetList::iterator it = myList.begin(); it != myList.end(); ++it )
-  {
-    QWidget* wid = *it;
-    int id = widgetId( wid );
+  QList<QtxWorkstackArea*> lst;
+  areas( mySplit, lst, true );
 
-    if ( id < 0 )
-      continue;
+  int idx = lst.indexOf( area );
+  if ( idx == -1 )
+    return;
 
-    bool vis = widgetVisibility( wid );
+  myWin = 0;
+  myArea = 0;
 
-    int cIdx = myBar->indexOf( id );
-    if ( cIdx != -1 && ( !vis || myBar->indexOf( id ) != idx ) )
-      myBar->removeTab( cIdx );
+  QtxWorkstackArea* newArea = neighbourArea( area );
+  if ( newArea && newArea->activeWidget() )
+    newArea->activeWidget()->setFocus();
 
-    if ( myBar->indexOf( id ) == -1 && vis )
-      myBar->setTabId( myBar->insertTab( idx, wid->windowTitle() ), id );
+  QApplication::postEvent( this, new QEvent( QEvent::User ) );
+}
 
-    updateTab( wid );
+/*!
+  \brief Create and show popup menu for workarea.
+  \param w workarea
+  \param p popup position
+*/
+void QtxWorkstack::onContextMenuRequested( QWidget* w, QPoint p )
+{
+  QtxWorkstackArea* anArea = ::qobject_cast<QtxWorkstackArea*>( (QObject*)sender() );
+  if ( !anArea )
+    anArea = activeArea();
 
-    bool block = isBlocked( wid );
-    setBlocked( wid, true );
+  if ( !anArea )
+    return;
 
-    QtxWorkstackChild* cont = child( wid );
+  QWidgetList lst = anArea->widgetList();
+  if ( lst.isEmpty() )
+    return;
 
-    if ( !vis )
-      myStack->removeWidget( cont );
-    else if ( myStack->indexOf( cont ) < 0 )
-      myStack->addWidget( cont );
+  myWorkWin = w;
+  myWorkArea = anArea;
 
-    if ( vis )
-      idx++;
+  QMenu* pm = new QMenu();
 
-    setBlocked( wid, block );
+  if ( lst.count() > 1 )
+  {
+    if ( myActionsMap[SplitVertical]->isEnabled() )
+      pm->addAction( myActionsMap[SplitVertical] );
+    if ( myActionsMap[SplitHorizontal]->isEnabled() )
+      pm->addAction( myActionsMap[SplitHorizontal] );
+    pm->addSeparator();
   }
 
-  int curId = widgetId( prev );
-  if ( myBar->indexOf( curId ) < 0 )
+  if ( w )
   {
-    QWidget* wid = 0;
-    int pos = myList.indexOf( prev );
-    for ( int i = pos - 1; i >= 0 && !wid; i-- )
-    {
-      if ( widgetVisibility( myList.at( i ) ) )
-        wid = myList.at( i );
-    }
-
-    for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ )
-    {
-      if ( widgetVisibility( myList.at( j ) ) )
-        wid = myList.at( j );
-    }
-
-    if ( wid )
-      curId = widgetId( wid );
+    if ( myActionsMap[Close]->isEnabled() )
+      pm->addAction( myActionsMap[Close] );
+    if ( myActionsMap[Rename]->isEnabled() )
+      pm->addAction( myActionsMap[Rename] );
   }
 
-  myBar->setCurrentIndex( myBar->indexOf( curId ) );
+  Qtx::simplifySeparators( pm );
 
-  myBar->blockSignals( block );
+  if ( !pm->actions().isEmpty() )
+    pm->exec( p );
 
-  updateCurrent();
+  delete pm;
 
-  myBar->updateActiveState();
+  myWorkWin = 0;
+  myWorkArea = 0;
+}
 
-  myBar->setUpdatesEnabled( updBar );
-  myStack->setUpdatesEnabled( updStk );
-  if ( updBar )
-    myBar->update();
-  if ( updStk )
-    myStack->update();
+/*!
+  \brief Add child widget.
+  \param w widget
+  \param f widget flags
+  \return child widget container
+*/
+QWidget* QtxWorkstack::addWindow( QWidget* w, Qt::WindowFlags f )
+{
+  if ( !w )
+    return 0;
 
-  QResizeEvent re( myBar->size(), myBar->size() );
-  QApplication::sendEvent( myBar, &re );
+  return targetArea()->insertWidget( w, -1, f );
+}
 
-  if ( isEmpty() )
-  {
-    hide();
-    emit deactivated( this );
-  }
-  else
-  {
-    show();
-    if ( prev != activeWidget() )
-      emit activated( activeWidget() );
-  }
+/*!
+  \brief Handle custom events.
+  \param e custom event (not used)
+*/
+void QtxWorkstack::customEvent( QEvent* /*e*/ )
+{
+  updateState();
 }
 
 /*!
-  \return first unshared widget id
+  \brief Get splitter corresponding to the workarea.
+  \param workarea
+  \return splitter corresponding to the workarea
 */
-int QtxWorkstackArea::generateId() const
+QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const
 {
-  QMap<int, int> map;
+  if ( !area )
+    return 0;
 
-  for ( WidgetInfoMap::const_iterator it = myInfo.begin(); it != myInfo.end(); ++it )
-    map.insert( it.value().id, 0 );
+  QSplitter* split = 0;
 
-  int id = 0;
-  while ( map.contains( id ) )
-    id++;
+  QWidget* wid = area->parentWidget();
+  if ( wid && wid->inherits( "QSplitter" ) )
+    split = (QSplitter*)wid;
 
-  return id;
+  return split;
 }
 
 /*!
-  \return true if widget is blocked
-  \param wid - widget
+  \brief Get list of child splitters.
+  \param split parent splitter
+  \param splitList list to be filled with child splitters
+  \param rec if \c true, perform recursive search of children
 */
-bool QtxWorkstackArea::isBlocked( QWidget* wid ) const
+void QtxWorkstack::splitters( QSplitter* split, QList<QSplitter*>& splitList, const bool rec ) const
 {
-  return myBlock.contains( wid );
+  if ( !split )
+    return;
+
+  const QObjectList& objs = split->children();
+  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
+  {
+    if ( rec )
+      splitters( (QSplitter*)*it, splitList, rec );
+    if ( (*it)->inherits( "QSplitter" ) )
+      splitList.append( (QSplitter*)*it );
+  }
 }
 
 /*!
-  Blocks widget
-  \param wid - widget
-  \param on - new blocked state
+  \brief Get list of child workareas.
+  \param split parent splitter
+  \param areaList list to be filled with child workareas
+  \param rec if \c true, perform recursive search of children
 */
-void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on )
+void QtxWorkstack::areas( QSplitter* split, QList<QtxWorkstackArea*>& areaList, const bool rec ) const
 {
-  if ( on )
-    myBlock.insert( wid, 0 );
-  else
-    myBlock.remove( wid );
+  if ( !split )
+    return;
+
+  const QObjectList& objs = split->children();
+  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
+  {
+    if ( (*it)->inherits( "QtxWorkstackArea" ) )
+      areaList.append( (QtxWorkstackArea*)*it );
+    else if ( rec && (*it)->inherits( "QSplitter" ) )
+      areas( (QSplitter*)*it, areaList, rec );
+  }
 }
 
 /*!
-  \return child corresponding to widget
-  \param wid - widget
+  \brief Get active workarea.
+  \return active workarea
 */
-QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const
+QtxWorkstackArea* QtxWorkstack::activeArea() const
 {
-  QtxWorkstackChild* res = 0;
-  if ( myChild.contains( wid ) )
-    res = myChild[wid];
-  return res;
+  return myArea;
 }
 
 /*!
-  Constructor
+  \brief Get target area (for which the current operation should be done).
+
+  Returns active workarea or current area (if there is no active workarea).
+  If there are no workareas, create new workarea and return it.
+
+  \return workarea
 */
-QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent, Qt::WindowFlags f )
-: QWidget( parent ),
-myWidget( wid )
+QtxWorkstackArea* QtxWorkstack::targetArea()
 {
-  myWidget->setParent( this, f );
-  myWidget->installEventFilter( this );
-  QVBoxLayout* base = new QVBoxLayout( this );
-  base->addWidget( myWidget );
+  QtxWorkstackArea* area = activeArea();
+  if ( !area )
+    area = currentArea();
+  if ( !area )
+  {
+    QList<QtxWorkstackArea*> lst;
+    areas( mySplit, lst );
+    if ( !lst.isEmpty() )
+      area = lst.first();
+  }
 
-  connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+  if ( !area )
+    area = createArea( mySplit );
+
+  return area;
 }
 
 /*!
-  Destructor
-*/
-QtxWorkstackChild::~QtxWorkstackChild()
-{
-  QApplication::instance()->removeEventFilter( this );
-
-  if ( !widget() )
-    return;
+  \brief Get current workarea.
 
-  disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
+  Current workarea is that one which has input focus.
 
-  widget()->hide();
-  widget()->removeEventFilter( this );
+  \return current area
+*/
+QtxWorkstackArea* QtxWorkstack::currentArea() const
+{
+  QtxWorkstackArea* area = 0;
+  QWidget* wid = focusWidget();
+  while ( wid && !area )
+  {
+    if ( wid->inherits( "QtxWorkstackArea" ) )
+      area = (QtxWorkstackArea*)wid;
+    wid = wid->parentWidget();
+  }
 
-  widget()->setParent( 0 );
+  return area;
 }
 
 /*!
-  \return corresponding widget
+  \brief Create new workarea.
+  \param parent parent widget
+  \return created workarea
 */
-QWidget* QtxWorkstackChild::widget() const
+QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const
 {
-  return myWidget;
+  QtxWorkstackArea* area = new QtxWorkstackArea( parent );
+
+  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 ) ) );
+  connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) );
+
+  return area;
 }
 
 /*!
-  Custom event filter
+  \brief Set active workarea.
+  \param workarea
 */
-bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e )
+void QtxWorkstack::setActiveArea( QtxWorkstackArea* area )
 {
-  if ( o->isWidgetType() )
-  {
-    if ( e->type() == QEvent::WindowTitleChange || e->type() == QEvent::WindowIconChange )
-      emit captionChanged( this );
+  QWidget* oldCur = myWin;
 
-    if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
-      emit shown( this );
+  QtxWorkstackArea* oldArea = myArea;
 
-    if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
-      emit hided( this );
+  myArea = area;
 
-    if ( e->type() == QEvent::FocusIn )
-      emit activated( this );
+  if ( myArea != oldArea )
+  {
+    if ( oldArea )
+      oldArea->updateActiveState();
+    if ( myArea )
+      myArea->updateActiveState();
   }
-  return QWidget::eventFilter( o, e );
+
+  if ( myArea )
+    myWin = myArea->activeWidget();
+
+  if ( myWin && oldCur != myWin )
+    emit windowActivated( myWin );
 }
 
 /*!
-  SLOT: called on object is destroyed
+  \brief Get workarea which is nearest to \a area.
+  \param area area for which neighbour is searched
+  \return neighbour area (or 0 if not found)
 */
-void QtxWorkstackChild::onDestroyed( QObject* obj )
+QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const
 {
-  if ( obj != widget() )
-    return;
+  QList<QtxWorkstackArea*> lst;
+  areas( mySplit, lst, true );
+  int pos = lst.indexOf( area );
+  if ( pos < 0 )
+    return 0;
 
-  myWidget = 0;
-  deleteLater();
+  QtxWorkstackArea* na = 0;
+  for ( int i = pos - 1; i >= 0 && !na; i-- )
+  {
+    if ( !lst.at( i )->isEmpty() )
+      na = lst.at( i );
+  }
+
+  for ( int j = pos + 1; j < (int)lst.count() && !na; j++ )
+  {
+    if ( !lst.at( j )->isEmpty() )
+        na = lst.at( j );
+  }
+  return na;
 }
 
 /*!
-  Custom child event handler
+  \brief Get workarea covering point.
+  \return workarea
+  \param p point
 */
-void QtxWorkstackChild::childEvent( QChildEvent* e )
+QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const
 {
-  if ( e->removed() && e->child() == widget() )
+  QtxWorkstackArea* area = 0;
+  QList<QtxWorkstackArea*> lst;
+  areas( mySplit, lst, true );
+  for ( QList<QtxWorkstackArea*>::iterator it = lst.begin(); it != lst.end() && !area; ++it )
   {
-    myWidget = 0;
-    deleteLater();
+    QtxWorkstackArea* cur = *it;
+    QRect r = cur->geometry();
+    if ( cur->parentWidget() )
+      r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() );
+    if ( r.contains( p ) )
+      area = cur;
   }
-  QWidget::childEvent( e );
+  return area;
 }
 
 /*!
-  Constructor
+  \brief Update internal state.
 */
-QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
-: QTabBar( parent ),
-myId( -1 )
+void QtxWorkstack::updateState()
 {
-  setDrawBase( true );
-  setElideMode( Qt::ElideNone );
-
-  connect( this, SIGNAL( currentChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) );
+  updateState( mySplit );
 }
 
 /*!
-  Destructor
+  \brief Update splitter state.
+  \param split splitter to be updated
 */
-QtxWorkstackTabBar::~QtxWorkstackTabBar()
+void QtxWorkstack::updateState( QSplitter* split )
 {
-}
+  QList<QSplitter*> recList;
+  splitters( split, recList, false );
+  for ( QList<QSplitter*>::iterator itr = recList.begin(); itr != recList.end(); ++itr )
+    updateState( *itr );
 
-int QtxWorkstackTabBar::tabId( const int index ) const
-{
-  QVariant v = tabData( index );
-  if ( !v.canConvert( QVariant::Int ) )
-    return -1;
-  return v.toInt();
-}
+  QList<QSplitter*> splitList;
+  splitters( split, splitList, false );
 
-void QtxWorkstackTabBar::setTabId( const int index, const int id )
-{
-  setTabData( index, id );
-}
+  QList<QtxWorkstackArea*> areaList;
+  areas( split, areaList, false );
 
-int QtxWorkstackTabBar::indexOf( const int id ) const
-{
-  int index = -1;
-  for ( int i = 0; i < (int)count() && index < 0; i++ )
+  bool vis = false;
+  for ( QList<QtxWorkstackArea*>::iterator it = areaList.begin(); it != areaList.end(); ++it )
   {
-    if ( tabId( i ) == id )
-      index = i;
+    if ( (*it)->isEmpty() )
+      (*it)->hide();
+    else
+    {
+      (*it)->show();
+      vis = true;
+    }
   }
-  return index;
-}
 
-/*!
-  Returns 'true' if the tab bar is active
-*/
-bool QtxWorkstackTabBar::isActive() const
-{
-  return myActive;
+  if ( split == mySplit )
+    return;
+
+  for ( QList<QSplitter*>::iterator iter = splitList.begin(); iter != splitList.end() && !vis; ++iter )
+    vis = (*iter)->isVisibleTo( (*iter)->parentWidget() );
+
+  if ( areaList.isEmpty() && splitList.isEmpty() )
+    delete split;
+  else if ( vis )
+    split->show();
+  else
+    split->hide();
 }
 
 /*!
-  Sets tab bar as active or inactive
-  \param on - new active state
+  \brief Get splitter info (for debug purposes)
+  \param split splitter
+  \param info string to be filled with splitter data.
 */
-void QtxWorkstackTabBar::setActive( const bool on )
+void QtxWorkstack::splitterInfo( QSplitter* split, QString& info ) const
 {
-  if ( myActive == on )
+  if ( !split )
     return;
 
-  myActive = on;
-  updateActiveState();
-}
+  const QObjectList& objs = split->children();
 
-void QtxWorkstackTabBar::updateActiveState()
-{
-  QColor bc = palette().color( QPalette::Text );
-  QColor ac = isActive() ? palette().color( QPalette::Highlight ) : bc;
-  for ( int i = 0; i < (int)count(); i++ )
-    setTabTextColor( i, currentIndex() == i ? ac : bc );
-}
+  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
+  }
 
-void QtxWorkstackTabBar::onCurrentChanged( int )
-{
-  updateActiveState();
-}
+  if ( !sizesStr.isEmpty() ) // cut the first ':'
+    sizesStr = sizesStr.right( sizesStr.length() - 1 );
 
-/*!
-  Custom mouse move event handler
-*/
-void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e )
-{
-  if ( myId != -1 && !tabRect( indexOf( myId ) ).contains( e->pos() ) )
+  info += QString( "(splitter orientation=%1 sizes=%3 " ).arg( split->orientation() ).arg( sizesStr );
+
+  for ( QObjectList::const_iterator it = objs.begin(); it != objs.end(); ++it )
   {
-    myId = -1;
-    emit dragActiveTab();
+    if ( (*it)->inherits( "QSplitter" ) )
+           splitterInfo( (QSplitter*)*it, info );
+    else if ( (*it)->inherits( "QtxWorkstackArea" ) )
+    {
+           QtxWorkstackArea* area = (QtxWorkstackArea*)*it;
+           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 += ')';
+    }
   }
 
-  QTabBar::mouseMoveEvent( e );
+  info += ')';
+  printf( (const char*)QString( info + '\n' ).toLatin1() );
 }
 
 /*!
-  Custom mouse press event handler
+  \brief Remove round brackets symbols from the string.
+  \internal
+  \param parameters string to be processed
 */
-void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e )
+static void cutBrackets( QString& parameters )
 {
-  QTabBar::mousePressEvent( e );
-
-  if ( e->button() == Qt::LeftButton )
-    myId = tabId( currentIndex() );
+  QChar c1 = parameters[0];
+  QChar c2 = parameters[int(parameters.length()-1)];
+  if ( !parameters.isEmpty() && c1 == '(' && c2 == ')' )
+    parameters = parameters.mid( 1, parameters.length()-2 );
 }
 
 /*!
-  Custom mouse release event handler
-*/
-void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e )
-{
-  QTabBar::mouseReleaseEvent( e );
+  \brief Parse string to get some parameter value.
+  \internal
 
-  myId = -1;
+  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 ( e->button() == Qt::RightButton )
-    emit contextMenuRequested( e->globalPos() );
+  \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();
 }
 
 /*!
-  Custom context menu event handler
+  \brief Check format of splitter parameters string.
+  \internal
+  \param parameters splitter parameters description
+  \return \c true on success and \c false on error
 */
-void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e )
+static bool checkFormat( const QString& parameters )
 {
-  if ( e->reason() != QContextMenuEvent::Mouse )
-    emit contextMenuRequested( e->globalPos() );
+  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;
 }
 
 /*!
-  Draws label of tab bar
+  \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
 */
-/*
-void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
+static QStringList getChildren( const QString& str )
 {
-  if ( currentTab() != t->identifier() )
+  QStringList lst;
+  if ( !str.startsWith( "(" ) )
+    return lst;
+
+  int i = 1,
+  nOpen = 1, // count brackets: '(' increments nOpen, ')' decrements
+  start = 0;
+  while ( i < (int)str.length() )
   {
-    QFont fnt = p->font();
-    fnt.setUnderline( false );
-    p->setFont( fnt );
+    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++;
   }
-  QTabBar::paintLabel( p, br, t, has_focus );
-}
-*/
 
-/*!
-  Constructor
-*/
-QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child )
-: QObject( 0 ),
-myWS( ws ),
-myChild( child ),
-myTab( -1 ),
-myArea( 0 ),
-myTabRect( 0 ),
-myAreaRect( 0 )
-{
-  QApplication::instance()->installEventFilter( this );
+  return lst;
 }
 
 /*!
-  Destructor
-*/
-QtxWorkstackDrag::~QtxWorkstackDrag()
-{
-  QApplication::instance()->removeEventFilter( this );
+  \brief Get view name by index.
+  \internal
 
-  endDrawRect();
-}
+  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
 
-/*!
-  Custom event filter
+  \param str string to be processed
+  \param i index
+  \return view name
 */
-bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e )
+static QString getViewName( const QString& str, int i )
 {
-  switch ( e->type() )
+  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 )
   {
-  case QEvent::MouseMove:
-    updateTarget( ((QMouseEvent*)e)->globalPos() );
-    break;
-  case QEvent::MouseButtonRelease:
-    drawRect();
-    endDrawRect();
-    dropWidget();
-    deleteLater();
-    break;
-  default:
-    return false;
+    start += exp.matchedLength();
+    num ++;
   }
-  return true;
-}
+  if ( start != -1 )      // +2 and -3 avoid starting space and starting and ending ' symbols
+    return str.mid( start + 2, exp.matchedLength() - 3 );
 
-/*!
-  Updates internal field with widget-target for dropping
-  \param p - current point of dragging
-*/
-void QtxWorkstackDrag::updateTarget( const QPoint& p )
-{
-  int tab = -1;
-  QtxWorkstackArea* area = detectTarget( p, tab );
-  setTarget( area, tab );
+  return QString();
 }
 
 /*!
-  \return target area for dropping by point
-  \param p - current point of dragging
-  \param tab - index of tab to dropping
+  \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
 */
-QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const
+static QWidget* getView( const QWidget* parent, const QString& aName )
 {
-  if ( p.isNull() )
-    return 0;
-
-  QtxWorkstackArea* area = myWS->areaAt( p );
-  if ( area )
-    tab = area->tabAt( p );
-  return area;
+  QWidget* view = 0;
+  QList<QWidget*> l = qFindChildren<QWidget*>( parent->topLevelWidget(), aName );
+  if ( !l.isEmpty() )
+    view = ::qobject_cast<QWidget*>( l.first() );
+  return view;
 }
 
 /*!
-  Changes target area for dropping
-  \param area - new target area
-  \param tab - tab index
+  \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 QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab )
+void QtxWorkstack::setSplitter( QSplitter* splitter, const QString& parameters, QMap<QSplitter*, QList<int> >& sMap )
 {
-  if ( !area || ( myArea == area && tab == myTab ) )
+  printf( QString( parameters + '\n' ).toLatin1() );
+  if ( !::checkFormat( parameters ) ) {
+    printf( "\nInvalid format of workstack parameters.  Positions of viewers can not be restored.\n" );
     return;
+  }
 
-  startDrawRect();
+  QString params( parameters );
+  ::cutBrackets( params );
 
-  if ( myArea )
-    drawRect();
+  // 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;
 
-  myTab = tab;
-  myArea = area;
+  // set orientation of splitter
+  int orient = ::getValue( params, "orientation" ).toInt();
+  splitter->setOrientation( (Qt::Orientation)orient );
 
-  if ( myArea )
-    drawRect();
-}
+  // get children
+  QString options = params.left( params.indexOf( '(' ) );
+  QString childrenStr = params.right( params.length()-options.length() );
+  QStringList children = ::getChildren( childrenStr );
 
-/*!
-  Called on widget drop, inserts dropped widget to area
-*/
-void QtxWorkstackDrag::dropWidget()
-{
-  if ( myArea )
-    myArea->insertWidget( myChild->widget(), myTab );
+  // 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() );
+
+  for ( it = children.begin(); it != children.end(); ++it )
+  {
+    if ( (*it).startsWith( "(splitter" ) )
+    {
+      QSplitter* newSplitter = new QSplitter( splitter );
+      setSplitter( newSplitter, *it, sMap );
+    }
+    else if ( (*it).startsWith( "(views" ) )
+    {
+      QtxWorkstackArea* 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 );
+    }
+  }
 }
 
 /*!
-  Draws float rect
+  \brief Restore workstack configuration from the state description string.
+  \param parameters workstack state description
+  \return reference to this workstack
 */
-void QtxWorkstackDrag::drawRect()
+QtxWorkstack& QtxWorkstack::operator<<( const QString& parameters )
 {
-  if ( !myArea )
-    return;
+  // 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;
 
-  QRect r = myArea->floatRect();
-  int m = 2;
+  for ( QList<QtxWorkstackArea*>::iterator it = areaList.begin(); it != areaList.end(); ++it )
+  {
+    if ( (*it)->isEmpty() )
+      delete *it;
+  }
 
-  r.setTop( r.top() + m + 2 );
-  r.setLeft( r.left() + m + 2 );
-  r.setRight( r.right() - m - 2 );
-  r.setBottom( r.bottom() - m - 2 );
+  // restore splitter recursively
+  QMap< QSplitter*, QList<int> > sMap;
+  setSplitter( mySplit, parameters, sMap );
 
-  if ( myAreaRect )
+  // 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 )
   {
-    myAreaRect->setGeometry( r );
-    myAreaRect->setVisible( r.isValid() );
+    if ( (*delIt)->isEmpty() )
+      delete *delIt;
   }
 
-  QRect tr = myArea->floatTab( myTab );
+  QApplication::instance()->processEvents();
 
-  tr.setTop( tr.top() + m );
-  tr.setLeft( tr.left() + m );
-  tr.setRight( tr.right() - m );
-  tr.setBottom( tr.bottom() - m );
+  // 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() );
 
-  if ( myTabRect )
-  {
-    myTabRect->setGeometry( tr );
-    myTabRect->setVisible( tr.isValid() );
-  }
+  return (*this);
 }
 
 /*!
-  Deletes internal painter
+  \brief Dump workstack configuration to the state description string.
+  \param parameters resulting workstack state description
+  \return reference to this workstack
 */
-void QtxWorkstackDrag::endDrawRect()
+QtxWorkstack& QtxWorkstack::operator>>( QString& outParameters )
 {
-  delete myAreaRect;
-  myAreaRect = 0;
-
-  delete myTabRect;
-  myTabRect = 0;
+  splitterInfo( mySplit, outParameters );
+  return (*this);
 }
 
 /*!
-  Initialize internal painter
+  \fn void QtxWorkstack::windowActivated( QWidget* w )
+  \brief Emitted when the workstack's child widget \w is activated.
+  \param w widget being activated
 */
-void QtxWorkstackDrag::startDrawRect()
-{
-  if ( !myTabRect )
-    myTabRect = new QRubberBand( QRubberBand::Rectangle );
-
-  myTabRect->hide();
-
-  if ( !myAreaRect )
-    myAreaRect = new QRubberBand( QRubberBand::Rectangle );
-
-  myAreaRect->hide();
-}
index 767127530069288e75945c37591bd27208e69c45..17adf942871f987eb3d335528d304b8d196ea053 100644 (file)
 
 #include "Qtx.h"
 
-#include <QtCore/qmap.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qframe.h>
-#include <QtGui/qtabbar.h>
+#include <QWidget>
+#include <QFrame>
+#include <QTabBar>
+#include <QEvent>
+#include <QMap>
 
 class QAction;
-class QTabBar;
-class QPainter;
 class QSplitter;
 class QPushButton;
-class QRubberBand;
 class QStackedWidget;
+class QRubberBand;
 
 class QtxWorkstackArea;
 class QtxWorkstackDrag;
@@ -51,13 +50,21 @@ class QTX_EXPORT QtxWorkstack : public QWidget
   Q_OBJECT
 
 public:
-  enum { SplitVertical, SplitHorizontal, Close, Rename };
+  //! 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
+  };
     
+  //! Workstack splitting type
   enum SplitType
   {
-    SPLIT_STAY, //!< given widget stays in its workarea, others are moved into a new one
-    SPLIT_AT,   //!< widgets before a given widget stays in they workarea, others are moved into a new one
-    SPLIT_MOVE  //!< given widget is moved into a new workarea, others stay in an old one
+    SplitStay,  //!< selected widget stays in current workarea, others widgets are moved into a new workarea
+    SplitAt,    //!< all widgets before selected widget stay in current workarea, other widgess are moved into a new workarea
+    SplitMove   //!< selected widget is moved into a new workarea, all other widgets stay in an old workarea
   };
 
 public:
@@ -72,8 +79,8 @@ public:
   int                 accel( const int ) const;
   void                setAccel( const int, const int );
 
-  bool                isActionEnabled( const int ) const;
-  void                setActionEnabled( const int, const bool );
+  void                setMenuActions( const int );
+  int                 menuActions() const;
 
   void                split( const int );
 
@@ -88,14 +95,14 @@ public:
   QtxWorkstack& operator<<( const QString& );
   QtxWorkstack& operator>>( QString& );
 
-Q_SIGNALS:
+signals:
   void                windowActivated( QWidget* );
 
-public Q_SLOTS:
+public slots:
   void                splitVertical();
   void                splitHorizontal();
   
-private Q_SLOTS:
+private slots:
   void                onRename();
   void                onCloseWindow();
   void                onDestroyed( QObject* );
@@ -136,13 +143,13 @@ private:
   void                setSplitter( QSplitter*, const QString&, QMap< QSplitter*, QList<int> >& );
   
 private:
-  QWidget*            myWin;
-  QtxWorkstackArea*   myArea;
-  QSplitter*          mySplit;
-  QWidget*            myWorkWin;
-  QtxWorkstackArea*   myWorkArea;
+  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)
 
-  QMap<int, QAction*> myActionsMap; //!< The map of the actions. Allows to get the QAction object by the key.
+  QMap<int, QAction*> myActionsMap; //!< actions map
 
   friend class QtxWorkstackArea;
   friend class QtxWorkstackDrag;
@@ -182,15 +189,15 @@ public:
 
   int                 tabAt( const QPoint& ) const;
 
-Q_SIGNALS:
+signals:
   void                activated( QWidget* );
   void                contextMenuRequested( QWidget*, QPoint );
   void                deactivated( QtxWorkstackArea* );
 
-public Q_SLOTS:
+public slots:
   virtual void        setVisible( bool );
 
-private Q_SLOTS:
+private slots:
   void                onClose();
   void                onCurrentChanged( int );
 
@@ -198,7 +205,7 @@ private Q_SLOTS:
 
   void                onChildDestroyed( QObject* );
   void                onChildShown( QtxWorkstackChild* );
-  void                onChildHided( QtxWorkstackChild* );
+  void                onChildHidden( QtxWorkstackChild* );
   void                onChildActivated( QtxWorkstackChild* );
   void                onChildCaptionChanged( QtxWorkstackChild* );
 
@@ -211,7 +218,11 @@ protected:
   virtual void        mousePressEvent( QMouseEvent* );
 
 private:
-  enum { ActivateWidget = QEvent::User, FocusWidget, RemoveWidget };
+  //! Custom events
+  enum { ActivateWidget = QEvent::User,   //!< activate widget event
+        FocusWidget,                     //!< focus receiving widget event
+        RemoveWidget                     //!< widget removing event
+  };
 
 private:
   void                updateState();
@@ -244,14 +255,14 @@ private:
   typedef QMap<QWidget*, WidgetInfo>         WidgetInfoMap;
 
 private:
-  QtxWorkstackTabBar* myBar;
-  QPushButton*        myClose;
-  QStackedWidget*     myStack;
-
-  QWidgetList         myList;
-  WidgetInfoMap       myInfo;
-  ChildMap            myChild;
-  BlockMap            myBlock;
+  QtxWorkstackTabBar* myBar;     //!< workarea tab bar header
+  QPushButton*        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
@@ -266,20 +277,20 @@ public:
 
   virtual bool        eventFilter( QObject*, QEvent* );
 
-Q_SIGNALS:
+signals:
   void                shown( QtxWorkstackChild* );
-  void                hided( QtxWorkstackChild* );
+  void                hidden( QtxWorkstackChild* );
   void                activated( QtxWorkstackChild* );
   void                captionChanged( QtxWorkstackChild* );
 
-private Q_SLOTS:
+private slots:
   void                onDestroyed( QObject* );
 
 protected:
   virtual void        childEvent( QChildEvent* );
 
 private:
-  QWidget*            myWidget;
+  QWidget*            myWidget;   //!< child widget
 };
 
 class QtxWorkstackTabBar : public QTabBar
@@ -299,11 +310,11 @@ public:
 
   void                updateActiveState();
 
-Q_SIGNALS:
+signals:
   void                dragActiveTab();
   void                contextMenuRequested( QPoint );
 
-private Q_SLOTS:
+private slots:
   void                onCurrentChanged( int );
 
 protected:
@@ -315,8 +326,8 @@ protected:
 //  virtual void        paintLabel( QPainter*, const QRect&, QTab*, bool ) const;
 
 private:
-  int                 myId;
-  bool                myActive;
+  int                 myId;         //!< current tab page index
+  bool                myActive;     //!< "active" status
 };
 
 class QtxWorkstackDrag : public QObject
@@ -341,17 +352,17 @@ private:
   void                startDrawRect();
 
 private:
-  QtxWorkstack*       myWS;
-  QtxWorkstackChild*  myChild;
+  QtxWorkstack*       myWS;          //!< parent workstack
+  QtxWorkstackChild*  myChild;       //!< workstack child widget container
 
-  int                 myTab;
-  QtxWorkstackArea*   myArea;
-  QRubberBand*        myTabRect;
-  QRubberBand*        myAreaRect;
+  int                 myTab;         //!< workarea tab page index
+  QtxWorkstackArea*   myArea;        //!< workarea
+  QRubberBand*        myTabRect;     //!< tab bar rubber band
+  QRubberBand*        myAreaRect;    //!< workarea rubber band
 };
 
 #ifdef WIN32
 #pragma warning( default:4251 )
 #endif
 
-#endif
+#endif   // QTXWORKSTACK_H
diff --git a/src/Qtx/QtxWorkstackAction.cxx b/src/Qtx/QtxWorkstackAction.cxx
new file mode 100644 (file)
index 0000000..4a4cb0f
--- /dev/null
@@ -0,0 +1,367 @@
+// 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
+//
+// File:      QtxWorkstackAction.cxx
+// Author:    Sergey TELKOV
+
+#include "QtxWorkstackAction.h"
+
+#include "QtxWorkstack.h"
+
+#include <QMenu>
+#include <QWidgetList>
+
+/*!
+  \class QtxWorkstackAction
+  \brief Implements actions group for menu Windows with standard operations, like
+         "Split vertical", "Split horizontal", etc.
+*/
+
+/*!
+  \brief Constructor.
+  \param ws workstack
+  \param parent parent object (owner of the action)
+*/
+QtxWorkstackAction::QtxWorkstackAction( QtxWorkstack* ws, QObject* parent )
+: QtxActionSet( parent ),
+  myWorkstack( ws ),
+  myWindowsFlag( true )
+{
+  insertAction( new QtxAction( tr( "Split the active window on two vertical parts" ),
+                               tr( "Split vertically" ), 0, this ), SplitVertical );
+  insertAction( new QtxAction( tr( "Split the active window on two horizontal parts" ),
+                               tr( "Split horizontally" ), 0, this ), SplitHorizontal );
+
+  connect( this, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
+
+  setMenuActions( Standard );
+}
+
+/*!
+  \brief Destructor.
+*/
+QtxWorkstackAction::~QtxWorkstackAction()
+{
+}
+
+/*!
+  \brief Get workstack.
+  \return parent workstack
+*/
+QtxWorkstack* QtxWorkstackAction::workstack() const
+{
+  return myWorkstack;
+}
+
+/*!
+  \brief Set actions to be visible in the menu.
+  
+  Actions, which IDs are set in \a flags parameter, will be shown in the 
+  menu bar. Other actions will not be shown.
+
+  \param flags ORed together actions flags
+*/
+void QtxWorkstackAction::setMenuActions( const int flags )
+{
+  action( SplitVertical )->setVisible( flags & SplitVertical );
+  action( SplitHorizontal )->setVisible( flags & SplitHorizontal );
+  myWindowsFlag = flags & Windows;
+}
+
+/*!
+  \brief Get menu actions which are currently visible in the menu bar.
+  \return ORed together actions flags
+  \sa setMenuActions()
+*/
+int QtxWorkstackAction::menuActions() const
+{
+  int ret = 0;
+  ret = ret | ( action( SplitVertical )->isVisible() ? SplitVertical : 0 );
+  ret = ret | ( action( SplitHorizontal )->isVisible() ? SplitHorizontal : 0 );
+  ret = ret | ( myWindowsFlag ? Windows : 0 );
+  return ret;
+}
+
+/*!
+  \brief Get keyboard accelerator for the specified action.
+  \param id menu action ID
+  \return keyboard accelerator of menu item or 0 if there is no such action
+*/
+int QtxWorkstackAction::accel( const int id ) const
+{
+  int a = 0;
+  if ( action( id ) )
+    a = action( id )->shortcut();
+  return a;
+}
+
+/*!
+  \brief Get icon for the specified action.
+
+  If \a id is invalid, null icon is returned.
+
+  \param id menu action ID
+  \return menu item icon
+*/
+QIcon QtxWorkstackAction::icon( const int id ) const
+{
+  QIcon ico;
+  if ( action( id ) )
+    ico = action( id )->icon();
+  return ico;
+}
+
+/*!
+  \brief Get menu item text for the specified action.
+  \param id menu action ID
+  \return menu item text or null QString if there is no such action
+*/
+QString QtxWorkstackAction::text( const int id ) const
+{
+  QString txt;
+  if ( action( id ) )
+    txt = action( id )->text();
+  return txt;
+}
+
+/*!
+  \brief Get status bar tip for the specified action.
+  \param id menu action ID
+  \return status bar tip menu item or null QString if there is no such action
+*/
+QString QtxWorkstackAction::statusTip( const int id ) const
+{
+  QString txt;
+  if ( action( id ) )
+    txt = action( id )->statusTip();
+  return txt;
+}
+
+/*!
+  \brief Set keyboard accelerator for the specified action.
+  \param id menu action ID
+  \param a new keyboard accelerator
+*/
+void QtxWorkstackAction::setAccel( const int id, const int a )
+{
+  if ( action( id ) )
+    action( id )->setShortcut( a );
+}
+
+/*!
+  \brief Set menu item icon for the specified action.
+  \param id menu action ID
+  \param ico new menu item icon
+*/
+void QtxWorkstackAction::setIcon( const int id, const QIcon& icon )
+{
+  if ( action( id ) )
+    action( id )->setIcon( icon );
+}
+
+/*!
+  \brief Set menu item text for the specified action.
+  \param id menu action ID
+  \param txt new menu item text
+*/
+void QtxWorkstackAction::setText( const int id, const QString& txt )
+{
+  if ( action( id ) )
+    action( id )->setText( txt );
+}
+
+/*!
+  \brief Set menu item status bar tip for the specified action.
+  \param id menu action ID
+  \param txt new menu item status bar tip
+*/
+void QtxWorkstackAction::setStatusTip( const int id, const QString& txt )
+{
+  if ( action( id ) )
+    action( id )->setStatusTip( txt );
+}
+
+/*!
+  \brief Process action activated by the user.
+  \param type action ID
+*/
+void QtxWorkstackAction::perform( const int type )
+{
+  switch ( type )
+  {
+  case SplitVertical:
+    splitVertical();
+    break;
+  case SplitHorizontal:
+    splitHorizontal();
+    break;
+  }
+}
+
+/*!
+  \brief Split the window area in the workstack in the vertical direction.
+*/
+void QtxWorkstackAction::splitVertical()
+{
+  QtxWorkstack* ws = workstack();
+  if ( ws )
+    ws->splitVertical();
+}
+
+/*!
+  \brief Split the window area in the workstack in the horizontal direction.
+*/
+void QtxWorkstackAction::splitHorizontal()
+{
+  QtxWorkstack* ws = workstack();
+  if ( ws )
+    ws->splitHorizontal();
+}
+
+/*!
+  \brief Called when action is added to the menu bar.
+  \param w menu bar widget this action is being added to
+*/
+void QtxWorkstackAction::addedTo( QWidget* w )
+{
+  QtxActionSet::addedTo( w );
+
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
+    connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
+}
+
+/*!
+  \brief Called when action is removed from the menu bar.
+  \param w menu bar widget this action is being removed from
+*/
+void QtxWorkstackAction::removedFrom( QWidget* w )
+{
+  QtxActionSet::removedFrom( w );
+
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
+    disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
+}
+
+/*!
+  \brief Update all menu action state.
+*/
+void QtxWorkstackAction::updateContent()
+{
+  bool count = workstack() ? workstack()->splitWindowList().count() > 1 : 0;
+  action( SplitVertical )->setEnabled( count );
+  action( SplitHorizontal )->setEnabled( count );
+
+  updateWindows();
+}
+
+/*!
+  \brief Update actions which refer to the opened child windows.
+*/
+void QtxWorkstackAction::updateWindows()
+{
+  QtxWorkstack* ws = workstack();
+  if ( !ws )
+    return;
+
+  QList<QAction*> lst = actions();
+  for ( QList<QAction*>::iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    int id = actionId( *it );
+    if ( id >= Windows )
+      removeAction( *it );
+  }
+
+  bool base = action( SplitVertical )->isVisible() || action( SplitHorizontal )->isVisible();
+
+  QList<QAction*> items;
+  QMap<QAction*, int> map;
+  if ( menuActions() & Windows )
+  {
+    int index = 1;
+    QWidgetList wList = ws->windowList();
+    for ( QWidgetList::iterator it = wList.begin(); it != wList.end(); ++it, index++ )
+    {
+      QWidget* wid = *it;
+      QAction* a = new QtxAction( wid->windowTitle(), wid->windowTitle(), 0, this, true );
+      a->setChecked( wid == ws->activeWindow() );
+      items.append( a );
+      map.insert( a, Windows + index );
+    }
+
+    if ( base && !items.isEmpty() )
+    {
+      QAction* sep = new QtxAction( this );
+      sep->setSeparator( true );
+      items.prepend( sep );
+      map.insert( sep, Windows );
+    }
+  }
+
+  if ( !items.isEmpty() )
+    insertActions( items );
+
+  for ( QMap<QAction*, int>::const_iterator itr = map.begin(); itr != map.end(); ++itr )
+    setActionId( itr.key(), itr.value() );
+}
+
+/*!
+  \brief Called when parent menu is about to show.
+
+  Updates all menu items.
+*/
+void QtxWorkstackAction::onAboutToShow()
+{
+  QMenu* pm = ::qobject_cast<QMenu*>( sender() );
+  if ( pm )
+    updateContent();
+}
+
+/*!
+  \brief Called when menu item corresponding to some child window is activated.
+
+  Activates correposponding child window.
+
+  \param idx menu item index
+*/
+void QtxWorkstackAction::activateItem( const int idx )
+{
+  QtxWorkstack* ws = workstack();
+  if ( !ws )
+    return;
+
+  QWidgetList wList = ws->windowList();
+  if ( idx >= 0 && idx < (int)wList.count() )
+    wList.at( idx )->setFocus();
+}
+
+/*!
+  \brief Called when menu item is activated by the user.
+  
+  Perform the corresponding action.
+
+  \param id menu item identifier
+*/
+void QtxWorkstackAction::onTriggered( int id )
+{
+  if ( id < Windows )
+    perform( id );
+  else
+    activateItem( id - Windows - 1 );
+}
diff --git a/src/Qtx/QtxWorkstackAction.h b/src/Qtx/QtxWorkstackAction.h
new file mode 100644 (file)
index 0000000..a9228a5
--- /dev/null
@@ -0,0 +1,89 @@
+// 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
+//
+// File:      QtxWorkstackAction.h
+// Author:    Sergey TELKOV
+
+#ifndef QTXWORKSTACKACTION_H
+#define QTXWORKSTACKACTION_H
+
+#include "QtxActionSet.h"
+
+class QtxWorkstack;
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+class QTX_EXPORT QtxWorkstackAction : public QtxActionSet
+{
+  Q_OBJECT
+
+public:
+  //! Actions (menu items) ID
+  enum { SplitVertical   = 0x0001,   //!< "Split window vertically" operation
+         SplitHorizontal = 0x0002,   //!< "Split window horizontally" operation
+         Windows         = 0x0010,   //!< A list of child windows menu items
+         Split           = SplitVertical | SplitHorizontal,
+         Standard        = Split | Windows };
+
+  QtxWorkstackAction( QtxWorkstack*, QObject* = 0 );
+  virtual ~QtxWorkstackAction();
+
+  QtxWorkstack* workstack() const;
+
+  int           menuActions() const;
+  void          setMenuActions( const int );
+
+  QIcon         icon( const int ) const;
+  QString       text( const int ) const;
+  int           accel( const int ) const;
+  QString       statusTip( const int ) const;
+
+  void          setAccel( const int, const int );
+  void          setIcon( const int, const QIcon& );
+  void          setText( const int, const QString& );
+  void          setStatusTip( const int, const QString& );
+
+  void          perform( const int );
+
+private slots:
+  void          onAboutToShow();
+  void          onTriggered( int );
+
+protected:
+  virtual void  addedTo( QWidget* );
+  virtual void  removedFrom( QWidget* );
+
+private:
+  void          updateContent();
+  void          updateWindows();
+  void          splitVertical();
+  void          splitHorizontal();
+  void          activateItem( const int );
+
+private:
+  QtxWorkstack* myWorkstack;       //!< parent workstack
+  bool          myWindowsFlag;     //!< "show child windows items" flag
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif