1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // Author: Sergey TELKOV
38 #include <QApplication>
39 #include <QDesktopWidget>
41 #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
42 #include <QSurfaceFormat>
50 #define BICOLOR_CHANGE_HUE
53 \brief Auxiliary function converting string \a str to the integer value.
54 Parameter \a defVal specifies default value that is returned if conversion can't be done.
55 Parameters \a minVal and \a maxVal limit the resulting value.
56 \param str string being converted
57 \param defVal default value
58 \param minVal minimum allowed value
59 \param maxVal maximum allowed value
60 \return integer value obtained from the string
63 static int stringToInt( const QString& str, int defVal, int minVal, int maxVal )
66 int v = str.toInt( &ok );
67 if ( !ok ) v = defVal;
68 return qMin( qMax( v, minVal ), maxVal );
73 \brief A set of helpful utility functions.
75 The class implements a set of the static functions which can be used
76 for the different purposes:
77 - specify tab order for the set of widgets: setTabOrder()
78 - align one widget to the coordinates of the another one: alignWidget()
79 - remove extra separators from the menu or toolbar: simplifySeparators()
80 - retrieve directory, file name and extension parts of the path:
81 dir(), file(), extension()
82 - get the path to the temporary directory: tmpDir()
83 - create or remove a directory (recursively): mkDir(), rmDir()
84 - convert text file from DOS to UNIX native format: dos2unix()
85 - convert a picture to the gray scale: grayscale()
90 \brief Convert character array (ASCII string) to the QString.
91 \param str character array
92 \param len array length, if < 0, the array should be zero-terminated
93 \return QString object
95 QString Qtx::toQString( const char* str, const int len )
97 return toQString( (unsigned char*)str, len );
101 \brief Convert integer array (UNICODE string) to the QString.
102 \param str integer array
103 \param len array length, if < 0, the array should be zero-terminated
104 \return QString object
106 QString Qtx::toQString( const short* str, const int len )
108 return toQString( (unsigned short*)str, len );
112 \brief Convert character array (ASCII string) to the QString.
113 \param str character array
114 \param len array length, if < 0, the array should be zero-terminated
115 \return QString object
117 QString Qtx::toQString( const unsigned char* str, const int len )
120 const unsigned char* s = str;
121 while ( len < 0 || res.length() < len )
126 res.append( QChar( *s ) );
133 \brief Convert integer array (UNICODE string) to the QString.
134 \param str integer array
135 \param len array length, if < 0, the array should be zero-terminated
136 \return QString object
138 QString Qtx::toQString( const unsigned short* str, const int len )
141 const unsigned short* s = str;
142 while ( len < 0 || res.length() < len )
147 res.append( QChar( *s ) );
154 \brief Set tab order for specified list of widgets.
156 The function has arbitrary number of parameters, each should be
157 hovewer of QWidget* type. Last parameter should be null pointer.
159 \param first first widget in the sequence
161 void Qtx::setTabOrder( QWidget* first, ... )
164 va_start( wids, first );
168 QWidget* cur = first;
171 widList.append( cur );
172 cur = va_arg( wids, QWidget* );
175 setTabOrder( widList );
179 \brief Set tab order for specified list of widgets.
180 \param widgets list of widgets
182 void Qtx::setTabOrder( const QWidgetList& widgets )
184 if ( widgets.count() < 2 )
188 for ( QWidgetList::const_iterator it = widgets.begin(); it!= widgets.end(); ++it )
192 QWidget::setTabOrder( prev, next );
198 \brief Align widget \a src relative to widget \a ref acording to the
199 alignment flags \a alignFlags.
200 \param src source widget (being aligned)
201 \param ref reference widget (source widget being aligned to)
202 \param alignFlags alignment flags (Qtx::AlignmentFlags)
204 void Qtx::alignWidget( QWidget* src, const QWidget* ref, const int alignFlags )
206 if ( !src || !ref || !alignFlags )
209 QPoint srcOri = src->pos();
210 QPoint refOri = ref->pos();
211 if ( src->parentWidget() && !src->isTopLevel() )
212 srcOri = src->parentWidget()->mapToGlobal( srcOri );
213 if ( ref->parentWidget() && !ref->isTopLevel() )
214 refOri = ref->parentWidget()->mapToGlobal( refOri );
216 int x = srcOri.x(), y = srcOri.y();
217 int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
218 int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
221 srcWidth = src->sizeHint().width();
223 srcHei = src->sizeHint().height();
226 if ( ref->isTopLevel() && ref->isMaximized() &&
227 src->isTopLevel() && !src->isMaximized() )
228 border = ( src->frameGeometry().width() - src->width() ) / 2;
230 if ( alignFlags & Qtx::AlignLeft )
231 x = refOri.x() + border;
232 if ( alignFlags & Qtx::AlignOutLeft )
233 x = refOri.x() - srcWidth - border;
234 if ( alignFlags & Qtx::AlignRight )
235 x = refOri.x() + refWidth - srcWidth - border;
236 if ( alignFlags & Qtx::AlignOutRight )
237 x = refOri.x() + refWidth + border;
238 if ( alignFlags & Qtx::AlignTop )
239 y = refOri.y() + border;
240 if ( alignFlags & Qtx::AlignOutTop )
241 y = refOri.y() - srcHei - border;
242 if ( alignFlags & Qtx::AlignBottom )
243 y = refOri.y() + refHei - srcHei - border;
244 if ( alignFlags & Qtx::AlignOutBottom )
245 y = refOri.y() + refHei + border;
246 if ( alignFlags & Qtx::AlignHCenter )
247 x = refOri.x() + ( refWidth - srcWidth ) / 2;
248 if ( alignFlags & Qtx::AlignVCenter )
249 y = refOri.y() + ( refHei - srcHei ) / 2;
251 if ( src->parentWidget() && !src->isTopLevel() )
253 QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
258 QWidget* desk = QApplication::desktop();
259 if ( desk && x + srcWidth + border > desk->width() )
260 x = desk->width() - srcWidth - border;
261 if ( desk && y + srcHei + border > desk->height() )
262 y = desk->height() - srcHei - border;
271 \brief Remove (recursively) unnecessary separators from the menu or toolbar.
272 \param wid widget, should be of QMenu* or QToolBar* class
274 void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
279 if ( wid->inherits( "QMenu") || wid->inherits( "QMenuBar") )
281 if ( qobject_cast<QMenu*>( wid ) )
282 qobject_cast<QMenu*>( wid )->setSeparatorsCollapsible( true );
285 foreach ( QAction* action, wid->actions() )
287 if ( action->menu() )
288 simplifySeparators( action->menu(), recursive );
294 QList<QAction*> actions = wid->actions();
295 if ( actions.isEmpty() )
298 bool is_action = false;
299 for ( int i = 0; i < actions.count(); i++ )
301 QAction* action = actions[i];
302 if ( action->isSeparator() )
304 action->setVisible( is_action );
307 else if ( action->isVisible() )
313 for ( int i = actions.count() - 1; i > 0; i-- )
315 QAction* action = actions[i];
316 if ( action->isSeparator() )
318 action->setVisible( is_action );
321 else if ( action->isVisible() )
330 \brief Return \c true if specified \a parent is a parent object
331 of given \a child (in terms of QObject).
333 This function works recursively. It means that \a true is also
334 returned if \a parent is a grand-father, grand-grand-father, etc
335 of \a child. If the same object is given as both \a parent and
336 \a child, \c true is also returned.
338 \param child child object
339 \param parent parent object
340 \return \c true if the \a parent is a parent of \a child
342 bool Qtx::isParent( QObject* child, QObject* parent )
344 if ( !child || !parent )
348 QObject* obj = child;
349 while ( !res && obj )
358 \brief Find the parent object of class specified by \a className (in terms of QObject).
360 \param obj current object
361 \param className class name of the parent
362 \return parent object or null pointer if the parent not found
364 QObject* Qtx::findParent( QObject* obj, const char* className )
369 if ( !className || !strlen( className ) )
370 return obj->parent();
373 QObject* p = obj->parent();
376 if ( p->inherits( className ) )
385 \brief Return directory part of the file path.
387 If the file path does not include directory part (the file is in the
388 current directory), null string is returned.
390 \param path file path
391 \param abs if true (default) \a path parameter is treated as absolute file path
392 \return directory part of the file path
394 QString Qtx::dir( const QString& path, const bool abs )
396 QDir aDir = QFileInfo( path ).dir();
397 QString dirPath = abs ? aDir.absolutePath() : aDir.path();
398 if ( dirPath == QString( "." ) )
404 \brief Return file name part of the file path.
406 \param path file path
407 \param withExt if true (default) complete file name (with all
408 extension except the last) is returned, otherwise only base name
410 \return file name part of the file path
412 QString Qtx::file( const QString& path, bool withExt )
414 QString fPath = path;
415 while ( !fPath.isEmpty() && ( fPath[fPath.length() - 1] == '\\' || fPath[fPath.length() - 1] == '/' ) )
416 fPath.remove( fPath.length() - 1, 1 );
419 return QFileInfo( fPath ).fileName();
421 return QFileInfo( fPath ).completeBaseName();
425 \brief Return extension part of the file path.
427 \param path file path
428 \param full if true complete extension (all extensions, dot separated)
429 is returned, otherwise (default) only last extension is returned
430 \return extension part of the file path
432 QString Qtx::extension( const QString& path, const bool full )
434 return full ? QFileInfo( path ).completeSuffix() : QFileInfo( path ).suffix();
438 \brief Convert the given parameter to the platform-specific library name.
440 The function appends platform-specific prefix (lib) and suffix (.dll/.so)
441 to the library file name.
442 For example, if \a str = "mylib", "libmylib.so" is returned for Linux and
443 mylib.dll for Windows.
445 \param str short library name
446 \return full library name
448 QString Qtx::library( const QString& str )
450 QString path = dir( str, false );
451 QString name = file( str, false );
452 QString ext = extension( str );
455 if ( !name.startsWith( "lib" ) )
456 name = QString( "lib" ) + name;
460 QString libExt( "dll" );
461 #elif defined(__APPLE__)
462 QString libExt( "dylib" );
464 QString libExt( "so" );
467 if ( ext.toLower() != QString( "so" ) && ext.toLower() != QString( "dll" ) && ext.toLower() != QString( "dylib" ) )
469 if ( !name.isEmpty() && !ext.isEmpty() )
470 name += QString( "." );
476 QString fileName = addSlash( path ) + name + QString( "." ) + ext;
482 \brief Get the temporary directory name.
483 \return temporary directory (platform specific)
485 QString Qtx::tmpDir()
487 const char* tmpdir = ::getenv( "TEMP" );
489 tmpdir = ::getenv ( "TMP" );
498 return QString( tmpdir );
502 \brief Create directory recursively including all intermediate sub directories.
503 \return \c true if the directory is successfully created and \c false otherwise
505 bool Qtx::mkDir( const QString& dirPath )
507 return QDir().mkpath( dirPath );
511 \brief Remove directory recursively including all subdirectories and files.
512 \return \c true if the directory is successfully removed and \c false otherwise
514 bool Qtx::rmDir( const QString& thePath )
516 QFileInfo fi( thePath );
522 stat = QFile::remove( thePath );
523 else if ( fi.isDir() )
525 QDir aDir( thePath );
526 QFileInfoList anEntries = aDir.entryInfoList();
527 for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
530 if ( inf.fileName() == "." || inf.fileName() == ".." )
532 stat = stat && rmDir( inf.absoluteFilePath() );
534 stat = stat && aDir.rmdir( thePath );
540 \brief Add a slash (platform-specific) to the end of \a path
541 if it is not already there.
542 \param path directory path
543 \return modified path (with slash added to the end)
545 QString Qtx::addSlash( const QString& path )
548 if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
549 res.at( res.length() - 1 ) != QChar( '\\' ) )
550 res += QDir::separator();
555 \brief Convert text file from DOS format to UNIX.
557 The function replaces "LF/CR" symbols sequence by "LF" symbol.
559 \param absName file name
560 \return \c true if the file is converted successfully and \c false in
563 bool Qtx::dos2unix( const QString& absName )
565 FILE* src = ::fopen( absName.toUtf8(), "rb" );
569 /* we'll use temporary file */
570 char temp[512] = { '\0' };
571 QString dir = Qtx::dir( absName );
572 FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toUtf8(), "__x" ) ), "wb" );
576 /* temp -> result of conversion */
577 const char CR = 0x0d;
578 const char LF = 0x0a;
579 bool waitingLF = false;
584 char inbuf[512], outbuf[512];
587 int nbread = ::fread( inbuf, 1, sizeof( inbuf ), src );
588 for ( int incnt = 0; incnt < nbread; incnt++ )
593 if ( inbuf[incnt] == LF )
594 outbuf[outcnt++] = LF;
596 outbuf[outcnt++] = CR;
598 else if ( inbuf[incnt] == CR )
601 outbuf[outcnt++] = inbuf[incnt];
604 /* check last sym in buffer */
605 waitingLF = ( inbuf[nbread - 1] == CR );
607 /* write converted buffer to temp file */
608 int nbwri = ::fwrite( outbuf, 1, outcnt, tgt );
609 if ( nbwri != outcnt )
613 QFile::remove( QString( temp ) );
616 if ( nbread != sizeof( inbuf ) )
617 break; /* converted ok */
622 /* rename temp -> src */
623 if ( !QFile::remove( absName ) )
626 return QDir().rename( QString( temp ), absName );
630 \brief Create path completer which can be used in the widgets
631 to provide auto completions.
633 Create an instance of QCompleter class and returns the pointer on it.
634 The calling function is responsible to the desstroying of the created
637 The QCompleter class provides completions based on a item model and can be
638 used in such as QLineEdit and QComboBox.
639 When the user starts typing a word, QCompleter suggests possible ways of
640 completing the word, based on a word list.
642 \param type path type (Qtx::PathType)
643 \param filter file/directory filters (list of wildcards, separated by ";;")
644 \return a pointer to the created completer
646 QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
649 QStringList filterList = filter.split( ";;" );
650 for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
652 QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
654 while ( ( index = rx.indexIn( *it, index ) ) != -1 )
656 extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
657 index += rx.matchedLength();
661 QDir::Filters filters = 0;
666 filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
669 filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
673 QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
674 QCompleter* cmp = new QCompleter( dm, 0 );
675 dm->setParent( cmp );
681 \brief Parse given string to retrieve environment variable.
683 Looks through the string for the environment variable patterns.
684 If string contains variable satisfying any pattern, the variable name
685 is returned, start index of the variable is returned in the \a start parameter,
686 and length of the variable is returned in the \a len parameter.
688 Supported environment variables definitions:
689 - ${name} or $name : Linux shell variable
690 - $(name) : GNU make substitution
691 - %name% : Windows shell variable
692 - %(name)s : Python substitutions:
694 \param str string being processed
695 \param start if variable is found, this parameter contains its starting
696 position in the \a str
697 \param len if variable is found, this parameter contains its length
698 \return first found variable or null QString if there is no ones
700 QString Qtx::findEnvVar( const QString& str, int& start, int& len )
706 rxList << "\\$\\{([a-zA-Z][a-zA-Z_0-9]*)\\}"; // ${name}
707 rxList << "\\$([a-zA-Z][a-zA-Z_0-9]*)"; // $name
708 rxList << "\\$\\(([a-zA-Z][a-zA-Z_0-9]*)\\)"; // $(name)
709 rxList << "%([a-zA-Z][a-zA-Z0-9_]*)%"; // %name%
710 rxList << "%\\(([a-zA-Z][a-zA-Z_0-9]*)\\)s"; // %(name)s
712 for ( int i = 0; i < rxList.count() && varName.isEmpty(); ++i )
714 QRegExp rx(rxList[i]);
715 int pos = rx.indexIn( str, start );
718 varName = rx.cap( 1 );
720 len = rx.matchedLength();
727 \brief Substitute environment variables by their values.
729 Environment variable is substituted by its value.
731 \param str string to be processed
732 \return processed string (with all substitutions made)
734 QString Qtx::makeEnvVarSubst( const QString& str, const SubstMode mode )
739 QMap<QString, int> ignoreMap;
741 int start( 0 ), len( 0 );
744 QString envName = findEnvVar( res, start, len );
745 if ( envName.isNull() )
749 if ( ::getenv( envName.toUtf8() ) || mode == Always )
750 newStr = QString( ::getenv( envName.toUtf8() ) );
752 if ( newStr.isNull() )
754 if ( ignoreMap.contains( envName ) )
759 ignoreMap.insert( envName, 0 );
761 res.replace( start, len, newStr );
764 res.replace( "$$", "$" );
765 res.replace( "%%", "%" );
772 \brief Pack the specified color into integer RGB set.
773 \param c unpacked color
776 int Qtx::rgbSet( const QColor& c )
778 return rgbSet( c.red(), c.green(), c.blue() );
782 \brief Pack the specified RGB color components into integer RGB set.
783 \param r red component
784 \param g green component
785 \param b blue component
788 int Qtx::rgbSet( const int r, const int g, const int b )
790 return ( ( ( 0xff & r ) << 16 ) + ( ( 0xff & g ) << 8 ) + ( 0xff & b ) );
794 \brief Unpack the specified integer RGB set to the color.
795 \param rgb packed color
796 \return unpacked color (QColor)
798 QColor Qtx::rgbSet( const int rgb )
801 rgbSet( rgb, r, g, b );
802 return QColor( r, g, b );
806 \brief Unpack the specified integer RGB set to the three RGB components.
807 \param rgb packed color
808 \param r returned unpacked red component
809 \param g returned unpacked green component
810 \param b returned unpacked blue component
812 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
814 r = ( rgb >> 16 ) & 0xff;
815 g = ( rgb >> 8 ) & 0xff;
820 \brief Return the color specified by the index between min (blue) and max (red).
821 \param index color index
822 \param min required minimum hue value
823 \param max required maximum hue value
824 \return resulting color
826 QColor Qtx::scaleColor( const int index, const int min, const int max )
828 static const int HUE[10] = {230, 210, 195, 180, 160, 80, 60, 50, 30, 0};
834 double aPosition = 9.0 * ( index - min ) / ( max - min );
835 if ( aPosition > 0.0 )
837 if ( aPosition >= 9.0 )
841 int idx = (int)aPosition;
842 hue = HUE[idx] + int( ( aPosition - idx ) * ( HUE[idx + 1] - HUE[idx] ) );
847 return QColor::fromHsv( hue, 255, 255 );
851 \brief Generate required number of colors aligned from blue to red.
852 \param num required number of colors
853 \param lst returned set of colors
855 void Qtx::scaleColors( const int num, QColorList& lst )
858 for ( int i = 0; i < num; i++ )
859 lst.append( scaleColor( i, 0, num - 1 ) );
863 \brief Scale the pixmap to the required size.
865 If \a h is 0 (default) the value of \a w is used instead (to create
868 \param icon pixmap to be resized
869 \param w required pixmap width
870 \param h required pixmap height
871 \return scaled pixmap
873 QPixmap Qtx::scaleIcon( const QPixmap& icon, const unsigned w, const unsigned h )
876 int aw = w, ah = h <= 0 ? w : h;
877 if ( icon.isNull() || aw <= 0 || ah <= 0 || ( aw == icon.width() && ah == icon.height() ) )
880 p = icon.fromImage( icon.toImage().scaled( aw, ah, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
885 \brief Convert given image to the grayscale format.
886 \param img initial image
887 \return converted to the grayscale image
889 QImage Qtx::grayscale( const QImage& img )
893 int colNum = res.colorCount();
896 for ( int i = 0; i < colNum; i++ )
897 res.setColor( i, qGray( res.color( i ) ) );
901 for ( int y = 0; y < res.height(); y++ )
903 for ( int x = 0; x < res.width(); x++ )
905 QRgb pix = res.pixel( x, y );
906 res.setPixel( x, y, qRgba( qGray( pix ), qGray( pix ), qGray( pix ), qAlpha( pix ) ) );
915 \brief Convert given pixmap to the grayscale format.
916 \param pix initial pixmap
917 \return converted to the grayscale pixmap
919 QPixmap Qtx::grayscale( const QPixmap& pix )
922 res.fromImage( grayscale( pix.toImage() ) );
927 \brief Create transparent image.
928 \param w required image width
929 \param h required image height
930 \param d required image depth
931 \return generated image
933 QImage Qtx::transparentImage( const int w, const int h, const int d )
939 fmt = QImage::Format_Mono;
942 fmt = QImage::Format_Indexed8;
948 fmt = QImage::Format_ARGB32;
952 QImage img( w, h, fmt );
955 // img.setAlphaBuffer( true );
956 for ( int i = 0; i < img.height(); i++ )
957 for ( int j = 0; j < img.width(); j++ )
958 img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) );
964 \brief Create transparent pixmap.
965 \param w required image width
966 \param h required pixmap height
967 \param d required pixmap depth
968 \return generated pixmap
970 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
973 QImage img = transparentImage( w, h, d );
975 pix.fromImage( img );
980 \brief Create composite pixmap.
982 Pixmap \a pix is drawn over pixmap \a dest with coordinates
983 specified relatively to the upper left corner of \a dest.
984 If \a dest is not given, the new empty pixmap with appropriate size created instead.
986 \param pix source pixmap
987 \param x horizontal shift
988 \param y vertical shift
989 \param dest background pixmap
990 \return resulting pixmap
992 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
997 int width = qMax( pix.width() + x, dest.width() );
998 int height = qMax( pix.height() + y, dest.height() );
1000 QPixmap res( width, height );
1001 QImage img = transparentImage( width, height, 32 );
1005 p.fillRect( 0, 0, width, height, QBrush( Qt::white ) );
1007 if ( !dest.isNull() )
1009 p.drawPixmap( 0, 0, dest );
1010 QImage temp = dest.toImage();
1011 for ( int i = 0; i < temp.width() && i < img.width(); i++ )
1013 for ( int j = 0; j < temp.height() && j < img.height(); j++ )
1015 if ( temp.hasAlphaChannel() )
1016 img.setPixel( i, j, temp.pixel( i, j ) );
1019 QRgb p = temp.pixel( i, j );
1020 img.setPixel( i, j, qRgba( qRed( p ), qGreen( p ), qBlue( p ), 255 ) );
1026 p.drawPixmap( x, y, pix );
1027 QImage temp = pix.toImage();
1028 for ( int c = x; c < temp.width() + x && c < img.width(); c++ )
1030 for ( int r = y; r < temp.height() + y && r < img.height(); r++ )
1032 if ( qAlpha( temp.pixel( c - x, r - y ) ) > 0 )
1033 img.setPixel( c, r, temp.pixel( c - x, r - y ) );
1039 for ( int ai = 0; ai < img.width(); ai++ )
1041 for ( int aj = 0; aj < img.height(); aj++ )
1043 if ( qAlpha( img.pixel( ai, aj ) ) < 1 )
1044 img.setPixel( ai, aj, qRgba( 255, 255, 255, 255 ) );
1046 img.setPixel( ai, aj, qRgba( 0, 0, 0, 0 ) );
1050 QBitmap bmp( width, height );
1051 bmp.fromImage( img, Qt::ColorMode_Mask | Qt::ThresholdDither );
1058 \brief Convert color to the string representation.
1060 The resulting string is in the one of two possible formats
1061 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1062 and alpha components of the color):
1063 - if color has alpha channel : "#RR,#GG,#BB,#AA"
1064 - if color does not have alpha channel : "#RRGGBB"
1066 If color is invalid, null string is returned.
1068 Backward conversion can be done with stringToColor() method.
1070 \param color color to be converted
1071 \return string representation of the color
1075 QString Qtx::colorToString( const QColor& color )
1078 if ( color.isValid() )
1080 if ( color.alpha() != 255 )
1083 vals << QString( "#%1" ).arg( color.red(), 0, 16 );
1084 vals << QString( "#%1" ).arg( color.green(), 0, 16 );
1085 vals << QString( "#%1" ).arg( color.blue(), 0, 16 );
1086 vals << QString( "#%1" ).arg( color.alpha(), 0, 16 );
1087 str = vals.join( "," );
1098 \brief Create color from the string representation.
1100 The parameter \a str must be in the one of following formats
1101 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1102 and alpha components of the color):
1103 - "#RR,#GG,#BB[,#AA]" or "#RR #GG #BB[ #AA]" (\c RR, \c GG, \c BB
1104 and optional \c AA values represent red, green, blue and alpha
1105 components of the color in hexadecimal form)
1106 - "RR,GG,BB[,AA]" or "RR GG BB[ AA]" (\c RR, \c GG, \c BB
1107 and optional \c AA values represent red, green, blue and alpha
1108 components of the color in decimal form)
1109 - "#RRGGBB" - (\c RR, \c GG and \c BB values represent red, green and blue
1110 components of the color in hexadecimal form)
1111 - an integer value representing packed color components (see rgbSet())
1112 - a name from the list of colors defined in the list of SVG color keyword names
1113 provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
1115 Backward conversion can be done with colorToString() method.
1117 \param str string representation of the color
1118 \param color resulting color value
1119 \return \c true if the conversion is successful and \c false otherwise
1121 \sa colorToString(), rgbSet()
1123 bool Qtx::stringToColor( const QString& str, QColor& color )
1126 QStringList vals = str.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1129 for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
1132 if ( (*it).startsWith( "#" ) )
1133 num = (*it).mid( 1 ).toInt( &res, 16 );
1135 num = (*it).toInt( &res, 10 );
1140 res = res && nums.count() >= 3;
1142 color.setRgb( nums[0], nums[1], nums[2] );
1146 int pack = str.toInt( &res );
1148 color = Qtx::rgbSet( pack );
1153 color = QColor( str );
1154 res = color.isValid();
1161 \brief Convert bi-color value to the string representation.
1163 Bi-color value is specified as main color and integer delta
1164 value that is used to calculate secondary color by changing
1165 paremeters of the main color ("saturation" and "value"
1166 components in HSV notation).
1168 The resulting string consists of two sub-strings separated by
1169 '|' symbol. The first part represents main color
1170 (see colorToString() for more details), the second part is a
1173 Backward conversion can be done with stringToBiColor() method.
1175 \param color color to be converted
1176 \param delta delta value
1177 \return string representation of the bi-color value
1179 \sa stringToBiColor(), stringToColor()
1181 QString Qtx::biColorToString( const QColor& color, const int delta )
1183 return QString("%1|%2").arg( Qtx::colorToString( color ) ).arg( delta );
1187 \brief Restore bi-color value from the string representation.
1189 Bi-color value is specified as main color and integer delta
1190 value that is used to calculate secondary color by changing
1191 paremeters of the main color ("saturation" and "value"
1192 components in HSV notation).
1194 The parameter \a str should consist of two sub-strings separated
1195 by '|' symbol. The first part represents main color
1196 (see stringToColor() for more details), the second part is a
1199 Backward conversion can be done with biColorToString() method.
1201 \param str string representation of the bi-color value
1202 \param color resulting color value
1203 \param delta resulting delta value
1204 \return \c true if the conversion is successful and \c false otherwise
1206 \sa biColorToString(), stringToColor(), rgbSet()
1208 bool Qtx::stringToBiColor( const QString& str, QColor& color, int& delta )
1210 QStringList data = str.split( "|", QString::KeepEmptyParts );
1213 bool ok = data.count() > 0 && Qtx::stringToColor( data[0], c );
1215 if ( data.count() > 1 ) d = data[1].toInt( &dok );
1217 color = ok ? c : QColor();
1223 \brief Compute secondary color value from specified main color
1226 Secondary color is calculated by changing paremeters of the main
1227 color ("saturation" and "value" components in HSV notation) using
1230 If main color is invalid, result of the function is also invalid color.
1232 \param color source main color
1233 \param delta delta value
1234 \return resulting secondary color
1236 \sa biColorToString(), stringToBiColor()
1238 QColor Qtx::mainColorToSecondary( const QColor& color, int delta )
1241 if ( cs.isValid() ) {
1242 int val = qMin( 255, qMax( cs.value() + delta, 0 ) );
1243 int sat = qMin( 255, qMax( cs.saturation() + delta-(val-cs.value()), 0 ) );
1244 #ifdef BICOLOR_CHANGE_HUE
1245 const int BICOLOR_HUE_MAXDELTA = 40;
1246 int dh = delta-(val-cs.value())-(sat-cs.saturation());
1247 dh = qMin( BICOLOR_HUE_MAXDELTA, qAbs( dh ) ) * ( dh > 0 ? 1 : -1 );
1248 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-(sat-cs.saturation()), 0 ) );
1249 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-ds, 0 ) );
1250 int hue = cs.hue() + dh;
1251 if ( hue < 0 ) hue = 360 - hue;
1255 cs.setHsv( hue, sat, val );
1261 \brief Dump linear gradient to the string description.
1262 \param gradient linear gradient to be converted
1263 \return string representation of the linear gradient
1264 \sa stringToLinearGradient()
1266 QString Qtx::gradientToString( const QLinearGradient& gradient )
1270 data << QString::number( gradient.start().x() );
1271 data << QString::number( gradient.start().y() );
1272 data << QString::number( gradient.finalStop().x() );
1273 data << QString::number( gradient.finalStop().y() );
1274 switch( gradient.spread() )
1276 case QGradient::PadSpread:
1279 case QGradient::RepeatSpread:
1282 case QGradient::ReflectSpread:
1288 QGradientStops stops = gradient.stops();
1290 foreach ( stop, stops )
1292 data << QString::number( stop.first );
1293 data << colorToString( stop.second );
1295 return data.join( "|" );
1299 \brief Dump radial gradient to the string description.
1300 \param gradient radial gradient to be converted
1301 \return string representation of the radial gradient
1302 \sa stringToRadialGradient()
1304 QString Qtx::gradientToString( const QRadialGradient& gradient )
1308 data << QString::number( gradient.center().x() );
1309 data << QString::number( gradient.center().y() );
1310 data << QString::number( gradient.focalPoint().x() );
1311 data << QString::number( gradient.focalPoint().y() );
1312 data << QString::number( gradient.radius() );
1313 switch( gradient.spread() )
1315 case QGradient::PadSpread:
1318 case QGradient::RepeatSpread:
1321 case QGradient::ReflectSpread:
1327 QGradientStops stops = gradient.stops();
1329 foreach ( stop, stops )
1331 data << QString::number( stop.first );
1332 data << colorToString( stop.second );
1334 return data.join( "|" );
1338 \brief Dump conical gradient to the string description.
1339 \param gradient conical gradient to be converted
1340 \return string representation of the conical gradient
1341 \sa stringToConicalGradient()
1343 QString Qtx::gradientToString( const QConicalGradient& gradient )
1347 data << QString::number( gradient.center().x() );
1348 data << QString::number( gradient.center().y() );
1349 data << QString::number( gradient.angle() );
1350 switch( gradient.spread() )
1352 case QGradient::PadSpread:
1355 case QGradient::RepeatSpread:
1358 case QGradient::ReflectSpread:
1364 QGradientStops stops = gradient.stops();
1366 foreach ( stop, stops )
1368 data << QString::number( stop.first );
1369 data << colorToString( stop.second );
1371 return data.join( "|" );
1375 \brief Create linear gradient from its string representation.
1376 \param str string representation of the linear gradient
1377 \param gradient resulting linear gradient object
1378 \return \c true if the conversion is successful and \c false otherwise
1379 \sa gradientToString()
1381 bool Qtx::stringToLinearGradient( const QString& str, QLinearGradient& gradient )
1383 bool success = false;
1384 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1385 if ( vals.count() > 4 && ( vals[0] == "linear" || vals[0] == "lg" ) )
1387 // start and end points
1388 double x1, y1, x2, y2;
1389 bool bOk1, bOk2, bOk3, bOk4;
1390 x1 = vals[1].toDouble( &bOk1 );
1391 y1 = vals[2].toDouble( &bOk2 );
1392 x2 = vals[3].toDouble( &bOk3 );
1393 y2 = vals[4].toDouble( &bOk4 );
1394 if ( bOk1 && bOk2 && bOk3 && bOk4 )
1396 gradient = QLinearGradient( x1, y1, x2, y2 );
1398 if ( vals.count() > 5 )
1400 QString spread = vals[ 5 ].trimmed().toLower();
1401 if ( spread == "pad" || spread == "0" )
1402 gradient.setSpread( QGradient::PadSpread );
1403 else if ( spread == "repeat" || spread == "2" )
1404 gradient.setSpread( QGradient::RepeatSpread );
1405 else if ( spread == "reflect" || spread == "1" )
1406 gradient.setSpread( QGradient::ReflectSpread );
1409 QGradientStops stops;
1410 for ( int i = 6; i < vals.count(); i+=2 )
1412 bool bOk5, bOk6 = false;
1414 double stop = vals[i].toDouble( &bOk5 );
1415 if ( i+1 < vals.count() )
1416 bOk6 = stringToColor( vals[ i+1 ], c );
1417 if ( bOk5 && stop >= 0.0 && stop <= 1.0 && bOk6 && c.isValid() )
1418 stops.append( QGradientStop( stop, c ) );
1420 gradient.setStops( stops );
1428 \brief Create radial gradient from its string representation.
1429 \param str string representation of the radial gradient
1430 \param gradient resulting radial gradient object
1431 \return \c true if the conversion is successful and \c false otherwise
1432 \sa gradientToString()
1434 bool Qtx::stringToRadialGradient( const QString& str, QRadialGradient& gradient )
1436 bool success = false;
1437 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1438 if ( vals.count() > 5 && ( vals[0] == "radial" || vals[0] == "rg" ) )
1440 // center, radius and focal point
1441 double cx, cy, r, fx, fy;
1442 bool bOk1, bOk2, bOk3, bOk4, bOk5;
1443 cx = vals[1].toDouble( &bOk1 );
1444 cy = vals[2].toDouble( &bOk2 );
1445 fx = vals[3].toDouble( &bOk4 );
1446 fy = vals[4].toDouble( &bOk5 );
1447 r = vals[5].toDouble( &bOk3 );
1448 if ( bOk1 && bOk2 && bOk3 && bOk4 && bOk5 )
1450 gradient = QRadialGradient( cx, cy, r, fx, fy );
1452 if ( vals.count() > 6 )
1454 QString spread = vals[ 6 ].trimmed().toLower();
1455 if ( spread == "pad" || spread == "0" )
1456 gradient.setSpread( QGradient::PadSpread );
1457 else if ( spread == "repeat" || spread == "2" )
1458 gradient.setSpread( QGradient::RepeatSpread );
1459 else if ( spread == "reflect" || spread == "1" )
1460 gradient.setSpread( QGradient::ReflectSpread );
1463 QGradientStops stops;
1464 for ( int i = 7; i < vals.count(); i+=2 )
1466 bool bOk7, bOk8 = false;
1468 double stop = vals[i].toDouble( &bOk7 );
1469 if ( i+1 < vals.count() )
1470 bOk8 = stringToColor( vals[ i+1 ], c );
1471 if ( bOk7 && stop >= 0.0 && stop <= 1.0 && bOk8 && c.isValid() )
1472 stops.append( QGradientStop( stop, c ) );
1474 gradient.setStops( stops );
1482 \brief Create conical gradient from its string representation.
1483 \param str string representation of the conical gradient
1484 \param gradient resulting conical gradient object
1485 \return \c true if the conversion is successful and \c false otherwise
1486 \sa gradientToString()
1488 bool Qtx::stringToConicalGradient( const QString& str, QConicalGradient& gradient )
1490 bool success = false;
1491 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1492 if ( vals.count() > 3 && ( vals[0] == "conical" || vals[0] == "cg" ) )
1496 bool bOk1, bOk2, bOk3;
1497 cx = vals[1].toDouble( &bOk1 );
1498 cy = vals[2].toDouble( &bOk2 );
1499 a = vals[3].toDouble( &bOk3 );
1500 if ( bOk1 && bOk2 && bOk3 )
1502 gradient = QConicalGradient( cx, cy, a );
1504 if ( vals.count() > 4 )
1506 QString spread = vals[ 4 ].trimmed().toLower();
1507 if ( spread == "pad" || spread == "0" )
1508 gradient.setSpread( QGradient::PadSpread );
1509 else if ( spread == "repeat" || spread == "2" )
1510 gradient.setSpread( QGradient::RepeatSpread );
1511 else if ( spread == "reflect" || spread == "1" )
1512 gradient.setSpread( QGradient::ReflectSpread );
1515 QGradientStops stops;
1516 for ( int i = 5; i < vals.count(); i+=2 )
1518 bool bOk4, bOk5 = false;
1520 double stop = vals[i].toDouble( &bOk4 );
1521 if ( i+1 < vals.count() )
1522 bOk5 = stringToColor( vals[ i+1 ], c );
1523 if ( bOk4 && stop >= 0.0 && stop <= 1.0 && bOk5 && c.isValid() )
1524 stops.append( QGradientStop( stop, c ) );
1526 gradient.setStops( stops );
1534 \brief Convert background data to the string representation.
1535 The resulting string consists of several sub-strings separated by ';' symbol.
1536 These sub-strings represent:
1537 1. background type (enumerator, see Qtx::BackgroundMode)
1538 2. texture image file name (string)
1539 3. texture mode (enumerator, see Qtx::TextureMode)
1540 4. "show texture" flag (boolean)
1541 5. first color (for simple gradient data) or solid color (for single-colored mode)
1542 6. second color (for simple gradient data)
1543 7. type of simple gradient (some integer identifier)
1544 8. complex gradient data (for custom gradient mode)
1545 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1547 Backward conversion can be done with stringToBackground() method.
1549 \param bgData background data
1550 \return string representation of the background data
1552 \sa stringToBackground()
1554 QString Qtx::backgroundToString( const Qtx::BackgroundData& bgData )
1556 const QString dtSep = ";";
1557 const QString kwSep = "=";
1558 const QString kwBgType = "bt";
1559 const QString kwFileName = "fn";
1560 const QString kwTextureMode = "tm";
1561 const QString kwShowTexture = "ts";
1562 const QString kwFirstColor = "c1";
1563 const QString kwSecondColor = "c2";
1564 const QString kwGrType = "gt";
1565 const QString kwGrData = "gr";
1567 Qtx::BackgroundMode bgMode = bgData.mode();
1569 Qtx::TextureMode textureMode = bgData.texture( fileName );
1570 bool showTexture = bgData.isTextureShown();
1572 int gradientType = bgData.gradient( c1, c2 );
1573 const QGradient* gradient = bgData.gradient();
1576 switch ( gradient->type() ) {
1577 case QGradient::LinearGradient:
1578 grString = gradientToString( *(static_cast<const QLinearGradient*>( gradient )) );
1580 case QGradient::RadialGradient:
1581 grString = gradientToString( *(static_cast<const QRadialGradient*>( gradient )) );
1583 case QGradient::ConicalGradient:
1584 grString = gradientToString( *(static_cast<const QConicalGradient*>( gradient )) );
1591 data << QString( "%1%2%3" ).arg( kwBgType ).arg( kwSep ).arg( (int)bgMode );
1592 data << QString( "%1%2%3" ).arg( kwFileName ).arg( kwSep ).arg( fileName );
1593 data << QString( "%1%2%3" ).arg( kwTextureMode ).arg( kwSep ).arg( (int)textureMode );
1594 data << QString( "%1%2%3" ).arg( kwShowTexture ).arg( kwSep ).arg( showTexture ? "true" : "false" );
1595 data << QString( "%1%2%3" ).arg( kwFirstColor ).arg( kwSep ).arg( Qtx::colorToString( c1 ) );
1596 data << QString( "%1%2%3" ).arg( kwSecondColor ).arg( kwSep ).arg( Qtx::colorToString( c2 ) );
1597 data << QString( "%1%2%3" ).arg( kwGrType ).arg( kwSep ).arg( gradientType );
1598 data << QString( "%1%2%3" ).arg( kwGrData ).arg( kwSep ).arg( grString );
1600 return data.join( dtSep );
1604 \brief Restore background data from the string representation.
1606 The string should consist of several sub-strings separated by ';' symbol.
1607 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1608 The sub-strings can follow in arbitrary order, some keywords can be missing.
1609 The background data is described by the following values:
1610 - background type (enumerator, see Qtx::BackgroundMode), keyword "bt"
1611 - texture image file name (string), keyword "fn"
1612 - texture mode (enumerator, see Qtx::TextureMode), keyword "tm"
1613 - "show texture" flag (boolean), keyword "ts"
1614 - first color (for simple gradient data) or solid color (for single-colored mode), keyword "c1"
1615 - second color (for simple gradient data), keyword "c2"
1616 - name of gradient type (string), keyword "gt"
1617 - complex gradient data (for custom gradient mode), keyword "gr"
1619 Also, for backward compatibility, background data can be represented by
1620 single color value, see stringToColor().
1622 Backward conversion can be done with backgroundToString() method.
1623 Returns invalid background if conversion could not be done.
1626 Qtx::BackgroundData bgData = Qtx::stringToBackground( str );
1627 if ( bgData.isValid() ) ) doSomething( bgData );
1630 \param theString string representation of the background data
1631 \return resulting background data (invalid if conversion has failed)
1633 \sa backgroundToString()
1636 Qtx::BackgroundData Qtx::stringToBackground( const QString& str )
1638 const QString dtSep = ";";
1639 const QString kwSep = "=";
1640 const QString kwBgType = "bt";
1641 const QString kwFileName = "fn";
1642 const QString kwTextureMode = "tm";
1643 const QString kwShowTexture = "ts";
1644 const QString kwFirstColor = "c1";
1645 const QString kwSecondColor = "c2";
1646 const QString kwGrType = "gt";
1647 const QString kwGrData = "gr";
1649 Qtx::BackgroundData bgData = BackgroundData();
1651 QStringList data = str.split( dtSep, QString::KeepEmptyParts );
1654 if ( data.count() == 1 && !data.contains( kwSep ) && stringToColor( data[0], c ) ) {
1655 // solid color mode, for backward compatibility
1656 bgData.setColor( c );
1659 QMap<QString, QString> dmap;
1661 foreach( QString d, data ) {
1662 QStringList items = d.split( kwSep, QString::KeepEmptyParts );
1663 if ( items.count() > 0 ) {
1664 QString kw = items.takeFirst().trimmed().toLower(); // keyword
1665 QString val = items.join( kwSep ).trimmed(); // if value contains "=" symbol, we have to restore it
1669 QString bgMode = dmap.value( kwBgType, QString() );
1670 QString fileName = dmap.value( kwFileName, QString() );
1671 QString textureMode = dmap.value( kwTextureMode, QString() );
1672 QString showTexture = dmap.value( kwShowTexture, QString() );
1673 QString color1 = dmap.value( kwFirstColor, QString() );
1674 QString color2 = dmap.value( kwSecondColor, QString() );
1675 QString gradientType = dmap.value( kwGrType, QString() );
1676 QString gradient = dmap.value( kwGrData, QString() );
1679 if ( !fileName.isEmpty() || !textureMode.isEmpty() || !showTexture.isEmpty() ) {
1680 Qtx::TextureMode m = (Qtx::TextureMode)( stringToInt( textureMode, Qtx::CenterTexture,
1681 Qtx::CenterTexture, Qtx::StretchTexture ) );
1682 bgData.setTexture( fileName, m );
1683 QStringList boolvars; boolvars << "true" << "yes" << "ok" << "1";
1684 if ( boolvars.contains( showTexture.trimmed().toLower() ) )
1685 bgData.setTextureShown( true );
1689 bool ok = Qtx::stringToColor( color1, c1 );
1691 bgData.setColor( c1 );
1693 // try simple gradient mode
1694 ok = Qtx::stringToColor( color2, c2 );
1695 if ( ok || !gradientType.isEmpty() ) {
1696 int gt = gradientType.toInt( &ok );
1697 bgData.setGradient( ok ? gt : -1, c1, c2 );
1699 // try custom gradient mode
1701 QConicalGradient cg;
1703 ok = Qtx::stringToLinearGradient( gradient, lg );
1705 bgData.setGradient( lg );
1707 ok = Qtx::stringToRadialGradient( gradient, rg );
1709 bgData.setGradient( rg );
1711 ok = Qtx::stringToConicalGradient( gradient, cg );
1713 bgData.setGradient( cg );
1716 // finally set background mode
1717 Qtx::BackgroundMode m = (Qtx::BackgroundMode)( stringToInt( bgMode, Qtx::ColorBackground,
1718 Qtx::NoBackground, Qtx::CustomGradientBackground ) );
1719 bgData.setMode( m );
1726 \class Qtx::Localizer
1727 \brief Localization helper
1729 This helper class can be used to solve the localization problems,
1730 usually related to the textual files reading/writing, namely when
1731 floating point values are read / written with API functions.
1732 The problem relates to such locale specific settings as decimal point
1733 separator, thousands separator, etc.
1735 To use the Localizer class, just create a local variable in the beginning
1736 of the code where you need to read / write data from textual file(s).
1737 The constructor of the class forces setting "C" locale temporariy.
1738 The destructor switches back to the initial locale.
1748 \brief Constructor. Forces "C" locale to be set.
1750 Qtx::Localizer::Localizer()
1752 myCurLocale = setlocale( LC_NUMERIC, 0 );
1753 setlocale( LC_NUMERIC, "C" );
1757 \brief Destructor. Reverts back to the initial locale.
1759 Qtx::Localizer::~Localizer()
1761 setlocale( LC_NUMERIC, myCurLocale.toLatin1().constData() );
1765 \class Qtx::BackgroundData
1766 \brief Stores background data
1768 This class is used to store background data. Depending on the mode,
1769 the background can be specified by:
1770 - image (by assigning the file name to be used as background texture), see setTexture(), setTextureShown()
1771 - single color (by assigning any color), see setColor()
1772 - simple two-color gradient (with the gradient type id and two colors), see setGradient( int, const QColor&, const QColor& )
1773 - complex gradient (by assigning arbitrary gradient data), see setGradient( const QGradient& )
1775 The class stores all the data passed to it, so switching between different modes can be done
1776 just by calling setMode() function.
1778 \note Texture is used with combination of the background mode.
1780 \note Two-color gradient is specified by two colors and integer identifier. The interpretation of
1781 this identifier should be done in the calling code.
1784 Qtx::BackgroundData bg;
1785 bg.setColor( QColor(100, 100, 100) ); // bg is switched to Qtx::ColorBackground mode
1786 bg.setGradient( Qt::Horizontal, Qt::gray, Qt::white ); // bg is switched to Qtx::ColorBackground mode
1787 QLinearGradient grad( 0,0,1,1 );
1788 grad.setColorAt( 0.0, Qt::gray );
1789 grad.setColorAt( 0.5, Qt::white );
1790 grad.setColorAt( 1.0, Qt::green );
1791 grad.setSpread( QGradient::PadSpread );
1792 bg.setGradient( grad ); // bg is switched to Qtx::CustomGradientBackground mode
1793 bg.setMode( Qtx::ColorBackground ); // bg is switched back to Qtx::ColorBackground mode
1794 bg.setTexture( "/data/images/background.png" ); // specify texture (in the centered mode by default)
1795 bg.setTextureShown( true ); // draw texture on the solid color background
1800 \brief Default constructor.
1801 Creates invalid background data.
1803 Qtx::BackgroundData::BackgroundData()
1804 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1806 setMode( Qtx::NoBackground );
1811 Creates background data initialized with the specified color
1814 Qtx::BackgroundData::BackgroundData( const QColor& c )
1815 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1822 Creates background data initialized with the specified two-color gradient
1823 \param type gradient type identifier
1824 \param c1 first gradient color
1825 \param c2 second gradient color
1826 \note the interpretation of the gradient identifier should be done in the calling code
1828 Qtx::BackgroundData::BackgroundData( int type, const QColor& c1, const QColor& c2 )
1829 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1831 setGradient( type, c1, c2 );
1836 Creates background data initialized with the arbirtary gradient data
1837 \param grad gradient data
1839 Qtx::BackgroundData::BackgroundData( const QGradient& grad )
1840 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1842 setGradient( grad );
1848 Qtx::BackgroundData::~BackgroundData()
1853 \brief Compares two background data objects
1855 bool Qtx::BackgroundData::operator==( const Qtx::BackgroundData& other ) const
1858 ( myMode == other.myMode ) &&
1859 ( myTextureMode == other.myTextureMode ) &&
1860 ( myFileName == other.myFileName ) &&
1861 ( myColors == other.myColors ) &&
1862 ( myGradientType == other.myGradientType ) &&
1863 ( myGradient == other.myGradient ) &&
1864 ( myTextureShown == other.myTextureShown );
1868 \brief Returns \c false if background data is not set (invalid)
1869 \return \c true if background data is valid or \c false otherwise
1872 bool Qtx::BackgroundData::isValid() const
1874 return myMode != Qtx::NoBackground;
1878 \brief Get background mode
1879 \return current background mode
1882 Qtx::BackgroundMode Qtx::BackgroundData::mode() const
1888 \brief Set background mode
1889 \param m background mode being set
1892 void Qtx::BackgroundData::setMode( const Qtx::BackgroundMode m )
1898 \brief Get file name used as a texture image
1899 \return path to the texture image file
1900 \sa setTexture(), setTextureShown()
1902 Qtx::TextureMode Qtx::BackgroundData::texture( QString& fileName ) const
1904 fileName = myFileName;
1905 return myTextureMode;
1909 \brief Set file name to be used as a texture image.
1911 \note To show texture image on the background it is necessary to call additionally
1912 setTextureShown() method.
1914 \param fileName path to the texture image file name
1915 \param m texture mode (Qtx::CenterTexture by default)
1916 \sa texture(), setTextureShown()
1918 void Qtx::BackgroundData::setTexture( const QString& fileName, const Qtx::TextureMode m )
1920 myFileName = fileName;
1925 \brief Check if "show texture" flag is switched on
1926 \return \c true if "show texture" flag is set or \c false otherwise
1927 \sa setTextureShown(), texture()
1929 bool Qtx::BackgroundData::isTextureShown() const
1931 return myTextureShown;
1935 \brief Specify if texture should be shown on the background or no.
1936 \param on \c true if texture should be shown or \c false otherwise
1937 \sa isTextureShown(), texture()
1939 void Qtx::BackgroundData::setTextureShown( bool on )
1941 myTextureShown = on;
1945 \brief Get background color. Returns null QColor if color is not set
1946 \return solid background color
1947 \sa setColor(), mode()
1949 QColor Qtx::BackgroundData::color() const
1951 return myColors.count() > 0 ? myColors[0] : QColor();
1955 \brief Set background color and switch to the Qtx::ColorBackground mode
1959 void Qtx::BackgroundData::setColor( const QColor& c )
1963 setMode( Qtx::ColorBackground );
1967 \brief Get simple gradient data.
1968 Returns -1 and null QColor for \a c1 and \a c2 if gradient data is not set
1969 \param c1 first gradient color is returned via this parameter
1970 \param c2 second gradient color is returned via this parameter
1971 \return current two-colored gradient mode type identifier
1972 \note the interpretation of the gradient identifier should be done in the calling code
1973 \sa setGradient(int, const QColor&, const QColor&), mode()
1975 int Qtx::BackgroundData::gradient( QColor& c1, QColor& c2 ) const
1977 c1 = myColors.count() > 0 ? myColors[0] : QColor();
1978 c2 = myColors.count() > 1 ? myColors[1] : ( myColors.count() > 0 ? myColors[0] : QColor() );
1979 return myGradientType;
1983 \brief Set simple background gradient data and switch to the Qtx::SimpleGradientBackground mode
1984 \param type two-colored gradient mode type identifier
1985 \param c1 first gradient color is returned via this parameter
1986 \param c2 second gradient color is returned via this parameter
1987 \note the interpretation of the gradient identifier should be done in the calling code
1988 \sa gradient(QColor&, QColor&), mode()
1990 void Qtx::BackgroundData::setGradient( int type, const QColor& c1, const QColor& c2 )
1993 myColors << c1 << c2;
1994 myGradientType = type;
1995 setMode( Qtx::SimpleGradientBackground );
1999 \brief Get complex gradient data.
2000 Returns QGradient of QGradient::NoGradient if gradient data is not set
2001 \note This function does not transform simple gradient data set with
2002 setGradient( const QString&, const QColor&, const QColor& ) to QGradient class
2003 \return gradient data
2004 \sa setGradient(const QGradient&), mode()
2006 const QGradient* Qtx::BackgroundData::gradient() const
2012 \brief Set complex background gradient data and switch to the Qtx::CustomGradientBackground mode
2013 \param grad gradient data (QLinearGradient, QRadialGradient or QConicalGradient)
2014 \sa gradient(), mode()
2016 void Qtx::BackgroundData::setGradient( const QGradient& grad )
2019 setMode( Qtx::CustomGradientBackground );
2023 \brief Convert string representation of version identifier to the numerical value.
2024 Resulting value can be used for comparison of different versions (lower, higher, equal).
2026 String representation of the version consists of zero or more components:
2028 [major[.minor[.release[patchid]]]]
2031 - major is version major number
2032 - minor is version minor number
2033 - release is version release number
2034 - patchid is a version dev identifier which is one of the following
2035 * 1 letter optionally followed by 1 or 2 digits, e.g. "a" for "alpha", "b1" for "beta 1"
2036 * "rc" optionally followed by 1 or 2 digits, e.g. "rc1" for "release candidate 1"
2037 * "dev" for development version (note: 7.4.0dev > 7.4.0, 7.4.0dev < 7.4.1, 7.4.0dev < 7.4.0a1)
2039 If version string does not include any component or has invalid format, the function returns 0.
2043 1.2.3a - version 1.2.3 alpha
2044 3.3.3b1 - version 3.3.3 beta 1
2045 7.4.0rc1 - version 7.4.0 release candidate 1
2046 7.4.0dev - dev version, i.e. future version 7.4.1 (or 7.5.0)
2048 \param version string representation of version
2049 \return numerical identifier of the version
2051 long Qtx::versionToId( const QString& version )
2055 QRegExp vers_exp( "^([0-9]+)([A-Z]|RC|DEV)?([0-9]{0,2})$", Qt::CaseInsensitive );
2057 QStringList vers = version.split( ".", QString::SkipEmptyParts );
2058 int major=0, minor=0;
2059 int release = 0, dev1 = 0, dev2 = 0;
2060 if ( vers.count() > 0 ) major = vers[0].toInt();
2061 if ( vers.count() > 1 ) minor = vers[1].toInt();
2062 if ( vers.count() > 2 ) {
2063 if ( vers_exp.indexIn( vers[2] ) != -1 ) {
2064 release = vers_exp.cap( 1 ).toInt();
2065 QString tag = vers_exp.cap( 2 ).toLower();
2066 if ( !tag.isEmpty() ) {
2067 // patchid is subtracted from version number
2068 // a = 55 --> -(55 * 100) + patch number --> 4500..4599, e.g. 7.4.1a1 -> 704004501
2069 // b = 54 --> -(54 * 100) + patch number --> 4600..4699, e.g. 7.4.1b1 -> 704004601
2070 // c = 53 --> -(53 * 100) + patch number --> 4700..4799, e.g. 7.4.1c1 -> 704004701
2072 // z = 30 --> -( 1 * 100) + patch number --> 7000..7099, e.g. 7.4.1z1 -> 704007001
2073 // rc = 1 --> -( 1 * 100) + patch number --> 9900..9999, e.g. 7.4.1rc1 -> 704009901
2074 // dev = -1 --> +( 1 * 100) + patch number --> 0100..0199, e.g. 7.4.1dev -> 704010100
2076 // i.e. "a" < "b" < ... < "z" < "rc" < [stable] < "dev"
2079 else if ( tag == "dev" )
2082 dev1 = (int)( QChar('z').toLatin1() ) - (int)( tag[ 0 ].toLatin1() ) + 30;
2084 if ( !vers_exp.cap( 3 ).isEmpty() )
2085 dev2 = vers_exp.cap( 3 ).toInt();
2089 int dev = dev1*100-dev2;
2092 id*=100; id+=release;
2100 \brief Get Qt installation directory
2102 The function tries to detect qt installation directory by analyzing the system variables in the following order:
2108 Optional parameter \a context allows obtaining subdirectory in the Qt installation directory.
2110 \param context optional sub-directory
2111 \return path to the Qt installation directory (or its sub-folder, if \a context is specified)
2114 QString Qtx::qtDir( const QString& context )
2116 const char* vars[] = { "QT5_ROOT_DIR", "QT4_ROOT_DIR", "QT_ROOT_DIR", "QTDIR" };
2118 for (uint i = 0; i < sizeof(vars)/sizeof(vars[0]) && qtPath.isEmpty(); i++ )
2119 qtPath = qgetenv( vars[i] );
2120 if ( !qtPath.isEmpty() && !context.isEmpty() )
2121 qtPath = QDir( qtPath ).absoluteFilePath( context );
2126 Creates font from string description
2128 QFont Qtx::stringToFont( const QString& fontDescription )
2131 if ( fontDescription.trimmed().isEmpty() || !font.fromString( fontDescription ) )
2132 font = QFont( "Courier", 11 );
2136 #if !defined WIN32 && !defined __APPLE__
2138 #include <X11/Xlib.h>
2142 \brief Open the default X display and returns pointer to it.
2143 This method is available on Linux only.
2144 \return Pointer to X display.
2147 void* Qtx::getDisplay()
2149 static Display* pDisplay = NULL;
2151 pDisplay = XOpenDisplay( NULL );
2156 \brief Returns pointer to X visual suitable for 3D rendering.
2157 This method is available on Linux only.
2158 \return Pointer to X visual.
2161 Qt::HANDLE Qtx::getVisual()
2163 Qt::HANDLE res = (Qt::HANDLE)NULL;
2165 Display* pDisplay = (Display*)getDisplay();
2172 // Make sure OpenGL's GLX extension supported
2173 if( !glXQueryExtension( pDisplay, &errorBase, &eventBase ) ){
2174 qCritical( "Could not find glx extension" );
2178 // Find an appropriate visual
2180 int doubleBufferVisual[] = {
2181 GLX_RGBA, // Needs to support OpenGL
2182 GLX_DEPTH_SIZE, 16, // Needs to support a 16 bit depth buffer
2183 GLX_DOUBLEBUFFER, // Needs to support double-buffering
2184 GLX_STEREO, // Needs to support stereo rendering
2185 GLX_STENCIL_SIZE, 1,
2189 // Try for the double-bufferd visual first
2190 XVisualInfo *visualInfo = NULL;
2191 visualInfo = glXChooseVisual( pDisplay, DefaultScreen(pDisplay), doubleBufferVisual );
2193 if( visualInfo == NULL ){
2194 qCritical( "Could not find matching glx visual" );
2198 qDebug() << "Picked visual 0x" << hex << XVisualIDFromVisual( visualInfo->visual );
2199 res = (Qt::HANDLE)( visualInfo->visual );
2207 #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
2209 \brief Set default QSurfaceFormat for an application.
2211 This application property should be set before a creation of the QApplication.
2213 void Qtx::initDefaultSurfaceFormat()
2215 // Settings from Paraview:
2216 // This piece of code was taken from QVTKOpenGLWidget::defaultFormat() method in
2217 // order to avoid dependency of the SALOME_Session_Server on vtk libraries
2219 fmt.setRenderableType(QSurfaceFormat::OpenGL);
2220 fmt.setVersion(3, 2);
2221 fmt.setProfile(QSurfaceFormat::CoreProfile);
2222 fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
2223 fmt.setRedBufferSize(1);
2224 fmt.setGreenBufferSize(1);
2225 fmt.setBlueBufferSize(1);
2226 fmt.setDepthBufferSize(1);
2227 fmt.setStencilBufferSize(0);
2229 fmt.setAlphaBufferSize(0);
2231 fmt.setAlphaBufferSize(1);
2233 fmt.setStereo(false);
2236 // Settings for OCCT viewer window:
2237 fmt.setDepthBufferSize(16);
2238 fmt.setStencilBufferSize(1);
2239 // fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
2241 QSurfaceFormat::setDefaultFormat(fmt);
2246 \class Qtx::CmdLineArgs
2247 \brief Get access to the command line arguments in the C-like manner.
2249 This class translates command line arguments stored in QApplication in form of QStrlingList
2250 to the char* array, in the same way as they specified to main() function.
2252 Constructor of class allocates required memory to store arguments; destructor deallocates it,
2253 This allows using this class as a local variable:
2256 Qtx::CmdLineArgs args;
2257 some_function(args.argc(), args.argv()); // function that has main()-like syntax.
2262 \brief Default constructor.
2264 Qtx::CmdLineArgs::CmdLineArgs()
2266 QStringList args = QCoreApplication::arguments();
2267 myArgc = args.size();
2268 myArgv = new char*[myArgc];
2269 for ( int i = 0; i < myArgc; i++ ) {
2270 QByteArray ba = args[i].toUtf8();
2271 myArgv[i] = qstrdup(ba.constData());
2276 \brief Destructor. Deallocates the array with command line arguments
2278 Qtx::CmdLineArgs::~CmdLineArgs()
2280 for ( int i = 0; i < myArgc; i++ )
2286 \brief Get number of command line arguments
2287 \return number of arguments
2289 int Qtx::CmdLineArgs::argc() const
2295 \brief Get command line arguments
2296 \return command line arguments
2298 char** Qtx::CmdLineArgs::argv() const