1 // Copyright (C) 2007-2016 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>
47 #define BICOLOR_CHANGE_HUE
50 \brief Auxiliary function converting string \a str to the integer value.
51 Parameter \a defVal specifies default value that is returned if conversion can't be done.
52 Parameters \a minVal and \a maxVal limit the resulting value.
53 \param str string being converted
54 \param defVal default value
55 \param minVal minimum allowed value
56 \param maxVal maximum allowed value
57 \return integer value obtained from the string
60 static int stringToInt( const QString& str, int defVal, int minVal, int maxVal )
63 int v = str.toInt( &ok );
64 if ( !ok ) v = defVal;
65 return qMin( qMax( v, minVal ), maxVal );
70 \brief A set of helpful utility functions.
72 The class implements a set of the static functions which can be used
73 for the different purposes:
74 - specify tab order for the set of widgets: setTabOrder()
75 - align one widget to the coordinates of the another one: alignWidget()
76 - remove extra separators from the menu or toolbar: simplifySeparators()
77 - retrieve directory, file name and extension parts of the path:
78 dir(), file(), extension()
79 - get the path to the temporary directory: tmpDir()
80 - create or remove a directory (recursively): mkDir(), rmDir()
81 - convert text file from DOS to UNIX native format: dos2unix()
82 - convert a picture to the gray scale: grayscale()
87 \brief Convert character array (ASCII string) to the QString.
88 \param str character array
89 \param len array length, if < 0, the array should be zero-terminated
90 \return QString object
92 QString Qtx::toQString( const char* str, const int len )
94 return toQString( (unsigned char*)str, len );
98 \brief Convert integer array (UNICODE string) to the QString.
99 \param str integer array
100 \param len array length, if < 0, the array should be zero-terminated
101 \return QString object
103 QString Qtx::toQString( const short* str, const int len )
105 return toQString( (unsigned short*)str, len );
109 \brief Convert character array (ASCII string) to the QString.
110 \param str character array
111 \param len array length, if < 0, the array should be zero-terminated
112 \return QString object
114 QString Qtx::toQString( const unsigned char* str, const int len )
117 const unsigned char* s = str;
118 while ( len < 0 || res.length() < len )
123 res.append( QChar( *s ) );
130 \brief Convert integer array (UNICODE string) to the QString.
131 \param str integer array
132 \param len array length, if < 0, the array should be zero-terminated
133 \return QString object
135 QString Qtx::toQString( const unsigned short* str, const int len )
138 const unsigned short* s = str;
139 while ( len < 0 || res.length() < len )
144 res.append( QChar( *s ) );
151 \brief Set tab order for specified list of widgets.
153 The function has arbitrary number of parameters, each should be
154 hovewer of QWidget* type. Last parameter should be null pointer.
156 \param first first widget in the sequence
158 void Qtx::setTabOrder( QWidget* first, ... )
161 va_start( wids, first );
165 QWidget* cur = first;
168 widList.append( cur );
169 cur = va_arg( wids, QWidget* );
172 setTabOrder( widList );
176 \brief Set tab order for specified list of widgets.
177 \param widgets list of widgets
179 void Qtx::setTabOrder( const QWidgetList& widgets )
181 if ( widgets.count() < 2 )
185 for ( QWidgetList::const_iterator it = widgets.begin(); it!= widgets.end(); ++it )
189 QWidget::setTabOrder( prev, next );
195 \brief Align widget \a src relative to widget \a ref acording to the
196 alignment flags \a alignFlags.
197 \param src source widget (being aligned)
198 \param ref reference widget (source widget being aligned to)
199 \param alignFlags alignment flags (Qtx::AlignmentFlags)
201 void Qtx::alignWidget( QWidget* src, const QWidget* ref, const int alignFlags )
203 if ( !src || !ref || !alignFlags )
206 QPoint srcOri = src->pos();
207 QPoint refOri = ref->pos();
208 if ( src->parentWidget() && !src->isTopLevel() )
209 srcOri = src->parentWidget()->mapToGlobal( srcOri );
210 if ( ref->parentWidget() && !ref->isTopLevel() )
211 refOri = ref->parentWidget()->mapToGlobal( refOri );
213 int x = srcOri.x(), y = srcOri.y();
214 int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
215 int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
218 srcWidth = src->sizeHint().width();
220 srcHei = src->sizeHint().height();
223 if ( ref->isTopLevel() && ref->isMaximized() &&
224 src->isTopLevel() && !src->isMaximized() )
225 border = ( src->frameGeometry().width() - src->width() ) / 2;
227 if ( alignFlags & Qtx::AlignLeft )
228 x = refOri.x() + border;
229 if ( alignFlags & Qtx::AlignOutLeft )
230 x = refOri.x() - srcWidth - border;
231 if ( alignFlags & Qtx::AlignRight )
232 x = refOri.x() + refWidth - srcWidth - border;
233 if ( alignFlags & Qtx::AlignOutRight )
234 x = refOri.x() + refWidth + border;
235 if ( alignFlags & Qtx::AlignTop )
236 y = refOri.y() + border;
237 if ( alignFlags & Qtx::AlignOutTop )
238 y = refOri.y() - srcHei - border;
239 if ( alignFlags & Qtx::AlignBottom )
240 y = refOri.y() + refHei - srcHei - border;
241 if ( alignFlags & Qtx::AlignOutBottom )
242 y = refOri.y() + refHei + border;
243 if ( alignFlags & Qtx::AlignHCenter )
244 x = refOri.x() + ( refWidth - srcWidth ) / 2;
245 if ( alignFlags & Qtx::AlignVCenter )
246 y = refOri.y() + ( refHei - srcHei ) / 2;
248 if ( src->parentWidget() && !src->isTopLevel() )
250 QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
255 QWidget* desk = QApplication::desktop();
256 if ( desk && x + srcWidth + border > desk->width() )
257 x = desk->width() - srcWidth - border;
258 if ( desk && y + srcHei + border > desk->height() )
259 y = desk->height() - srcHei - border;
268 \brief Remove (recursively) unnecessary separators from the menu or toolbar.
269 \param wid widget, should be of QMenu* or QToolBar* class
271 void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
276 QList<QAction*> items = wid->actions();
277 if ( items.isEmpty() )
281 for ( int i = 0; i < items.count(); i++ )
283 QAction* a = items[i];
284 if ( a->isSeparator() ) {
285 a->setVisible(action);
288 else if ( a->isVisible() ) {
290 if ( recursive && a->menu() )
291 simplifySeparators( a->menu(), recursive );
296 for ( int i = items.count() - 1; i > 0; i-- ) {
297 QAction* a = items[i];
298 if ( a->isSeparator() ) {
299 a->setVisible(action);
302 else if ( a->isVisible() )
308 \brief Return \c true if specified \a parent is a parent object
309 of given \a child (in terms of QObject).
311 This function works recursively. It means that \a true is also
312 returned if \a parent is a grand-father, grand-grand-father, etc
313 of \a child. If the same object is given as both \a parent and
314 \a child, \c true is also returned.
316 \param child child object
317 \param parent parent object
318 \return \c true if the \a parent is a parent of \a child
320 bool Qtx::isParent( QObject* child, QObject* parent )
322 if ( !child || !parent )
326 QObject* obj = child;
327 while ( !res && obj )
336 \brief Find the parent object of class specified by \a className (in terms of QObject).
338 \param obj current object
339 \param className class name of the parent
340 \return parent object or null pointer if the parent not found
342 QObject* Qtx::findParent( QObject* obj, const char* className )
347 if ( !className || !strlen( className ) )
348 return obj->parent();
351 QObject* p = obj->parent();
354 if ( p->inherits( className ) )
363 \brief Return directory part of the file path.
365 If the file path does not include directory part (the file is in the
366 current directory), null string is returned.
368 \param path file path
369 \param abs if true (default) \a path parameter is treated as absolute file path
370 \return directory part of the file path
372 QString Qtx::dir( const QString& path, const bool abs )
374 QDir aDir = QFileInfo( path ).dir();
375 QString dirPath = abs ? aDir.absolutePath() : aDir.path();
376 if ( dirPath == QString( "." ) )
382 \brief Return file name part of the file path.
384 \param path file path
385 \param withExt if true (default) complete file name (with all
386 extension except the last) is returned, otherwise only base name
388 \return file name part of the file path
390 QString Qtx::file( const QString& path, bool withExt )
392 QString fPath = path;
393 while ( !fPath.isEmpty() && ( fPath[fPath.length() - 1] == '\\' || fPath[fPath.length() - 1] == '/' ) )
394 fPath.remove( fPath.length() - 1, 1 );
397 return QFileInfo( fPath ).fileName();
399 return QFileInfo( fPath ).completeBaseName();
403 \brief Return extension part of the file path.
405 \param path file path
406 \param full if true complete extension (all extensions, dot separated)
407 is returned, otherwise (default) only last extension is returned
408 \return extension part of the file path
410 QString Qtx::extension( const QString& path, const bool full )
412 return full ? QFileInfo( path ).completeSuffix() : QFileInfo( path ).suffix();
416 \brief Convert the given parameter to the platform-specific library name.
418 The function appends platform-specific prefix (lib) and suffix (.dll/.so)
419 to the library file name.
420 For example, if \a str = "mylib", "libmylib.so" is returned for Linux and
421 mylib.dll for Windows.
423 \param str short library name
424 \return full library name
426 QString Qtx::library( const QString& str )
428 QString path = dir( str, false );
429 QString name = file( str, false );
430 QString ext = extension( str );
433 if ( !name.startsWith( "lib" ) )
434 name = QString( "lib" ) + name;
438 QString libExt( "dll" );
439 #elif defined(__APPLE__)
440 QString libExt( "dylib" );
442 QString libExt( "so" );
445 if ( ext.toLower() != QString( "so" ) && ext.toLower() != QString( "dll" ) && ext.toLower() != QString( "dylib" ) )
447 if ( !name.isEmpty() && !ext.isEmpty() )
448 name += QString( "." );
454 QString fileName = addSlash( path ) + name + QString( "." ) + ext;
460 \brief Get the temporary directory name.
461 \return temporary directory (platform specific)
463 QString Qtx::tmpDir()
465 const char* tmpdir = ::getenv( "TEMP" );
467 tmpdir = ::getenv ( "TMP" );
476 return QString( tmpdir );
480 \brief Create directory recursively including all intermediate sub directories.
481 \return \c true if the directory is successfully created and \c false otherwise
483 bool Qtx::mkDir( const QString& dirPath )
485 return QDir().mkpath( dirPath );
489 \brief Remove directory recursively including all subdirectories and files.
490 \return \c true if the directory is successfully removed and \c false otherwise
492 bool Qtx::rmDir( const QString& thePath )
494 QFileInfo fi( thePath );
500 stat = QFile::remove( thePath );
501 else if ( fi.isDir() )
503 QDir aDir( thePath );
504 QFileInfoList anEntries = aDir.entryInfoList();
505 for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
508 if ( inf.fileName() == "." || inf.fileName() == ".." )
510 stat = stat && rmDir( inf.absoluteFilePath() );
512 stat = stat && aDir.rmdir( thePath );
518 \brief Add a slash (platform-specific) to the end of \a path
519 if it is not already there.
520 \param path directory path
521 \return modified path (with slash added to the end)
523 QString Qtx::addSlash( const QString& path )
526 if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
527 res.at( res.length() - 1 ) != QChar( '\\' ) )
528 res += QDir::separator();
533 \brief Convert text file from DOS format to UNIX.
535 The function replaces "LF/CR" symbols sequence by "LF" symbol.
537 \param absName file name
538 \return \c true if the file is converted successfully and \c false in
541 bool Qtx::dos2unix( const QString& absName )
543 FILE* src = ::fopen( absName.toLatin1(), "rb" );
547 /* we'll use temporary file */
548 char temp[512] = { '\0' };
549 QString dir = Qtx::dir( absName );
550 FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toLatin1(), "__x" ) ), "wb" );
554 /* temp -> result of conversion */
555 const char CR = 0x0d;
556 const char LF = 0x0a;
557 bool waitingLF = false;
562 char inbuf[512], outbuf[512];
565 int nbread = ::fread( inbuf, 1, sizeof( inbuf ), src );
566 for ( int incnt = 0; incnt < nbread; incnt++ )
571 if ( inbuf[incnt] == LF )
572 outbuf[outcnt++] = LF;
574 outbuf[outcnt++] = CR;
576 else if ( inbuf[incnt] == CR )
579 outbuf[outcnt++] = inbuf[incnt];
582 /* check last sym in buffer */
583 waitingLF = ( inbuf[nbread - 1] == CR );
585 /* write converted buffer to temp file */
586 int nbwri = ::fwrite( outbuf, 1, outcnt, tgt );
587 if ( nbwri != outcnt )
591 QFile::remove( QString( temp ) );
594 if ( nbread != sizeof( inbuf ) )
595 break; /* converted ok */
600 /* rename temp -> src */
601 if ( !QFile::remove( absName ) )
604 return QDir().rename( QString( temp ), absName );
608 \brief Create path completer which can be used in the widgets
609 to provide auto completions.
611 Create an instance of QCompleter class and returns the pointer on it.
612 The calling function is responsible to the desstroying of the created
615 The QCompleter class provides completions based on a item model and can be
616 used in such as QLineEdit and QComboBox.
617 When the user starts typing a word, QCompleter suggests possible ways of
618 completing the word, based on a word list.
620 \param type path type (Qtx::PathType)
621 \param filter file/directory filters (list of wildcards, separated by ";;")
622 \return a pointer to the created completer
624 QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
627 QStringList filterList = filter.split( ";;" );
628 for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
630 QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
632 while ( ( index = rx.indexIn( *it, index ) ) != -1 )
634 extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
635 index += rx.matchedLength();
639 QDir::Filters filters = 0;
644 filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
647 filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
651 QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
652 QCompleter* cmp = new QCompleter( dm, 0 );
653 dm->setParent( cmp );
659 \brief Parse given string to retrieve environment variable.
661 Looks through the string for the environment variable patterns.
662 If string contains variable satisfying any pattern, the variable name
663 is returned, start index of the variable is returned in the \a start parameter,
664 and length of the variable is returned in the \a len parameter.
666 Supported environment variables definitions:
667 - ${name} or $name : Linux shell variable
668 - $(name) : GNU make substitution
669 - %name% : Windows shell variable
670 - %(name)s : Python substitutions:
672 \param str string being processed
673 \param start if variable is found, this parameter contains its starting
674 position in the \a str
675 \param len if variable is found, this parameter contains its length
676 \return first found variable or null QString if there is no ones
678 QString Qtx::findEnvVar( const QString& str, int& start, int& len )
684 rxList << "\\$\\{([a-zA-Z][a-zA-Z_0-9]*)\\}"; // ${name}
685 rxList << "\\$([a-zA-Z][a-zA-Z_0-9]*)"; // $name
686 rxList << "\\$\\(([a-zA-Z][a-zA-Z_0-9]*)\\)"; // $(name)
687 rxList << "%([a-zA-Z][a-zA-Z0-9_]*)%"; // %name%
688 rxList << "%\\(([a-zA-Z][a-zA-Z_0-9]*)\\)s"; // %(name)s
690 for ( int i = 0; i < rxList.count() && varName.isEmpty(); ++i )
692 QRegExp rx(rxList[i]);
693 int pos = rx.indexIn( str, start );
696 varName = rx.cap( 1 );
698 len = rx.matchedLength();
705 \brief Substitute environment variables by their values.
707 Environment variable is substituted by its value.
709 \param str string to be processed
710 \return processed string (with all substitutions made)
712 QString Qtx::makeEnvVarSubst( const QString& str, const SubstMode mode )
717 QMap<QString, int> ignoreMap;
719 int start( 0 ), len( 0 );
722 QString envName = findEnvVar( res, start, len );
723 if ( envName.isNull() )
727 if ( ::getenv( envName.toLatin1() ) || mode == Always )
728 newStr = QString( ::getenv( envName.toLatin1() ) );
730 if ( newStr.isNull() )
732 if ( ignoreMap.contains( envName ) )
737 ignoreMap.insert( envName, 0 );
739 res.replace( start, len, newStr );
742 res.replace( "$$", "$" );
743 res.replace( "%%", "%" );
750 \brief Pack the specified color into integer RGB set.
751 \param c unpacked color
754 int Qtx::rgbSet( const QColor& c )
756 return rgbSet( c.red(), c.green(), c.blue() );
760 \brief Pack the specified RGB color components into integer RGB set.
761 \param r red component
762 \param g green component
763 \param b blue component
766 int Qtx::rgbSet( const int r, const int g, const int b )
768 return ( ( ( 0xff & r ) << 16 ) + ( ( 0xff & g ) << 8 ) + ( 0xff & b ) );
772 \brief Unpack the specified integer RGB set to the color.
773 \param rgb packed color
774 \return unpacked color (QColor)
776 QColor Qtx::rgbSet( const int rgb )
779 rgbSet( rgb, r, g, b );
780 return QColor( r, g, b );
784 \brief Unpack the specified integer RGB set to the three RGB components.
785 \param rgb packed color
786 \param r returned unpacked red component
787 \param g returned unpacked green component
788 \param b returned unpacked blue component
790 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
792 r = ( rgb >> 16 ) & 0xff;
793 g = ( rgb >> 8 ) & 0xff;
798 \brief Return the color specified by the index between min (blue) and max (red).
799 \param index color index
800 \param min required minimum hue value
801 \param max required maximum hue value
802 \return resulting color
804 QColor Qtx::scaleColor( const int index, const int min, const int max )
806 static const int HUE[10] = {230, 210, 195, 180, 160, 80, 60, 50, 30, 0};
812 double aPosition = 9.0 * ( index - min ) / ( max - min );
813 if ( aPosition > 0.0 )
815 if ( aPosition >= 9.0 )
819 int idx = (int)aPosition;
820 hue = HUE[idx] + int( ( aPosition - idx ) * ( HUE[idx + 1] - HUE[idx] ) );
825 return QColor::fromHsv( hue, 255, 255 );
829 \brief Generate required number of colors aligned from blue to red.
830 \param num required number of colors
831 \param lst returned set of colors
833 void Qtx::scaleColors( const int num, QColorList& lst )
836 for ( int i = 0; i < num; i++ )
837 lst.append( scaleColor( i, 0, num - 1 ) );
841 \brief Scale the pixmap to the required size.
843 If \a h is 0 (default) the value of \a w is used instead (to create
846 \param icon pixmap to be resized
847 \param w required pixmap width
848 \param h required pixmap height
849 \return scaled pixmap
851 QPixmap Qtx::scaleIcon( const QPixmap& icon, const unsigned w, const unsigned h )
854 int aw = w, ah = h <= 0 ? w : h;
855 if ( icon.isNull() || aw <= 0 || ah <= 0 || ( aw == icon.width() && ah == icon.height() ) )
858 p = icon.fromImage( icon.toImage().scaled( aw, ah, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
863 \brief Convert given image to the grayscale format.
864 \param img initial image
865 \return converted to the grayscale image
867 QImage Qtx::grayscale( const QImage& img )
871 int colNum = res.colorCount();
874 for ( int i = 0; i < colNum; i++ )
875 res.setColor( i, qGray( res.color( i ) ) );
879 for ( int y = 0; y < res.height(); y++ )
881 for ( int x = 0; x < res.width(); x++ )
883 QRgb pix = res.pixel( x, y );
884 res.setPixel( x, y, qRgba( qGray( pix ), qGray( pix ), qGray( pix ), qAlpha( pix ) ) );
893 \brief Convert given pixmap to the grayscale format.
894 \param pix initial pixmap
895 \return converted to the grayscale pixmap
897 QPixmap Qtx::grayscale( const QPixmap& pix )
900 res.fromImage( grayscale( pix.toImage() ) );
905 \brief Create transparent image.
906 \param w required image width
907 \param h required image height
908 \param d required image depth
909 \return generated image
911 QImage Qtx::transparentImage( const int w, const int h, const int d )
917 fmt = QImage::Format_Mono;
920 fmt = QImage::Format_Indexed8;
926 fmt = QImage::Format_ARGB32;
930 QImage img( w, h, fmt );
933 // img.setAlphaBuffer( true );
934 for ( int i = 0; i < img.height(); i++ )
935 for ( int j = 0; j < img.width(); j++ )
936 img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) );
942 \brief Create transparent pixmap.
943 \param w required image width
944 \param h required pixmap height
945 \param d required pixmap depth
946 \return generated pixmap
948 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
951 QImage img = transparentImage( w, h, d );
953 pix.fromImage( img );
958 \brief Create composite pixmap.
960 Pixmap \a pix is drawn over pixmap \a dest with coordinates
961 specified relatively to the upper left corner of \a dest.
962 If \a dest is not given, the new empty pixmap with appropriate size created instead.
964 \param pix source pixmap
965 \param x horizontal shift
966 \param y vertical shift
967 \param dest background pixmap
968 \return resulting pixmap
970 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
975 int width = qMax( pix.width() + x, dest.width() );
976 int height = qMax( pix.height() + y, dest.height() );
978 QPixmap res( width, height );
979 QImage img = transparentImage( width, height, 32 );
983 p.fillRect( 0, 0, width, height, QBrush( Qt::white ) );
985 if ( !dest.isNull() )
987 p.drawPixmap( 0, 0, dest );
988 QImage temp = dest.toImage();
989 for ( int i = 0; i < temp.width() && i < img.width(); i++ )
991 for ( int j = 0; j < temp.height() && j < img.height(); j++ )
993 if ( temp.hasAlphaChannel() )
994 img.setPixel( i, j, temp.pixel( i, j ) );
997 QRgb p = temp.pixel( i, j );
998 img.setPixel( i, j, qRgba( qRed( p ), qGreen( p ), qBlue( p ), 255 ) );
1004 p.drawPixmap( x, y, pix );
1005 QImage temp = pix.toImage();
1006 for ( int c = x; c < temp.width() + x && c < img.width(); c++ )
1008 for ( int r = y; r < temp.height() + y && r < img.height(); r++ )
1010 if ( qAlpha( temp.pixel( c - x, r - y ) ) > 0 )
1011 img.setPixel( c, r, temp.pixel( c - x, r - y ) );
1017 for ( int ai = 0; ai < img.width(); ai++ )
1019 for ( int aj = 0; aj < img.height(); aj++ )
1021 if ( qAlpha( img.pixel( ai, aj ) ) < 1 )
1022 img.setPixel( ai, aj, qRgba( 255, 255, 255, 255 ) );
1024 img.setPixel( ai, aj, qRgba( 0, 0, 0, 0 ) );
1028 QBitmap bmp( width, height );
1029 bmp.fromImage( img, Qt::ColorMode_Mask | Qt::ThresholdDither );
1036 \brief Convert color to the string representation.
1038 The resulting string is in the one of two possible formats
1039 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1040 and alpha components of the color):
1041 - if color has alpha channel : "#RR,#GG,#BB,#AA"
1042 - if color does not have alpha channel : "#RRGGBB"
1044 If color is invalid, null string is returned.
1046 Backward conversion can be done with stringToColor() method.
1048 \param color color to be converted
1049 \return string representation of the color
1053 QString Qtx::colorToString( const QColor& color )
1056 if ( color.isValid() )
1058 if ( color.alpha() != 255 )
1061 vals << QString( "#%1" ).arg( color.red(), 0, 16 );
1062 vals << QString( "#%1" ).arg( color.green(), 0, 16 );
1063 vals << QString( "#%1" ).arg( color.blue(), 0, 16 );
1064 vals << QString( "#%1" ).arg( color.alpha(), 0, 16 );
1065 str = vals.join( "," );
1076 \brief Create color from the string representation.
1078 The parameter \a str must be in the one of following formats
1079 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1080 and alpha components of the color):
1081 - "#RR,#GG,#BB[,#AA]" or "#RR #GG #BB[ #AA]" (\c RR, \c GG, \c BB
1082 and optional \c AA values represent red, green, blue and alpha
1083 components of the color in hexadecimal form)
1084 - "RR,GG,BB[,AA]" or "RR GG BB[ AA]" (\c RR, \c GG, \c BB
1085 and optional \c AA values represent red, green, blue and alpha
1086 components of the color in decimal form)
1087 - "#RRGGBB" - (\c RR, \c GG and \c BB values represent red, green and blue
1088 components of the color in hexadecimal form)
1089 - an integer value representing packed color components (see rgbSet())
1090 - a name from the list of colors defined in the list of SVG color keyword names
1091 provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
1093 Backward conversion can be done with colorToString() method.
1095 \param str string representation of the color
1096 \param color resulting color value
1097 \return \c true if the conversion is successful and \c false otherwise
1099 \sa colorToString(), rgbSet()
1101 bool Qtx::stringToColor( const QString& str, QColor& color )
1104 QStringList vals = str.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1107 for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
1110 if ( (*it).startsWith( "#" ) )
1111 num = (*it).mid( 1 ).toInt( &res, 16 );
1113 num = (*it).toInt( &res, 10 );
1118 res = res && nums.count() >= 3;
1120 color.setRgb( nums[0], nums[1], nums[2] );
1124 int pack = str.toInt( &res );
1126 color = Qtx::rgbSet( pack );
1131 color = QColor( str );
1132 res = color.isValid();
1139 \brief Convert bi-color value to the string representation.
1141 Bi-color value is specified as main color and integer delta
1142 value that is used to calculate secondary color by changing
1143 paremeters of the main color ("saturation" and "value"
1144 components in HSV notation).
1146 The resulting string consists of two sub-strings separated by
1147 '|' symbol. The first part represents main color
1148 (see colorToString() for more details), the second part is a
1151 Backward conversion can be done with stringToBiColor() method.
1153 \param color color to be converted
1154 \param delta delta value
1155 \return string representation of the bi-color value
1157 \sa stringToBiColor(), stringToColor()
1159 QString Qtx::biColorToString( const QColor& color, const int delta )
1161 return QString("%1|%2").arg( Qtx::colorToString( color ) ).arg( delta );
1165 \brief Restore bi-color value from the string representation.
1167 Bi-color value is specified as main color and integer delta
1168 value that is used to calculate secondary color by changing
1169 paremeters of the main color ("saturation" and "value"
1170 components in HSV notation).
1172 The parameter \a str should consist of two sub-strings separated
1173 by '|' symbol. The first part represents main color
1174 (see stringToColor() for more details), the second part is a
1177 Backward conversion can be done with biColorToString() method.
1179 \param str string representation of the bi-color value
1180 \param color resulting color value
1181 \param delta resulting delta value
1182 \return \c true if the conversion is successful and \c false otherwise
1184 \sa biColorToString(), stringToColor(), rgbSet()
1186 bool Qtx::stringToBiColor( const QString& str, QColor& color, int& delta )
1188 QStringList data = str.split( "|", QString::KeepEmptyParts );
1191 bool ok = data.count() > 0 && Qtx::stringToColor( data[0], c );
1193 if ( data.count() > 1 ) d = data[1].toInt( &dok );
1195 color = ok ? c : QColor();
1201 \brief Compute secondary color value from specified main color
1204 Secondary color is calculated by changing paremeters of the main
1205 color ("saturation" and "value" components in HSV notation) using
1208 If main color is invalid, result of the function is also invalid color.
1210 \param color source main color
1211 \param delta delta value
1212 \return resulting secondary color
1214 \sa biColorToString(), stringToBiColor()
1216 QColor Qtx::mainColorToSecondary( const QColor& color, int delta )
1219 if ( cs.isValid() ) {
1220 int val = qMin( 255, qMax( cs.value() + delta, 0 ) );
1221 int sat = qMin( 255, qMax( cs.saturation() + delta-(val-cs.value()), 0 ) );
1222 #ifdef BICOLOR_CHANGE_HUE
1223 const int BICOLOR_HUE_MAXDELTA = 40;
1224 int dh = delta-(val-cs.value())-(sat-cs.saturation());
1225 dh = qMin( BICOLOR_HUE_MAXDELTA, qAbs( dh ) ) * ( dh > 0 ? 1 : -1 );
1226 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-(sat-cs.saturation()), 0 ) );
1227 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-ds, 0 ) );
1228 int hue = cs.hue() + dh;
1229 if ( hue < 0 ) hue = 360 - hue;
1233 cs.setHsv( hue, sat, val );
1239 \brief Dump linear gradient to the string description.
1240 \param gradient linear gradient to be converted
1241 \return string representation of the linear gradient
1242 \sa stringToLinearGradient()
1244 QString Qtx::gradientToString( const QLinearGradient& gradient )
1248 data << QString::number( gradient.start().x() );
1249 data << QString::number( gradient.start().y() );
1250 data << QString::number( gradient.finalStop().x() );
1251 data << QString::number( gradient.finalStop().y() );
1252 switch( gradient.spread() )
1254 case QGradient::PadSpread:
1257 case QGradient::RepeatSpread:
1260 case QGradient::ReflectSpread:
1266 QGradientStops stops = gradient.stops();
1268 foreach ( stop, stops )
1270 data << QString::number( stop.first );
1271 data << colorToString( stop.second );
1273 return data.join( "|" );
1277 \brief Dump radial gradient to the string description.
1278 \param gradient radial gradient to be converted
1279 \return string representation of the radial gradient
1280 \sa stringToRadialGradient()
1282 QString Qtx::gradientToString( const QRadialGradient& gradient )
1286 data << QString::number( gradient.center().x() );
1287 data << QString::number( gradient.center().y() );
1288 data << QString::number( gradient.focalPoint().x() );
1289 data << QString::number( gradient.focalPoint().y() );
1290 data << QString::number( gradient.radius() );
1291 switch( gradient.spread() )
1293 case QGradient::PadSpread:
1296 case QGradient::RepeatSpread:
1299 case QGradient::ReflectSpread:
1305 QGradientStops stops = gradient.stops();
1307 foreach ( stop, stops )
1309 data << QString::number( stop.first );
1310 data << colorToString( stop.second );
1312 return data.join( "|" );
1316 \brief Dump conical gradient to the string description.
1317 \param gradient conical gradient to be converted
1318 \return string representation of the conical gradient
1319 \sa stringToConicalGradient()
1321 QString Qtx::gradientToString( const QConicalGradient& gradient )
1325 data << QString::number( gradient.center().x() );
1326 data << QString::number( gradient.center().y() );
1327 data << QString::number( gradient.angle() );
1328 switch( gradient.spread() )
1330 case QGradient::PadSpread:
1333 case QGradient::RepeatSpread:
1336 case QGradient::ReflectSpread:
1342 QGradientStops stops = gradient.stops();
1344 foreach ( stop, stops )
1346 data << QString::number( stop.first );
1347 data << colorToString( stop.second );
1349 return data.join( "|" );
1353 \brief Create linear gradient from its string representation.
1354 \param str string representation of the linear gradient
1355 \param gradient resulting linear gradient object
1356 \return \c true if the conversion is successful and \c false otherwise
1357 \sa gradientToString()
1359 bool Qtx::stringToLinearGradient( const QString& str, QLinearGradient& gradient )
1361 bool success = false;
1362 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1363 if ( vals.count() > 4 && ( vals[0] == "linear" || vals[0] == "lg" ) )
1365 // start and end points
1366 double x1, y1, x2, y2;
1367 bool bOk1, bOk2, bOk3, bOk4;
1368 x1 = vals[1].toDouble( &bOk1 );
1369 y1 = vals[2].toDouble( &bOk2 );
1370 x2 = vals[3].toDouble( &bOk3 );
1371 y2 = vals[4].toDouble( &bOk4 );
1372 if ( bOk1 && bOk2 && bOk3 && bOk4 )
1374 gradient = QLinearGradient( x1, y1, x2, y2 );
1376 if ( vals.count() > 5 )
1378 QString spread = vals[ 5 ].trimmed().toLower();
1379 if ( spread == "pad" || spread == "0" )
1380 gradient.setSpread( QGradient::PadSpread );
1381 else if ( spread == "repeat" || spread == "2" )
1382 gradient.setSpread( QGradient::RepeatSpread );
1383 else if ( spread == "reflect" || spread == "1" )
1384 gradient.setSpread( QGradient::ReflectSpread );
1387 QGradientStops stops;
1388 for ( int i = 6; i < vals.count(); i+=2 )
1390 bool bOk5, bOk6 = false;
1392 double stop = vals[i].toDouble( &bOk5 );
1393 if ( i+1 < vals.count() )
1394 bOk6 = stringToColor( vals[ i+1 ], c );
1395 if ( bOk5 && stop >= 0.0 && stop <= 1.0 && bOk6 && c.isValid() )
1396 stops.append( QGradientStop( stop, c ) );
1398 gradient.setStops( stops );
1406 \brief Create radial gradient from its string representation.
1407 \param str string representation of the radial gradient
1408 \param gradient resulting radial gradient object
1409 \return \c true if the conversion is successful and \c false otherwise
1410 \sa gradientToString()
1412 bool Qtx::stringToRadialGradient( const QString& str, QRadialGradient& gradient )
1414 bool success = false;
1415 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1416 if ( vals.count() > 5 && ( vals[0] == "radial" || vals[0] == "rg" ) )
1418 // center, radius and focal point
1419 double cx, cy, r, fx, fy;
1420 bool bOk1, bOk2, bOk3, bOk4, bOk5;
1421 cx = vals[1].toDouble( &bOk1 );
1422 cy = vals[2].toDouble( &bOk2 );
1423 fx = vals[3].toDouble( &bOk4 );
1424 fy = vals[4].toDouble( &bOk5 );
1425 r = vals[5].toDouble( &bOk3 );
1426 if ( bOk1 && bOk2 && bOk3 && bOk4 && bOk5 )
1428 gradient = QRadialGradient( cx, cy, r, fx, fy );
1430 if ( vals.count() > 6 )
1432 QString spread = vals[ 6 ].trimmed().toLower();
1433 if ( spread == "pad" || spread == "0" )
1434 gradient.setSpread( QGradient::PadSpread );
1435 else if ( spread == "repeat" || spread == "2" )
1436 gradient.setSpread( QGradient::RepeatSpread );
1437 else if ( spread == "reflect" || spread == "1" )
1438 gradient.setSpread( QGradient::ReflectSpread );
1441 QGradientStops stops;
1442 for ( int i = 7; i < vals.count(); i+=2 )
1444 bool bOk7, bOk8 = false;
1446 double stop = vals[i].toDouble( &bOk7 );
1447 if ( i+1 < vals.count() )
1448 bOk8 = stringToColor( vals[ i+1 ], c );
1449 if ( bOk7 && stop >= 0.0 && stop <= 1.0 && bOk8 && c.isValid() )
1450 stops.append( QGradientStop( stop, c ) );
1452 gradient.setStops( stops );
1460 \brief Create conical gradient from its string representation.
1461 \param str string representation of the conical gradient
1462 \param gradient resulting conical gradient object
1463 \return \c true if the conversion is successful and \c false otherwise
1464 \sa gradientToString()
1466 bool Qtx::stringToConicalGradient( const QString& str, QConicalGradient& gradient )
1468 bool success = false;
1469 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1470 if ( vals.count() > 3 && ( vals[0] == "conical" || vals[0] == "cg" ) )
1474 bool bOk1, bOk2, bOk3;
1475 cx = vals[1].toDouble( &bOk1 );
1476 cy = vals[2].toDouble( &bOk2 );
1477 a = vals[3].toDouble( &bOk3 );
1478 if ( bOk1 && bOk2 && bOk3 )
1480 gradient = QConicalGradient( cx, cy, a );
1482 if ( vals.count() > 4 )
1484 QString spread = vals[ 4 ].trimmed().toLower();
1485 if ( spread == "pad" || spread == "0" )
1486 gradient.setSpread( QGradient::PadSpread );
1487 else if ( spread == "repeat" || spread == "2" )
1488 gradient.setSpread( QGradient::RepeatSpread );
1489 else if ( spread == "reflect" || spread == "1" )
1490 gradient.setSpread( QGradient::ReflectSpread );
1493 QGradientStops stops;
1494 for ( int i = 5; i < vals.count(); i+=2 )
1496 bool bOk4, bOk5 = false;
1498 double stop = vals[i].toDouble( &bOk4 );
1499 if ( i+1 < vals.count() )
1500 bOk5 = stringToColor( vals[ i+1 ], c );
1501 if ( bOk4 && stop >= 0.0 && stop <= 1.0 && bOk5 && c.isValid() )
1502 stops.append( QGradientStop( stop, c ) );
1504 gradient.setStops( stops );
1512 \brief Convert background data to the string representation.
1513 The resulting string consists of several sub-strings separated by ';' symbol.
1514 These sub-strings represent:
1515 1. background type (enumerator, see Qtx::BackgroundMode)
1516 2. texture image file name (string)
1517 3. texture mode (enumerator, see Qtx::TextureMode)
1518 4. "show texture" flag (boolean)
1519 5. first color (for simple gradient data) or solid color (for single-colored mode)
1520 6. second color (for simple gradient data)
1521 7. type of simple gradient (some integer identifier)
1522 8. complex gradient data (for custom gradient mode)
1523 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1525 Backward conversion can be done with stringToBackground() method.
1527 \param bgData background data
1528 \return string representation of the background data
1530 \sa stringToBackground()
1532 QString Qtx::backgroundToString( const Qtx::BackgroundData& bgData )
1534 const QString dtSep = ";";
1535 const QString kwSep = "=";
1536 const QString kwBgType = "bt";
1537 const QString kwFileName = "fn";
1538 const QString kwTextureMode = "tm";
1539 const QString kwShowTexture = "ts";
1540 const QString kwFirstColor = "c1";
1541 const QString kwSecondColor = "c2";
1542 const QString kwGrType = "gt";
1543 const QString kwGrData = "gr";
1545 Qtx::BackgroundMode bgMode = bgData.mode();
1547 Qtx::TextureMode textureMode = bgData.texture( fileName );
1548 bool showTexture = bgData.isTextureShown();
1550 int gradientType = bgData.gradient( c1, c2 );
1551 const QGradient* gradient = bgData.gradient();
1554 switch ( gradient->type() ) {
1555 case QGradient::LinearGradient:
1556 grString = gradientToString( *(static_cast<const QLinearGradient*>( gradient )) );
1558 case QGradient::RadialGradient:
1559 grString = gradientToString( *(static_cast<const QRadialGradient*>( gradient )) );
1561 case QGradient::ConicalGradient:
1562 grString = gradientToString( *(static_cast<const QConicalGradient*>( gradient )) );
1569 data << QString( "%1%2%3" ).arg( kwBgType ).arg( kwSep ).arg( (int)bgMode );
1570 data << QString( "%1%2%3" ).arg( kwFileName ).arg( kwSep ).arg( fileName );
1571 data << QString( "%1%2%3" ).arg( kwTextureMode ).arg( kwSep ).arg( (int)textureMode );
1572 data << QString( "%1%2%3" ).arg( kwShowTexture ).arg( kwSep ).arg( showTexture ? "true" : "false" );
1573 data << QString( "%1%2%3" ).arg( kwFirstColor ).arg( kwSep ).arg( Qtx::colorToString( c1 ) );
1574 data << QString( "%1%2%3" ).arg( kwSecondColor ).arg( kwSep ).arg( Qtx::colorToString( c2 ) );
1575 data << QString( "%1%2%3" ).arg( kwGrType ).arg( kwSep ).arg( gradientType );
1576 data << QString( "%1%2%3" ).arg( kwGrData ).arg( kwSep ).arg( grString );
1578 return data.join( dtSep );
1582 \brief Restore background data from the string representation.
1584 The string should consist of several sub-strings separated by ';' symbol.
1585 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1586 The sub-strings can follow in arbitrary order, some keywords can be missing.
1587 The background data is described by the following values:
1588 - background type (enumerator, see Qtx::BackgroundMode), keyword "bt"
1589 - texture image file name (string), keyword "fn"
1590 - texture mode (enumerator, see Qtx::TextureMode), keyword "tm"
1591 - "show texture" flag (boolean), keyword "ts"
1592 - first color (for simple gradient data) or solid color (for single-colored mode), keyword "c1"
1593 - second color (for simple gradient data), keyword "c2"
1594 - name of gradient type (string), keyword "gt"
1595 - complex gradient data (for custom gradient mode), keyword "gr"
1597 Also, for backward compatibility, background data can be represented by
1598 single color value, see stringToColor().
1600 Backward conversion can be done with backgroundToString() method.
1601 Returns invalid background if conversion could not be done.
1604 Qtx::BackgroundData bgData = Qtx::stringToBackground( str );
1605 if ( bgData.isValid() ) ) doSomething( bgData );
1608 \param theString string representation of the background data
1609 \return resulting background data (invalid if conversion has failed)
1611 \sa backgroundToString()
1614 Qtx::BackgroundData Qtx::stringToBackground( const QString& str )
1616 const QString dtSep = ";";
1617 const QString kwSep = "=";
1618 const QString kwBgType = "bt";
1619 const QString kwFileName = "fn";
1620 const QString kwTextureMode = "tm";
1621 const QString kwShowTexture = "ts";
1622 const QString kwFirstColor = "c1";
1623 const QString kwSecondColor = "c2";
1624 const QString kwGrType = "gt";
1625 const QString kwGrData = "gr";
1627 Qtx::BackgroundData bgData = BackgroundData();
1629 QStringList data = str.split( dtSep, QString::KeepEmptyParts );
1632 if ( data.count() == 1 && !data.contains( kwSep ) && stringToColor( data[0], c ) ) {
1633 // solid color mode, for backward compatibility
1634 bgData.setColor( c );
1637 QMap<QString, QString> dmap;
1639 foreach( QString d, data ) {
1640 QStringList items = d.split( kwSep, QString::KeepEmptyParts );
1641 if ( items.count() > 0 ) {
1642 QString kw = items.takeFirst().trimmed().toLower(); // keyword
1643 QString val = items.join( kwSep ).trimmed(); // if value contains "=" symbol, we have to restore it
1647 QString bgMode = dmap.value( kwBgType, QString() );
1648 QString fileName = dmap.value( kwFileName, QString() );
1649 QString textureMode = dmap.value( kwTextureMode, QString() );
1650 QString showTexture = dmap.value( kwShowTexture, QString() );
1651 QString color1 = dmap.value( kwFirstColor, QString() );
1652 QString color2 = dmap.value( kwSecondColor, QString() );
1653 QString gradientType = dmap.value( kwGrType, QString() );
1654 QString gradient = dmap.value( kwGrData, QString() );
1657 if ( !fileName.isEmpty() || !textureMode.isEmpty() || !showTexture.isEmpty() ) {
1658 Qtx::TextureMode m = (Qtx::TextureMode)( stringToInt( textureMode, Qtx::CenterTexture,
1659 Qtx::CenterTexture, Qtx::StretchTexture ) );
1660 bgData.setTexture( fileName, m );
1661 QStringList boolvars; boolvars << "true" << "yes" << "ok" << "1";
1662 if ( boolvars.contains( showTexture.trimmed().toLower() ) )
1663 bgData.setTextureShown( true );
1667 bool ok = Qtx::stringToColor( color1, c1 );
1669 bgData.setColor( c1 );
1671 // try simple gradient mode
1672 ok = Qtx::stringToColor( color2, c2 );
1673 if ( ok || !gradientType.isEmpty() ) {
1674 int gt = gradientType.toInt( &ok );
1675 bgData.setGradient( ok ? gt : -1, c1, c2 );
1677 // try custom gradient mode
1679 QConicalGradient cg;
1681 ok = Qtx::stringToLinearGradient( gradient, lg );
1683 bgData.setGradient( lg );
1685 ok = Qtx::stringToRadialGradient( gradient, rg );
1687 bgData.setGradient( rg );
1689 ok = Qtx::stringToConicalGradient( gradient, cg );
1691 bgData.setGradient( cg );
1694 // finally set background mode
1695 Qtx::BackgroundMode m = (Qtx::BackgroundMode)( stringToInt( bgMode, Qtx::ColorBackground,
1696 Qtx::NoBackground, Qtx::CustomGradientBackground ) );
1697 bgData.setMode( m );
1704 \class Qtx::Localizer
1705 \brief Localization helper
1707 This helper class can be used to solve the localization problems,
1708 usually related to the textual files reading/writing, namely when
1709 floating point values are read / written with API functions.
1710 The problem relates to such locale specific settings as decimal point
1711 separator, thousands separator, etc.
1713 To use the Localizer class, just create a local variable in the beginning
1714 of the code where you need to read / write data from textual file(s).
1715 The constructor of the class forces setting "C" locale temporariy.
1716 The destructor switches back to the initial locale.
1726 \brief Constructor. Forces "C" locale to be set.
1728 Qtx::Localizer::Localizer()
1730 myCurLocale = setlocale( LC_NUMERIC, 0 );
1731 setlocale( LC_NUMERIC, "C" );
1735 \brief Destructor. Reverts back to the initial locale.
1737 Qtx::Localizer::~Localizer()
1739 setlocale( LC_NUMERIC, myCurLocale.toLatin1().constData() );
1743 \class Qtx::BackgroundData
1744 \brief Stores background data
1746 This class is used to store background data. Depending on the mode,
1747 the background can be specified by:
1748 - image (by assigning the file name to be used as background texture), see setTexture(), setTextureShown()
1749 - single color (by assigning any color), see setColor()
1750 - simple two-color gradient (with the gradient type id and two colors), see setGradient( int, const QColor&, const QColor& )
1751 - complex gradient (by assigning arbitrary gradient data), see setGradient( const QGradient& )
1753 The class stores all the data passed to it, so switching between different modes can be done
1754 just by calling setMode() function.
1756 \note Texture is used with combination of the background mode.
1758 \note Two-color gradient is specified by two colors and integer identifier. The interpretation of
1759 this identifier should be done in the calling code.
1762 Qtx::BackgroundData bg;
1763 bg.setColor( QColor(100, 100, 100) ); // bg is switched to Qtx::ColorBackground mode
1764 bg.setGradient( Qt::Horizontal, Qt::gray, Qt::white ); // bg is switched to Qtx::ColorBackground mode
1765 QLinearGradient grad( 0,0,1,1 );
1766 grad.setColorAt( 0.0, Qt::gray );
1767 grad.setColorAt( 0.5, Qt::white );
1768 grad.setColorAt( 1.0, Qt::green );
1769 grad.setSpread( QGradient::PadSpread );
1770 bg.setGradient( grad ); // bg is switched to Qtx::CustomGradientBackground mode
1771 bg.setMode( Qtx::ColorBackground ); // bg is switched back to Qtx::ColorBackground mode
1772 bg.setTexture( "/data/images/background.png" ); // specify texture (in the centered mode by default)
1773 bg.setTextureShown( true ); // draw texture on the solid color background
1778 \brief Default constructor.
1779 Creates invalid background data.
1781 Qtx::BackgroundData::BackgroundData()
1782 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1784 setMode( Qtx::NoBackground );
1789 Creates background data initialized with the specified color
1792 Qtx::BackgroundData::BackgroundData( const QColor& c )
1793 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1800 Creates background data initialized with the specified two-color gradient
1801 \param type gradient type identifier
1802 \param c1 first gradient color
1803 \param c2 second gradient color
1804 \note the interpretation of the gradient identifier should be done in the calling code
1806 Qtx::BackgroundData::BackgroundData( int type, const QColor& c1, const QColor& c2 )
1807 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1809 setGradient( type, c1, c2 );
1814 Creates background data initialized with the arbirtary gradient data
1815 \param grad gradient data
1817 Qtx::BackgroundData::BackgroundData( const QGradient& grad )
1818 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1820 setGradient( grad );
1826 Qtx::BackgroundData::~BackgroundData()
1831 \brief Compares two background data objects
1833 bool Qtx::BackgroundData::operator==( const Qtx::BackgroundData& other ) const
1836 ( myMode == other.myMode ) &&
1837 ( myTextureMode == other.myTextureMode ) &&
1838 ( myFileName == other.myFileName ) &&
1839 ( myColors == other.myColors ) &&
1840 ( myGradientType == other.myGradientType ) &&
1841 ( myGradient == other.myGradient ) &&
1842 ( myTextureShown == other.myTextureShown );
1846 \brief Returns \c false if background data is not set (invalid)
1847 \return \c true if background data is valid or \c false otherwise
1850 bool Qtx::BackgroundData::isValid() const
1852 return myMode != Qtx::NoBackground;
1856 \brief Get background mode
1857 \return current background mode
1860 Qtx::BackgroundMode Qtx::BackgroundData::mode() const
1866 \brief Set background mode
1867 \param m background mode being set
1870 void Qtx::BackgroundData::setMode( const Qtx::BackgroundMode m )
1876 \brief Get file name used as a texture image
1877 \return path to the texture image file
1878 \sa setTexture(), setTextureShown()
1880 Qtx::TextureMode Qtx::BackgroundData::texture( QString& fileName ) const
1882 fileName = myFileName;
1883 return myTextureMode;
1887 \brief Set file name to be used as a texture image.
1889 \note To show texture image on the background it is necessary to call additionally
1890 setTextureShown() method.
1892 \param fileName path to the texture image file name
1893 \param m texture mode (Qtx::CenterTexture by default)
1894 \sa texture(), setTextureShown()
1896 void Qtx::BackgroundData::setTexture( const QString& fileName, const Qtx::TextureMode m )
1898 myFileName = fileName;
1903 \brief Check if "show texture" flag is switched on
1904 \return \c true if "show texture" flag is set or \c false otherwise
1905 \sa setTextureShown(), texture()
1907 bool Qtx::BackgroundData::isTextureShown() const
1909 return myTextureShown;
1913 \brief Specify if texture should be shown on the background or no.
1914 \param on \c true if texture should be shown or \c false otherwise
1915 \sa isTextureShown(), texture()
1917 void Qtx::BackgroundData::setTextureShown( bool on )
1919 myTextureShown = on;
1923 \brief Get background color. Returns null QColor if color is not set
1924 \return solid background color
1925 \sa setColor(), mode()
1927 QColor Qtx::BackgroundData::color() const
1929 return myColors.count() > 0 ? myColors[0] : QColor();
1933 \brief Set background color and switch to the Qtx::ColorBackground mode
1937 void Qtx::BackgroundData::setColor( const QColor& c )
1941 setMode( Qtx::ColorBackground );
1945 \brief Get simple gradient data.
1946 Returns -1 and null QColor for \a c1 and \a c2 if gradient data is not set
1947 \param c1 first gradient color is returned via this parameter
1948 \param c2 second gradient color is returned via this parameter
1949 \return current two-colored gradient mode type identifier
1950 \note the interpretation of the gradient identifier should be done in the calling code
1951 \sa setGradient(int, const QColor&, const QColor&), mode()
1953 int Qtx::BackgroundData::gradient( QColor& c1, QColor& c2 ) const
1955 c1 = myColors.count() > 0 ? myColors[0] : QColor();
1956 c2 = myColors.count() > 1 ? myColors[1] : ( myColors.count() > 0 ? myColors[0] : QColor() );
1957 return myGradientType;
1961 \brief Set simple background gradient data and switch to the Qtx::SimpleGradientBackground mode
1962 \param type two-colored gradient mode type identifier
1963 \param c1 first gradient color is returned via this parameter
1964 \param c2 second gradient color is returned via this parameter
1965 \note the interpretation of the gradient identifier should be done in the calling code
1966 \sa gradient(QColor&, QColor&), mode()
1968 void Qtx::BackgroundData::setGradient( int type, const QColor& c1, const QColor& c2 )
1971 myColors << c1 << c2;
1972 myGradientType = type;
1973 setMode( Qtx::SimpleGradientBackground );
1977 \brief Get complex gradient data.
1978 Returns QGradient of QGradient::NoGradient if gradient data is not set
1979 \note This function does not transform simple gradient data set with
1980 setGradient( const QString&, const QColor&, const QColor& ) to QGradient class
1981 \return gradient data
1982 \sa setGradient(const QGradient&), mode()
1984 const QGradient* Qtx::BackgroundData::gradient() const
1990 \brief Set complex background gradient data and switch to the Qtx::CustomGradientBackground mode
1991 \param grad gradient data (QLinearGradient, QRadialGradient or QConicalGradient)
1992 \sa gradient(), mode()
1994 void Qtx::BackgroundData::setGradient( const QGradient& grad )
1997 setMode( Qtx::CustomGradientBackground );
2001 \brief Convert string representation of version identifier to the numerical value.
2002 Resulting value can be used for comparison of different versions (lower, higher, equal).
2004 String representation of the version consists of zero or more components:
2006 [major[.minor[.release[patchid]]]]
2009 - major is version major number
2010 - minor is version minor number
2011 - release is version release number
2012 - patchid is a version dev identifier which is one of the following
2013 * 1 letter optionally followed by 1 or 2 digits, e.g. "a" for "alpha", "b1" for "beta 1"
2014 * "rc" optionally followed by 1 or 2 digits, e.g. "rc1" for "release candidate 1"
2015 * "dev" for development version (note: 7.4.0dev > 7.4.0, 7.4.0dev < 7.4.1, 7.4.0dev < 7.4.0a1)
2017 If version string does not include any component or has invalid format, the function returns 0.
2021 1.2.3a - version 1.2.3 alpha
2022 3.3.3b1 - version 3.3.3 beta 1
2023 7.4.0rc1 - version 7.4.0 release candidate 1
2024 7.4.0dev - dev version, i.e. future version 7.4.1 (or 7.5.0)
2026 \param version string representation of version
2027 \return numerical identifier of the version
2029 long Qtx::versionToId( const QString& version )
2033 QRegExp vers_exp( "^([0-9]+)([A-Z]|RC|DEV)?([0-9]{0,2})$", Qt::CaseInsensitive );
2035 QStringList vers = version.split( ".", QString::SkipEmptyParts );
2036 int major=0, minor=0;
2037 int release = 0, dev1 = 0, dev2 = 0;
2038 if ( vers.count() > 0 ) major = vers[0].toInt();
2039 if ( vers.count() > 1 ) minor = vers[1].toInt();
2040 if ( vers.count() > 2 ) {
2041 if ( vers_exp.indexIn( vers[2] ) != -1 ) {
2042 release = vers_exp.cap( 1 ).toInt();
2043 QString tag = vers_exp.cap( 2 ).toLower();
2044 if ( !tag.isEmpty() ) {
2045 // patchid is subtracted from version number
2046 // a = 55 --> -(55 * 100) + patch number --> 4500..4599, e.g. 7.4.1a1 -> 704004501
2047 // b = 54 --> -(54 * 100) + patch number --> 4600..4699, e.g. 7.4.1b1 -> 704004601
2048 // c = 53 --> -(53 * 100) + patch number --> 4700..4799, e.g. 7.4.1c1 -> 704004701
2050 // z = 30 --> -( 1 * 100) + patch number --> 7000..7099, e.g. 7.4.1z1 -> 704007001
2051 // rc = 1 --> -( 1 * 100) + patch number --> 9900..9999, e.g. 7.4.1rc1 -> 704009901
2052 // dev = -1 --> +( 1 * 100) + patch number --> 0100..0199, e.g. 7.4.1dev -> 704010100
2054 // i.e. "a" < "b" < ... < "z" < "rc" < [stable] < "dev"
2057 else if ( tag == "dev" )
2060 dev1 = (int)( QChar('z').toLatin1() ) - (int)( tag[ 0 ].toLatin1() ) + 30;
2062 if ( !vers_exp.cap( 3 ).isEmpty() )
2063 dev2 = vers_exp.cap( 3 ).toInt();
2067 int dev = dev1*100-dev2;
2070 id*=100; id+=release;
2078 \brief Get Qt installation directory
2080 The function tries to detect qt installation directory by analyzing the system variables in the following order:
2086 Optional parameter \a context allows obtaining subdirectory in the Qt installation directory.
2088 \param context optional sub-directory
2089 \return path to the Qt installation directory (or its sub-folder, if \a context is specified)
2092 QString Qtx::qtDir( const QString& context )
2094 const char* vars[] = { "QT5_ROOT_DIR", "QT4_ROOT_DIR", "QT_ROOT_DIR", "QTDIR" };
2096 for (uint i = 0; i < sizeof(vars)/sizeof(vars[0]) && qtPath.isEmpty(); i++ )
2097 qtPath = qgetenv( vars[i] );
2098 if ( !qtPath.isEmpty() && !context.isEmpty() )
2099 qtPath = QDir( qtPath ).absoluteFilePath( context );
2104 Creates font from string description
2106 QFont Qtx::stringToFont( const QString& fontDescription )
2109 if ( fontDescription.trimmed().isEmpty() || !font.fromString( fontDescription ) )
2110 font = QFont( "Courier", 11 );
2114 #if !defined WIN32 && !defined __APPLE__
2116 #include <X11/Xlib.h>
2120 \brief Open the default X display and returns pointer to it.
2121 This method is available on Linux only.
2122 \return Pointer to X display.
2125 void* Qtx::getDisplay()
2127 static Display* pDisplay = NULL;
2129 pDisplay = XOpenDisplay( NULL );
2134 \brief Returns pointer to X visual suitable for 3D rendering.
2135 This method is available on Linux only.
2136 \return Pointer to X visual.
2139 Qt::HANDLE Qtx::getVisual()
2141 Qt::HANDLE res = (Qt::HANDLE)NULL;
2143 Display* pDisplay = (Display*)getDisplay();
2150 // Make sure OpenGL's GLX extension supported
2151 if( !glXQueryExtension( pDisplay, &errorBase, &eventBase ) ){
2152 qCritical( "Could not find glx extension" );
2156 // Find an appropriate visual
2158 int doubleBufferVisual[] = {
2159 GLX_RGBA, // Needs to support OpenGL
2160 GLX_DEPTH_SIZE, 16, // Needs to support a 16 bit depth buffer
2161 GLX_DOUBLEBUFFER, // Needs to support double-buffering
2162 GLX_STEREO, // Needs to support stereo rendering
2163 GLX_STENCIL_SIZE, 1,
2167 // Try for the double-bufferd visual first
2168 XVisualInfo *visualInfo = NULL;
2169 visualInfo = glXChooseVisual( pDisplay, DefaultScreen(pDisplay), doubleBufferVisual );
2171 if( visualInfo == NULL ){
2172 qCritical( "Could not find matching glx visual" );
2176 qDebug() << "Picked visual 0x" << hex << XVisualIDFromVisual( visualInfo->visual );
2177 res = (Qt::HANDLE)( visualInfo->visual );
2185 \class Qtx::CmdLineArgs
2186 \brief Get access to the command line arguments in the C-like manner.
2188 This class translates command line arguments stored in QApplication in form of QStrlingList
2189 to the char* array, in the same way as they specified to main() function.
2191 Constructor of class allocates required memory to store arguments; destructor deallocates it,
2192 This allows using this class as a local variable:
2195 Qtx::CmdLineArgs args;
2196 some_function(args.argc(), args.argv()); // function that has main()-like syntax.
2201 \brief Default constructor.
2203 Qtx::CmdLineArgs::CmdLineArgs()
2205 QStringList args = QCoreApplication::arguments();
2206 myArgc = args.size();
2207 myArgv = new char*[myArgc];
2208 for ( int i = 0; i < myArgc; i++ ) {
2209 QByteArray ba = args[i].toUtf8();
2210 myArgv[i] = qstrdup(ba.constData());
2215 \brief Destructor. Deallocates the array with command line arguments
2217 Qtx::CmdLineArgs::~CmdLineArgs()
2219 for ( int i = 0; i < myArgc; i++ )
2225 \brief Get number of command line arguments
2226 \return number of arguments
2228 int Qtx::CmdLineArgs::argc() const
2234 \brief Get command line arguments
2235 \return command line arguments
2237 char** Qtx::CmdLineArgs::argv() const