1 // Copyright (C) 2007-2015 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() )
280 QList<QAction*> toRemove;
281 for ( int i = 1; i < items.count(); i++ )
283 if ( items[i]->isSeparator() && items[i - 1]->isSeparator() )
284 toRemove.append( items[i] );
286 if ( recursive && items[i]->menu() )
287 simplifySeparators( items[i]->menu(), recursive );
290 for ( QList<QAction*>::iterator it = toRemove.begin(); it != toRemove.end(); ++it )
291 wid->removeAction( *it );
293 items = wid->actions();
294 if ( !items.isEmpty() && items[0]->isSeparator() )
295 wid->removeAction( items[0] );
297 items = wid->actions();
298 if ( !items.isEmpty() && items[items.count() - 1]->isSeparator() )
299 wid->removeAction( items[items.count() - 1] );
303 \brief Return \c true if specified \a parent is a parent object
304 of given \a child (in terms of QObject).
306 This function works recursively. It means that \a true is also
307 returned if \a parent is a grand-father, grand-grand-father, etc
308 of \a child. If the same object is given as both \a parent and
309 \a child, \c true is also returned.
311 \param child child object
312 \param parent parent object
313 \return \c true if the \a parent is a parent of \a child
315 bool Qtx::isParent( QObject* child, QObject* parent )
317 if ( !child || !parent )
321 QObject* obj = child;
322 while ( !res && obj )
331 \brief Find the parent object of class specified by \a className (in terms of QObject).
333 \param obj current object
334 \param className class name of the parent
335 \return parent object or null pointer if the parent not found
337 QObject* Qtx::findParent( QObject* obj, const char* className )
342 if ( !className || !strlen( className ) )
343 return obj->parent();
346 QObject* p = obj->parent();
349 if ( p->inherits( className ) )
358 \brief Return directory part of the file path.
360 If the file path does not include directory part (the file is in the
361 current directory), null string is returned.
363 \param path file path
364 \param abs if true (default) \a path parameter is treated as absolute file path
365 \return directory part of the file path
367 QString Qtx::dir( const QString& path, const bool abs )
369 QDir aDir = QFileInfo( path ).dir();
370 QString dirPath = abs ? aDir.absolutePath() : aDir.path();
371 if ( dirPath == QString( "." ) )
377 \brief Return file name part of the file path.
379 \param path file path
380 \param withExt if true (default) complete file name (with all
381 extension except the last) is returned, otherwise only base name
383 \return file name part of the file path
385 QString Qtx::file( const QString& path, bool withExt )
387 QString fPath = path;
388 while ( !fPath.isEmpty() && ( fPath[fPath.length() - 1] == '\\' || fPath[fPath.length() - 1] == '/' ) )
389 fPath.remove( fPath.length() - 1, 1 );
392 return QFileInfo( fPath ).fileName();
394 return QFileInfo( fPath ).completeBaseName();
398 \brief Return extension part of the file path.
400 \param path file path
401 \param full if true complete extension (all extensions, dot separated)
402 is returned, otherwise (default) only last extension is returned
403 \return extension part of the file path
405 QString Qtx::extension( const QString& path, const bool full )
407 return full ? QFileInfo( path ).completeSuffix() : QFileInfo( path ).suffix();
411 \brief Convert the given parameter to the platform-specific library name.
413 The function appends platform-specific prefix (lib) and suffix (.dll/.so)
414 to the library file name.
415 For example, if \a str = "mylib", "libmylib.so" is returned for Linux and
416 mylib.dll for Windows.
418 \param str short library name
419 \return full library name
421 QString Qtx::library( const QString& str )
423 QString path = dir( str, false );
424 QString name = file( str, false );
425 QString ext = extension( str );
428 if ( !name.startsWith( "lib" ) )
429 name = QString( "lib" ) + name;
433 QString libExt( "dll" );
435 QString libExt( "so" );
438 if ( ext.toLower() != QString( "so" ) && ext.toLower() != QString( "dll" ) )
440 if ( !name.isEmpty() && !ext.isEmpty() )
441 name += QString( "." );
447 QString fileName = addSlash( path ) + name + QString( "." ) + ext;
453 \brief Get the temporary directory name.
454 \return temporary directory (platform specific)
456 QString Qtx::tmpDir()
458 const char* tmpdir = ::getenv( "TEMP" );
460 tmpdir = ::getenv ( "TMP" );
469 return QString( tmpdir );
473 \brief Create directory recursively including all intermediate sub directories.
474 \return \c true if the directory is successfully created and \c false otherwise
476 bool Qtx::mkDir( const QString& dirPath )
478 return QDir().mkpath( dirPath );
482 \brief Remove directory recursively including all subdirectories and files.
483 \return \c true if the directory is successfully removed and \c false otherwise
485 bool Qtx::rmDir( const QString& thePath )
487 QFileInfo fi( thePath );
493 stat = QFile::remove( thePath );
494 else if ( fi.isDir() )
496 QDir aDir( thePath );
497 QFileInfoList anEntries = aDir.entryInfoList();
498 for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
501 if ( inf.fileName() == "." || inf.fileName() == ".." )
503 stat = stat && rmDir( inf.absoluteFilePath() );
505 stat = stat && aDir.rmdir( thePath );
511 \brief Add a slash (platform-specific) to the end of \a path
512 if it is not already there.
513 \param path directory path
514 \return modified path (with slash added to the end)
516 QString Qtx::addSlash( const QString& path )
519 if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
520 res.at( res.length() - 1 ) != QChar( '\\' ) )
521 res += QDir::separator();
526 \brief Convert text file from DOS format to UNIX.
528 The function replaces "LF/CR" symbols sequence by "LF" symbol.
530 \param absName file name
531 \return \c true if the file is converted successfully and \c false in
534 bool Qtx::dos2unix( const QString& absName )
536 FILE* src = ::fopen( absName.toLatin1(), "rb" );
540 /* we'll use temporary file */
541 char temp[512] = { '\0' };
542 QString dir = Qtx::dir( absName );
543 FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toLatin1(), "__x" ) ), "wb" );
547 /* temp -> result of conversion */
548 const char CR = 0x0d;
549 const char LF = 0x0a;
550 bool waitingLF = false;
555 char inbuf[512], outbuf[512];
558 int nbread = ::fread( inbuf, 1, sizeof( inbuf ), src );
559 for ( int incnt = 0; incnt < nbread; incnt++ )
564 if ( inbuf[incnt] == LF )
565 outbuf[outcnt++] = LF;
567 outbuf[outcnt++] = CR;
569 else if ( inbuf[incnt] == CR )
572 outbuf[outcnt++] = inbuf[incnt];
575 /* check last sym in buffer */
576 waitingLF = ( inbuf[nbread - 1] == CR );
578 /* write converted buffer to temp file */
579 int nbwri = ::fwrite( outbuf, 1, outcnt, tgt );
580 if ( nbwri != outcnt )
584 QFile::remove( QString( temp ) );
587 if ( nbread != sizeof( inbuf ) )
588 break; /* converted ok */
593 /* rename temp -> src */
594 if ( !QFile::remove( absName ) )
597 return QDir().rename( QString( temp ), absName );
601 \brief Create path completer which can be used in the widgets
602 to provide auto completions.
604 Create an instance of QCompleter class and returns the pointer on it.
605 The calling function is responsible to the desstroying of the created
608 The QCompleter class provides completions based on a item model and can be
609 used in such as QLineEdit and QComboBox.
610 When the user starts typing a word, QCompleter suggests possible ways of
611 completing the word, based on a word list.
613 \param type path type (Qtx::PathType)
614 \param filter file/directory filters (list of wildcards, separated by ";;")
615 \return a pointer to the created completer
617 QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
620 QStringList filterList = filter.split( ";;" );
621 for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
623 QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
625 while ( ( index = rx.indexIn( *it, index ) ) != -1 )
627 extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
628 index += rx.matchedLength();
632 QDir::Filters filters = 0;
637 filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
640 filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
644 QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
645 QCompleter* cmp = new QCompleter( dm, 0 );
646 dm->setParent( cmp );
652 \brief Parse given string to retrieve environment variable.
654 Looks through the string for the patterns: ${name} or $(name) or %name%.
655 If string contains variable satisfying any pattern, the variable name
656 is returned, start index of the variable is returned in the \a start parameter,
657 and length of the variable is returned in the \a len parameter.
659 \param str string being processed
660 \param start if variable is found, this parameter contains its starting
661 position in the \a str
662 \param len if variable is found, this parameter contains its length
663 \return first found variable or null QString if there is no ones
665 QString Qtx::findEnvVar( const QString& str, int& start, int& len )
670 QRegExp rx( "(^\\$\\{|[^\\$]\\$\\{)([a-zA-Z]+[a-zA-Z0-9_]*)(\\})|(^\\$\\(|[^\\$]\\$\\()([a-zA-Z]+[a-zA-Z0-9_]*)(\\))|(^\\$|[^\\$]\\$)([a-zA-Z]+[a-zA-Z0-9_]*)|(^%|[^%]%)([a-zA-Z]+[a-zA-Z0-9_]*)(%[^%]|%$)" );
672 int pos = rx.indexIn( str, start );
676 while ( i <= rx.numCaptures() && varName.isEmpty() )
678 QString capStr = rx.cap( i );
679 if ( !capStr.contains( "%" ) && !capStr.contains( "$" ) )
684 if ( !varName.isEmpty() )
687 start = rx.pos( capIdx );
688 int end = start + varName.length();
689 if ( capIdx > 1 && rx.cap( capIdx - 1 ).contains( QRegExp( "\\$|%" ) ) )
690 start = rx.pos( capIdx - 1 ) + rx.cap( capIdx - 1 ).indexOf( QRegExp( "\\$|%" ) );
691 if ( capIdx < rx.numCaptures() && !rx.cap( capIdx - 1 ).isEmpty() )
700 \brief Substitute environment variables by their values.
702 Environment variable is substituted by its value.
704 \param str string to be processed
705 \return processed string (with all substitutions made)
707 QString Qtx::makeEnvVarSubst( const QString& str, const SubstMode mode )
712 QMap<QString, int> ignoreMap;
714 int start( 0 ), len( 0 );
717 QString envName = findEnvVar( res, start, len );
718 if ( envName.isNull() )
722 if ( ::getenv( envName.toLatin1() ) || mode == Always )
723 newStr = QString( ::getenv( envName.toLatin1() ) );
725 if ( newStr.isNull() )
727 if ( ignoreMap.contains( envName ) )
732 ignoreMap.insert( envName, 0 );
734 res.replace( start, len, newStr );
737 res.replace( "$$", "$" );
738 res.replace( "%%", "%" );
745 \brief Pack the specified color into integer RGB set.
746 \param c unpacked color
749 int Qtx::rgbSet( const QColor& c )
751 return rgbSet( c.red(), c.green(), c.blue() );
755 \brief Pack the specified RGB color components into integer RGB set.
756 \param r red component
757 \param g green component
758 \param b blue component
761 int Qtx::rgbSet( const int r, const int g, const int b )
763 return ( ( ( 0xff & r ) << 16 ) + ( ( 0xff & g ) << 8 ) + ( 0xff & b ) );
767 \brief Unpack the specified integer RGB set to the color.
768 \param rgb packed color
769 \return unpacked color (QColor)
771 QColor Qtx::rgbSet( const int rgb )
774 rgbSet( rgb, r, g, b );
775 return QColor( r, g, b );
779 \brief Unpack the specified integer RGB set to the three RGB components.
780 \param rgb packed color
781 \param r returned unpacked red component
782 \param g returned unpacked green component
783 \param b returned unpacked blue component
785 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
787 r = ( rgb >> 16 ) & 0xff;
788 g = ( rgb >> 8 ) & 0xff;
793 \brief Return the color specified by the index between min (blue) and max (red).
794 \param index color index
795 \param min required minimum hue value
796 \param max required maximum hue value
797 \return resulting color
799 QColor Qtx::scaleColor( const int index, const int min, const int max )
801 static const int HUE[10] = {230, 210, 195, 180, 160, 80, 60, 50, 30, 0};
807 double aPosition = 9.0 * ( index - min ) / ( max - min );
808 if ( aPosition > 0.0 )
810 if ( aPosition >= 9.0 )
814 int idx = (int)aPosition;
815 hue = HUE[idx] + int( ( aPosition - idx ) * ( HUE[idx + 1] - HUE[idx] ) );
820 return QColor::fromHsv( hue, 255, 255 );
824 \brief Generate required number of colors aligned from blue to red.
825 \param num required number of colors
826 \param lst returned set of colors
828 void Qtx::scaleColors( const int num, QColorList& lst )
831 for ( int i = 0; i < num; i++ )
832 lst.append( scaleColor( i, 0, num - 1 ) );
836 \brief Scale the pixmap to the required size.
838 If \a h is 0 (default) the value of \a w is used instead (to create
841 \param icon pixmap to be resized
842 \param w required pixmap width
843 \param h required pixmap height
844 \return scaled pixmap
846 QPixmap Qtx::scaleIcon( const QPixmap& icon, const unsigned w, const unsigned h )
849 int aw = w, ah = h <= 0 ? w : h;
850 if ( icon.isNull() || aw <= 0 || ah <= 0 || ( aw == icon.width() && ah == icon.height() ) )
853 p = icon.fromImage( icon.toImage().scaled( aw, ah, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
858 \brief Convert given image to the grayscale format.
859 \param img initial image
860 \return converted to the grayscale image
862 QImage Qtx::grayscale( const QImage& img )
866 int colNum = res.numColors();
869 for ( int i = 0; i < colNum; i++ )
870 res.setColor( i, qGray( res.color( i ) ) );
874 for ( int y = 0; y < res.height(); y++ )
876 for ( int x = 0; x < res.width(); x++ )
878 QRgb pix = res.pixel( x, y );
879 res.setPixel( x, y, qRgba( qGray( pix ), qGray( pix ), qGray( pix ), qAlpha( pix ) ) );
888 \brief Convert given pixmap to the grayscale format.
889 \param pix initial pixmap
890 \return converted to the grayscale pixmap
892 QPixmap Qtx::grayscale( const QPixmap& pix )
895 res.fromImage( grayscale( pix.toImage() ) );
900 \brief Create transparent image.
901 \param w required image width
902 \param h required image height
903 \param d required image depth
904 \return generated image
906 QImage Qtx::transparentImage( const int w, const int h, const int d )
912 fmt = QImage::Format_Mono;
915 fmt = QImage::Format_Indexed8;
921 fmt = QImage::Format_ARGB32;
925 QImage img( w, h, fmt );
928 // img.setAlphaBuffer( true );
929 for ( int i = 0; i < img.height(); i++ )
930 for ( int j = 0; j < img.width(); j++ )
931 img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) );
937 \brief Create transparent pixmap.
938 \param w required image width
939 \param h required pixmap height
940 \param d required pixmap depth
941 \return generated pixmap
943 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
946 QImage img = transparentImage( w, h, d );
948 pix.fromImage( img );
953 \brief Create composite pixmap.
955 Pixmap \a pix is drawn over pixmap \a dest with coordinates
956 specified relatively to the upper left corner of \a dest.
957 If \a dest is not given, the new empty pixmap with appropriate size created instead.
959 \param pix source pixmap
960 \param x horizontal shift
961 \param y vertical shift
962 \param dest background pixmap
963 \return resulting pixmap
965 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
970 int width = qMax( pix.width() + x, dest.width() );
971 int height = qMax( pix.height() + y, dest.height() );
973 QPixmap res( width, height );
974 QImage img = transparentImage( width, height, 32 );
978 p.fillRect( 0, 0, width, height, QBrush( Qt::white ) );
980 if ( !dest.isNull() )
982 p.drawPixmap( 0, 0, dest );
983 QImage temp = dest.toImage();
984 for ( int i = 0; i < temp.width() && i < img.width(); i++ )
986 for ( int j = 0; j < temp.height() && j < img.height(); j++ )
988 if ( temp.hasAlphaChannel() )
989 img.setPixel( i, j, temp.pixel( i, j ) );
992 QRgb p = temp.pixel( i, j );
993 img.setPixel( i, j, qRgba( qRed( p ), qGreen( p ), qBlue( p ), 255 ) );
999 p.drawPixmap( x, y, pix );
1000 QImage temp = pix.toImage();
1001 for ( int c = x; c < temp.width() + x && c < img.width(); c++ )
1003 for ( int r = y; r < temp.height() + y && r < img.height(); r++ )
1005 if ( qAlpha( temp.pixel( c - x, r - y ) ) > 0 )
1006 img.setPixel( c, r, temp.pixel( c - x, r - y ) );
1012 for ( int ai = 0; ai < img.width(); ai++ )
1014 for ( int aj = 0; aj < img.height(); aj++ )
1016 if ( qAlpha( img.pixel( ai, aj ) ) < 1 )
1017 img.setPixel( ai, aj, qRgba( 255, 255, 255, 255 ) );
1019 img.setPixel( ai, aj, qRgba( 0, 0, 0, 0 ) );
1023 QBitmap bmp( width, height );
1024 bmp.fromImage( img, Qt::ColorMode_Mask | Qt::ThresholdDither );
1031 \brief Convert color to the string representation.
1033 The resulting string is in the one of two possible formats
1034 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1035 and alpha components of the color):
1036 - if color has alpha channel : "#RR,#GG,#BB,#AA"
1037 - if color does not have alpha channel : "#RRGGBB"
1039 If color is invalid, null string is returned.
1041 Backward conversion can be done with stringToColor() method.
1043 \param color color to be converted
1044 \return string representation of the color
1048 QString Qtx::colorToString( const QColor& color )
1051 if ( color.isValid() )
1053 if ( color.alpha() != 255 )
1056 vals << QString( "#%1" ).arg( color.red(), 0, 16 );
1057 vals << QString( "#%1" ).arg( color.green(), 0, 16 );
1058 vals << QString( "#%1" ).arg( color.blue(), 0, 16 );
1059 vals << QString( "#%1" ).arg( color.alpha(), 0, 16 );
1060 str = vals.join( "," );
1071 \brief Create color from the string representation.
1073 The parameter \a str must be in the one of following formats
1074 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
1075 and alpha components of the color):
1076 - "#RR,#GG,#BB[,#AA]" or "#RR #GG #BB[ #AA]" (\c RR, \c GG, \c BB
1077 and optional \c AA values represent red, green, blue and alpha
1078 components of the color in hexadecimal form)
1079 - "RR,GG,BB[,AA]" or "RR GG BB[ AA]" (\c RR, \c GG, \c BB
1080 and optional \c AA values represent red, green, blue and alpha
1081 components of the color in decimal form)
1082 - "#RRGGBB" - (\c RR, \c GG and \c BB values represent red, green and blue
1083 components of the color in hexadecimal form)
1084 - an integer value representing packed color components (see rgbSet())
1085 - a name from the list of colors defined in the list of SVG color keyword names
1086 provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
1088 Backward conversion can be done with colorToString() method.
1090 \param str string representation of the color
1091 \param color resulting color value
1092 \return \c true if the conversion is successful and \c false otherwise
1094 \sa colorToString(), rgbSet()
1096 bool Qtx::stringToColor( const QString& str, QColor& color )
1099 QStringList vals = str.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
1102 for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
1105 if ( (*it).startsWith( "#" ) )
1106 num = (*it).mid( 1 ).toInt( &res, 16 );
1108 num = (*it).toInt( &res, 10 );
1113 res = res && nums.count() >= 3;
1115 color.setRgb( nums[0], nums[1], nums[2] );
1119 int pack = str.toInt( &res );
1121 color = Qtx::rgbSet( pack );
1126 color = QColor( str );
1127 res = color.isValid();
1134 \brief Convert bi-color value to the string representation.
1136 Bi-color value is specified as main color and integer delta
1137 value that is used to calculate secondary color by changing
1138 paremeters of the main color ("saturation" and "value"
1139 components in HSV notation).
1141 The resulting string consists of two sub-strings separated by
1142 '|' symbol. The first part represents main color
1143 (see colorToString() for more details), the second part is a
1146 Backward conversion can be done with stringToBiColor() method.
1148 \param color color to be converted
1149 \param delta delta value
1150 \return string representation of the bi-color value
1152 \sa stringToBiColor(), stringToColor()
1154 QString Qtx::biColorToString( const QColor& color, const int delta )
1156 return QString("%1|%2").arg( Qtx::colorToString( color ) ).arg( delta );
1160 \brief Restore bi-color value from the string representation.
1162 Bi-color value is specified as main color and integer delta
1163 value that is used to calculate secondary color by changing
1164 paremeters of the main color ("saturation" and "value"
1165 components in HSV notation).
1167 The parameter \a str should consist of two sub-strings separated
1168 by '|' symbol. The first part represents main color
1169 (see stringToColor() for more details), the second part is a
1172 Backward conversion can be done with biColorToString() method.
1174 \param str string representation of the bi-color value
1175 \param color resulting color value
1176 \param delta resulting delta value
1177 \return \c true if the conversion is successful and \c false otherwise
1179 \sa biColorToString(), stringToColor(), rgbSet()
1181 bool Qtx::stringToBiColor( const QString& str, QColor& color, int& delta )
1183 QStringList data = str.split( "|", QString::KeepEmptyParts );
1186 bool ok = data.count() > 0 && Qtx::stringToColor( data[0], c );
1188 if ( data.count() > 1 ) d = data[1].toInt( &dok );
1190 color = ok ? c : QColor();
1196 \brief Compute secondary color value from specified main color
1199 Secondary color is calculated by changing paremeters of the main
1200 color ("saturation" and "value" components in HSV notation) using
1203 If main color is invalid, result of the function is also invalid color.
1205 \param color source main color
1206 \param delta delta value
1207 \return resulting secondary color
1209 \sa biColorToString(), stringToBiColor()
1211 QColor Qtx::mainColorToSecondary( const QColor& color, int delta )
1214 if ( cs.isValid() ) {
1215 int val = qMin( 255, qMax( cs.value() + delta, 0 ) );
1216 int sat = qMin( 255, qMax( cs.saturation() + delta-(val-cs.value()), 0 ) );
1217 #ifdef BICOLOR_CHANGE_HUE
1218 const int BICOLOR_HUE_MAXDELTA = 40;
1219 int dh = delta-(val-cs.value())-(sat-cs.saturation());
1220 dh = qMin( BICOLOR_HUE_MAXDELTA, qAbs( dh ) ) * ( dh > 0 ? 1 : -1 );
1221 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-(sat-cs.saturation()), 0 ) );
1222 //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-ds, 0 ) );
1223 int hue = cs.hue() + dh;
1224 if ( hue < 0 ) hue = 360 - hue;
1228 cs.setHsv( hue, sat, val );
1234 \brief Dump linear gradient to the string description.
1235 \param gradient linear gradient to be converted
1236 \return string representation of the linear gradient
1237 \sa stringToLinearGradient()
1239 QString Qtx::gradientToString( const QLinearGradient& gradient )
1243 data << QString::number( gradient.start().x() );
1244 data << QString::number( gradient.start().y() );
1245 data << QString::number( gradient.finalStop().x() );
1246 data << QString::number( gradient.finalStop().y() );
1247 switch( gradient.spread() )
1249 case QGradient::PadSpread:
1252 case QGradient::RepeatSpread:
1255 case QGradient::ReflectSpread:
1261 QGradientStops stops = gradient.stops();
1263 foreach ( stop, stops )
1265 data << QString::number( stop.first );
1266 data << colorToString( stop.second );
1268 return data.join( "|" );
1272 \brief Dump radial gradient to the string description.
1273 \param gradient radial gradient to be converted
1274 \return string representation of the radial gradient
1275 \sa stringToRadialGradient()
1277 QString Qtx::gradientToString( const QRadialGradient& gradient )
1281 data << QString::number( gradient.center().x() );
1282 data << QString::number( gradient.center().y() );
1283 data << QString::number( gradient.focalPoint().x() );
1284 data << QString::number( gradient.focalPoint().y() );
1285 data << QString::number( gradient.radius() );
1286 switch( gradient.spread() )
1288 case QGradient::PadSpread:
1291 case QGradient::RepeatSpread:
1294 case QGradient::ReflectSpread:
1300 QGradientStops stops = gradient.stops();
1302 foreach ( stop, stops )
1304 data << QString::number( stop.first );
1305 data << colorToString( stop.second );
1307 return data.join( "|" );
1311 \brief Dump conical gradient to the string description.
1312 \param gradient conical gradient to be converted
1313 \return string representation of the conical gradient
1314 \sa stringToConicalGradient()
1316 QString Qtx::gradientToString( const QConicalGradient& gradient )
1320 data << QString::number( gradient.center().x() );
1321 data << QString::number( gradient.center().y() );
1322 data << QString::number( gradient.angle() );
1323 switch( gradient.spread() )
1325 case QGradient::PadSpread:
1328 case QGradient::RepeatSpread:
1331 case QGradient::ReflectSpread:
1337 QGradientStops stops = gradient.stops();
1339 foreach ( stop, stops )
1341 data << QString::number( stop.first );
1342 data << colorToString( stop.second );
1344 return data.join( "|" );
1348 \brief Create linear gradient from its string representation.
1349 \param str string representation of the linear gradient
1350 \param gradient resulting linear gradient object
1351 \return \c true if the conversion is successful and \c false otherwise
1352 \sa gradientToString()
1354 bool Qtx::stringToLinearGradient( const QString& str, QLinearGradient& gradient )
1356 bool success = false;
1357 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1358 if ( vals.count() > 4 && ( vals[0] == "linear" || vals[0] == "lg" ) )
1360 // start and end points
1361 double x1, y1, x2, y2;
1362 bool bOk1, bOk2, bOk3, bOk4;
1363 x1 = vals[1].toDouble( &bOk1 );
1364 y1 = vals[2].toDouble( &bOk2 );
1365 x2 = vals[3].toDouble( &bOk3 );
1366 y2 = vals[4].toDouble( &bOk4 );
1367 if ( bOk1 && bOk2 && bOk3 && bOk4 )
1369 gradient = QLinearGradient( x1, y1, x2, y2 );
1371 if ( vals.count() > 5 )
1373 QString spread = vals[ 5 ].trimmed().toLower();
1374 if ( spread == "pad" || spread == "0" )
1375 gradient.setSpread( QGradient::PadSpread );
1376 else if ( spread == "repeat" || spread == "2" )
1377 gradient.setSpread( QGradient::RepeatSpread );
1378 else if ( spread == "reflect" || spread == "1" )
1379 gradient.setSpread( QGradient::ReflectSpread );
1382 QGradientStops stops;
1383 for ( int i = 6; i < vals.count(); i+=2 )
1385 bool bOk5, bOk6 = false;
1387 double stop = vals[i].toDouble( &bOk5 );
1388 if ( i+1 < vals.count() )
1389 bOk6 = stringToColor( vals[ i+1 ], c );
1390 if ( bOk5 && stop >= 0.0 && stop <= 1.0 && bOk6 && c.isValid() )
1391 stops.append( QGradientStop( stop, c ) );
1393 gradient.setStops( stops );
1401 \brief Create radial gradient from its string representation.
1402 \param str string representation of the radial gradient
1403 \param gradient resulting radial gradient object
1404 \return \c true if the conversion is successful and \c false otherwise
1405 \sa gradientToString()
1407 bool Qtx::stringToRadialGradient( const QString& str, QRadialGradient& gradient )
1409 bool success = false;
1410 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1411 if ( vals.count() > 5 && ( vals[0] == "radial" || vals[0] == "rg" ) )
1413 // center, radius and focal point
1414 double cx, cy, r, fx, fy;
1415 bool bOk1, bOk2, bOk3, bOk4, bOk5;
1416 cx = vals[1].toDouble( &bOk1 );
1417 cy = vals[2].toDouble( &bOk2 );
1418 fx = vals[3].toDouble( &bOk4 );
1419 fy = vals[4].toDouble( &bOk5 );
1420 r = vals[5].toDouble( &bOk3 );
1421 if ( bOk1 && bOk2 && bOk3 && bOk4 && bOk5 )
1423 gradient = QRadialGradient( cx, cy, r, fx, fy );
1425 if ( vals.count() > 6 )
1427 QString spread = vals[ 6 ].trimmed().toLower();
1428 if ( spread == "pad" || spread == "0" )
1429 gradient.setSpread( QGradient::PadSpread );
1430 else if ( spread == "repeat" || spread == "2" )
1431 gradient.setSpread( QGradient::RepeatSpread );
1432 else if ( spread == "reflect" || spread == "1" )
1433 gradient.setSpread( QGradient::ReflectSpread );
1436 QGradientStops stops;
1437 for ( int i = 7; i < vals.count(); i+=2 )
1439 bool bOk7, bOk8 = false;
1441 double stop = vals[i].toDouble( &bOk7 );
1442 if ( i+1 < vals.count() )
1443 bOk8 = stringToColor( vals[ i+1 ], c );
1444 if ( bOk7 && stop >= 0.0 && stop <= 1.0 && bOk8 && c.isValid() )
1445 stops.append( QGradientStop( stop, c ) );
1447 gradient.setStops( stops );
1455 \brief Create conical gradient from its string representation.
1456 \param str string representation of the conical gradient
1457 \param gradient resulting conical gradient object
1458 \return \c true if the conversion is successful and \c false otherwise
1459 \sa gradientToString()
1461 bool Qtx::stringToConicalGradient( const QString& str, QConicalGradient& gradient )
1463 bool success = false;
1464 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1465 if ( vals.count() > 3 && ( vals[0] == "conical" || vals[0] == "cg" ) )
1469 bool bOk1, bOk2, bOk3;
1470 cx = vals[1].toDouble( &bOk1 );
1471 cy = vals[2].toDouble( &bOk2 );
1472 a = vals[3].toDouble( &bOk3 );
1473 if ( bOk1 && bOk2 && bOk3 )
1475 gradient = QConicalGradient( cx, cy, a );
1477 if ( vals.count() > 4 )
1479 QString spread = vals[ 4 ].trimmed().toLower();
1480 if ( spread == "pad" || spread == "0" )
1481 gradient.setSpread( QGradient::PadSpread );
1482 else if ( spread == "repeat" || spread == "2" )
1483 gradient.setSpread( QGradient::RepeatSpread );
1484 else if ( spread == "reflect" || spread == "1" )
1485 gradient.setSpread( QGradient::ReflectSpread );
1488 QGradientStops stops;
1489 for ( int i = 5; i < vals.count(); i+=2 )
1491 bool bOk4, bOk5 = false;
1493 double stop = vals[i].toDouble( &bOk4 );
1494 if ( i+1 < vals.count() )
1495 bOk5 = stringToColor( vals[ i+1 ], c );
1496 if ( bOk4 && stop >= 0.0 && stop <= 1.0 && bOk5 && c.isValid() )
1497 stops.append( QGradientStop( stop, c ) );
1499 gradient.setStops( stops );
1507 \brief Convert background data to the string representation.
1508 The resulting string consists of several sub-strings separated by ';' symbol.
1509 These sub-strings represent:
1510 1. background type (enumerator, see Qtx::BackgroundMode)
1511 2. texture image file name (string)
1512 3. texture mode (enumerator, see Qtx::TextureMode)
1513 4. "show texture" flag (boolean)
1514 5. first color (for simple gradient data) or solid color (for single-colored mode)
1515 6. second color (for simple gradient data)
1516 7. type of simple gradient (some integer identifier)
1517 8. complex gradient data (for custom gradient mode)
1518 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1520 Backward conversion can be done with stringToBackground() method.
1522 \param bgData background data
1523 \return string representation of the background data
1525 \sa stringToBackground()
1527 QString Qtx::backgroundToString( const Qtx::BackgroundData& bgData )
1529 const QString dtSep = ";";
1530 const QString kwSep = "=";
1531 const QString kwBgType = "bt";
1532 const QString kwFileName = "fn";
1533 const QString kwTextureMode = "tm";
1534 const QString kwShowTexture = "ts";
1535 const QString kwFirstColor = "c1";
1536 const QString kwSecondColor = "c2";
1537 const QString kwGrType = "gt";
1538 const QString kwGrData = "gr";
1540 Qtx::BackgroundMode bgMode = bgData.mode();
1542 Qtx::TextureMode textureMode = bgData.texture( fileName );
1543 bool showTexture = bgData.isTextureShown();
1545 int gradientType = bgData.gradient( c1, c2 );
1546 const QGradient* gradient = bgData.gradient();
1549 switch ( gradient->type() ) {
1550 case QGradient::LinearGradient:
1551 grString = gradientToString( *(static_cast<const QLinearGradient*>( gradient )) );
1553 case QGradient::RadialGradient:
1554 grString = gradientToString( *(static_cast<const QRadialGradient*>( gradient )) );
1556 case QGradient::ConicalGradient:
1557 grString = gradientToString( *(static_cast<const QConicalGradient*>( gradient )) );
1564 data << QString( "%1%2%3" ).arg( kwBgType ).arg( kwSep ).arg( (int)bgMode );
1565 data << QString( "%1%2%3" ).arg( kwFileName ).arg( kwSep ).arg( fileName );
1566 data << QString( "%1%2%3" ).arg( kwTextureMode ).arg( kwSep ).arg( (int)textureMode );
1567 data << QString( "%1%2%3" ).arg( kwShowTexture ).arg( kwSep ).arg( showTexture ? "true" : "false" );
1568 data << QString( "%1%2%3" ).arg( kwFirstColor ).arg( kwSep ).arg( Qtx::colorToString( c1 ) );
1569 data << QString( "%1%2%3" ).arg( kwSecondColor ).arg( kwSep ).arg( Qtx::colorToString( c2 ) );
1570 data << QString( "%1%2%3" ).arg( kwGrType ).arg( kwSep ).arg( gradientType );
1571 data << QString( "%1%2%3" ).arg( kwGrData ).arg( kwSep ).arg( grString );
1573 return data.join( dtSep );
1577 \brief Restore background data from the string representation.
1579 The string should consist of several sub-strings separated by ';' symbol.
1580 Each sub-string consists of keyword/value couple, in form of "<keyword>=<value>".
1581 The sub-strings can follow in arbitrary order, some keywords can be missing.
1582 The background data is described by the following values:
1583 - background type (enumerator, see Qtx::BackgroundMode), keyword "bt"
1584 - texture image file name (string), keyword "fn"
1585 - texture mode (enumerator, see Qtx::TextureMode), keyword "tm"
1586 - "show texture" flag (boolean), keyword "ts"
1587 - first color (for simple gradient data) or solid color (for single-colored mode), keyword "c1"
1588 - second color (for simple gradient data), keyword "c2"
1589 - name of gradient type (string), keyword "gt"
1590 - complex gradient data (for custom gradient mode), keyword "gr"
1592 Also, for backward compatibility, background data can be represented by
1593 single color value, see stringToColor().
1595 Backward conversion can be done with backgroundToString() method.
1596 Returns invalid background if conversion could not be done.
1599 Qtx::BackgroundData bgData = Qtx::stringToBackground( str );
1600 if ( bgData.isValid() ) ) doSomething( bgData );
1603 \param theString string representation of the background data
1604 \return resulting background data (invalid if conversion has failed)
1606 \sa backgroundToString()
1609 Qtx::BackgroundData Qtx::stringToBackground( const QString& str )
1611 const QString dtSep = ";";
1612 const QString kwSep = "=";
1613 const QString kwBgType = "bt";
1614 const QString kwFileName = "fn";
1615 const QString kwTextureMode = "tm";
1616 const QString kwShowTexture = "ts";
1617 const QString kwFirstColor = "c1";
1618 const QString kwSecondColor = "c2";
1619 const QString kwGrType = "gt";
1620 const QString kwGrData = "gr";
1622 Qtx::BackgroundData bgData = BackgroundData();
1624 QStringList data = str.split( dtSep, QString::KeepEmptyParts );
1627 if ( data.count() == 1 && !data.contains( kwSep ) && stringToColor( data[0], c ) ) {
1628 // solid color mode, for backward compatibility
1629 bgData.setColor( c );
1632 QMap<QString, QString> dmap;
1634 foreach( QString d, data ) {
1635 QStringList items = d.split( kwSep, QString::KeepEmptyParts );
1636 if ( items.count() > 0 ) {
1637 QString kw = items.takeFirst().trimmed().toLower(); // keyword
1638 QString val = items.join( kwSep ).trimmed(); // if value contains "=" symbol, we have to restore it
1642 QString bgMode = dmap.value( kwBgType, QString() );
1643 QString fileName = dmap.value( kwFileName, QString() );
1644 QString textureMode = dmap.value( kwTextureMode, QString() );
1645 QString showTexture = dmap.value( kwShowTexture, QString() );
1646 QString color1 = dmap.value( kwFirstColor, QString() );
1647 QString color2 = dmap.value( kwSecondColor, QString() );
1648 QString gradientType = dmap.value( kwGrType, QString() );
1649 QString gradient = dmap.value( kwGrData, QString() );
1652 if ( !fileName.isEmpty() || !textureMode.isEmpty() || !showTexture.isEmpty() ) {
1653 Qtx::TextureMode m = (Qtx::TextureMode)( stringToInt( textureMode, Qtx::CenterTexture,
1654 Qtx::CenterTexture, Qtx::StretchTexture ) );
1655 bgData.setTexture( fileName, m );
1656 QStringList boolvars; boolvars << "true" << "yes" << "ok" << "1";
1657 if ( boolvars.contains( showTexture.trimmed().toLower() ) )
1658 bgData.setTextureShown( true );
1662 bool ok = Qtx::stringToColor( color1, c1 );
1664 bgData.setColor( c1 );
1666 // try simple gradient mode
1667 ok = Qtx::stringToColor( color2, c2 );
1668 if ( ok || !gradientType.isEmpty() ) {
1669 int gt = gradientType.toInt( &ok );
1670 bgData.setGradient( ok ? gt : -1, c1, c2 );
1672 // try custom gradient mode
1674 QConicalGradient cg;
1676 ok = Qtx::stringToLinearGradient( gradient, lg );
1678 bgData.setGradient( lg );
1680 ok = Qtx::stringToRadialGradient( gradient, rg );
1682 bgData.setGradient( rg );
1684 ok = Qtx::stringToConicalGradient( gradient, cg );
1686 bgData.setGradient( cg );
1689 // finally set background mode
1690 Qtx::BackgroundMode m = (Qtx::BackgroundMode)( stringToInt( bgMode, Qtx::ColorBackground,
1691 Qtx::NoBackground, Qtx::CustomGradientBackground ) );
1692 bgData.setMode( m );
1699 \class Qtx::Localizer
1700 \brief Localization helper
1702 This helper class can be used to solve the localization problems,
1703 usually related to the textual files reading/writing, namely when
1704 floating point values are read / written with API functions.
1705 The problem relates to such locale specific settings as decimal point
1706 separator, thousands separator, etc.
1708 To use the Localizer class, just create a local variable in the beginning
1709 of the code where you need to read / write data from textual file(s).
1710 The constructor of the class forces setting "C" locale temporariy.
1711 The destructor switches back to the initial locale.
1721 \brief Constructor. Forces "C" locale to be set.
1723 Qtx::Localizer::Localizer()
1725 myCurLocale = setlocale( LC_NUMERIC, 0 );
1726 setlocale( LC_NUMERIC, "C" );
1730 \brief Destructor. Reverts back to the initial locale.
1732 Qtx::Localizer::~Localizer()
1734 setlocale( LC_NUMERIC, myCurLocale.toLatin1().constData() );
1738 \class Qtx::BackgroundData
1739 \brief Stores background data
1741 This class is used to store background data. Depending on the mode,
1742 the background can be specified by:
1743 - image (by assigning the file name to be used as background texture), see setTexture(), setTextureShown()
1744 - single color (by assigning any color), see setColor()
1745 - simple two-color gradient (with the gradient type id and two colors), see setGradient( int, const QColor&, const QColor& )
1746 - complex gradient (by assigning arbitrary gradient data), see setGradient( const QGradient& )
1748 The class stores all the data passed to it, so switching between different modes can be done
1749 just by calling setMode() function.
1751 \note Texture is used with combination of the background mode.
1753 \note Two-color gradient is specified by two colors and integer identifier. The interpretation of
1754 this identifier should be done in the calling code.
1757 Qtx::BackgroundData bg;
1758 bg.setColor( QColor(100, 100, 100) ); // bg is switched to Qtx::ColorBackground mode
1759 bg.setGradient( Qt::Horizontal, Qt::gray, Qt::white ); // bg is switched to Qtx::ColorBackground mode
1760 QLinearGradient grad( 0,0,1,1 );
1761 grad.setColorAt( 0.0, Qt::gray );
1762 grad.setColorAt( 0.5, Qt::white );
1763 grad.setColorAt( 1.0, Qt::green );
1764 grad.setSpread( QGradient::PadSpread );
1765 bg.setGradient( grad ); // bg is switched to Qtx::CustomGradientBackground mode
1766 bg.setMode( Qtx::ColorBackground ); // bg is switched back to Qtx::ColorBackground mode
1767 bg.setTexture( "/data/images/background.png" ); // specify texture (in the centered mode by default)
1768 bg.setTextureShown( true ); // draw texture on the solid color background
1773 \brief Default constructor.
1774 Creates invalid background data.
1776 Qtx::BackgroundData::BackgroundData()
1777 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1779 setMode( Qtx::NoBackground );
1784 Creates background data initialized with the specified color
1787 Qtx::BackgroundData::BackgroundData( const QColor& c )
1788 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1795 Creates background data initialized with the specified two-color gradient
1796 \param type gradient type identifier
1797 \param c1 first gradient color
1798 \param c2 second gradient color
1799 \note the interpretation of the gradient identifier should be done in the calling code
1801 Qtx::BackgroundData::BackgroundData( int type, const QColor& c1, const QColor& c2 )
1802 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1804 setGradient( type, c1, c2 );
1809 Creates background data initialized with the arbirtary gradient data
1810 \param grad gradient data
1812 Qtx::BackgroundData::BackgroundData( const QGradient& grad )
1813 : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
1815 setGradient( grad );
1821 Qtx::BackgroundData::~BackgroundData()
1826 \brief Compares two background data objects
1828 bool Qtx::BackgroundData::operator==( const Qtx::BackgroundData& other ) const
1831 ( myMode == other.myMode ) &&
1832 ( myTextureMode == other.myTextureMode ) &&
1833 ( myFileName == other.myFileName ) &&
1834 ( myColors == other.myColors ) &&
1835 ( myGradientType == other.myGradientType ) &&
1836 ( myGradient == other.myGradient ) &&
1837 ( myTextureShown == other.myTextureShown );
1841 \brief Returns \c false if background data is not set (invalid)
1842 \return \c true if background data is valid or \c false otherwise
1845 bool Qtx::BackgroundData::isValid() const
1847 return myMode != Qtx::NoBackground;
1851 \brief Get background mode
1852 \return current background mode
1855 Qtx::BackgroundMode Qtx::BackgroundData::mode() const
1861 \brief Set background mode
1862 \param m background mode being set
1865 void Qtx::BackgroundData::setMode( const Qtx::BackgroundMode m )
1871 \brief Get file name used as a texture image
1872 \return path to the texture image file
1873 \sa setTexture(), setTextureShown()
1875 Qtx::TextureMode Qtx::BackgroundData::texture( QString& fileName ) const
1877 fileName = myFileName;
1878 return myTextureMode;
1882 \brief Set file name to be used as a texture image.
1884 \note To show texture image on the background it is necessary to call additionally
1885 setTextureShown() method.
1887 \param fileName path to the texture image file name
1888 \param m texture mode (Qtx::CenterTexture by default)
1889 \sa texture(), setTextureShown()
1891 void Qtx::BackgroundData::setTexture( const QString& fileName, const Qtx::TextureMode m )
1893 myFileName = fileName;
1898 \brief Check if "show texture" flag is switched on
1899 \return \c true if "show texture" flag is set or \c false otherwise
1900 \sa setTextureShown(), texture()
1902 bool Qtx::BackgroundData::isTextureShown() const
1904 return myTextureShown;
1908 \brief Specify if texture should be shown on the background or no.
1909 \param on \c true if texture should be shown or \c false otherwise
1910 \sa isTextureShown(), texture()
1912 void Qtx::BackgroundData::setTextureShown( bool on )
1914 myTextureShown = on;
1918 \brief Get background color. Returns null QColor if color is not set
1919 \return solid background color
1920 \sa setColor(), mode()
1922 QColor Qtx::BackgroundData::color() const
1924 return myColors.count() > 0 ? myColors[0] : QColor();
1928 \brief Set background color and switch to the Qtx::ColorBackground mode
1932 void Qtx::BackgroundData::setColor( const QColor& c )
1936 setMode( Qtx::ColorBackground );
1940 \brief Get simple gradient data.
1941 Returns -1 and null QColor for \a c1 and \a c2 if gradient data is not set
1942 \param c1 first gradient color is returned via this parameter
1943 \param c2 second gradient color is returned via this parameter
1944 \return current two-colored gradient mode type identifier
1945 \note the interpretation of the gradient identifier should be done in the calling code
1946 \sa setGradient(int, const QColor&, const QColor&), mode()
1948 int Qtx::BackgroundData::gradient( QColor& c1, QColor& c2 ) const
1950 c1 = myColors.count() > 0 ? myColors[0] : QColor();
1951 c2 = myColors.count() > 1 ? myColors[1] : ( myColors.count() > 0 ? myColors[0] : QColor() );
1952 return myGradientType;
1956 \brief Set simple background gradient data and switch to the Qtx::SimpleGradientBackground mode
1957 \param type two-colored gradient mode type identifier
1958 \param c1 first gradient color is returned via this parameter
1959 \param c2 second gradient color is returned via this parameter
1960 \note the interpretation of the gradient identifier should be done in the calling code
1961 \sa gradient(QColor&, QColor&), mode()
1963 void Qtx::BackgroundData::setGradient( int type, const QColor& c1, const QColor& c2 )
1966 myColors << c1 << c2;
1967 myGradientType = type;
1968 setMode( Qtx::SimpleGradientBackground );
1972 \brief Get complex gradient data.
1973 Returns QGradient of QGradient::NoGradient if gradient data is not set
1974 \note This function does not transform simple gradient data set with
1975 setGradient( const QString&, const QColor&, const QColor& ) to QGradient class
1976 \return gradient data
1977 \sa setGradient(const QGradient&), mode()
1979 const QGradient* Qtx::BackgroundData::gradient() const
1985 \brief Set complex background gradient data and switch to the Qtx::CustomGradientBackground mode
1986 \param grad gradient data (QLinearGradient, QRadialGradient or QConicalGradient)
1987 \sa gradient(), mode()
1989 void Qtx::BackgroundData::setGradient( const QGradient& grad )
1992 setMode( Qtx::CustomGradientBackground );
1996 \brief Convert string representation of version identifier to the numerical value.
1997 Resulting value can be used for comparison of different versions (lower, higher, equal).
1999 String representation of the version consists of zero or more components:
2001 [major[.minor[.release[patchid]]]]
2004 - major is version major number
2005 - minor is version minor number
2006 - release is version release number
2007 - patchid is a version dev identifier which is one of the following
2008 * 1 letter optionally followed by 1 or 2 digits, e.g. "a" for "alpha", "b1" for "beta 1"
2009 * "rc" optionally followed by 1 or 2 digits, e.g. "rc1" for "release candidate 1"
2010 * "dev" for development version (note: 7.4.0dev > 7.4.0, 7.4.0dev < 7.4.1, 7.4.0dev < 7.4.0a1)
2012 If version string does not include any component or has invalid format, the function returns 0.
2016 1.2.3a - version 1.2.3 alpha
2017 3.3.3b1 - version 3.3.3 beta 1
2018 7.4.0rc1 - version 7.4.0 release candidate 1
2019 7.4.0dev - dev version, i.e. future version 7.4.1 (or 7.5.0)
2021 \param version string representation of version
2022 \return numerical identifier of the version
2024 long Qtx::versionToId( const QString& version )
2028 QRegExp vers_exp( "^([0-9]+)([A-Z]|RC|DEV)?([0-9]{0,2})$", Qt::CaseInsensitive );
2030 QStringList vers = version.split( ".", QString::SkipEmptyParts );
2031 int major=0, minor=0;
2032 int release = 0, dev1 = 0, dev2 = 0;
2033 if ( vers.count() > 0 ) major = vers[0].toInt();
2034 if ( vers.count() > 1 ) minor = vers[1].toInt();
2035 if ( vers.count() > 2 ) {
2036 if ( vers_exp.indexIn( vers[2] ) != -1 ) {
2037 release = vers_exp.cap( 1 ).toInt();
2038 QString tag = vers_exp.cap( 2 ).toLower();
2039 if ( !tag.isEmpty() ) {
2040 // patchid is subtracted from version number
2041 // a = 55 --> -(55 * 100) + patch number --> 4500..4599, e.g. 7.4.1a1 -> 704004501
2042 // b = 54 --> -(54 * 100) + patch number --> 4600..4699, e.g. 7.4.1b1 -> 704004601
2043 // c = 53 --> -(53 * 100) + patch number --> 4700..4799, e.g. 7.4.1c1 -> 704004701
2045 // z = 30 --> -( 1 * 100) + patch number --> 7000..7099, e.g. 7.4.1z1 -> 704007001
2046 // rc = 1 --> -( 1 * 100) + patch number --> 9900..9999, e.g. 7.4.1rc1 -> 704009901
2047 // dev = -1 --> +( 1 * 100) + patch number --> 0100..0199, e.g. 7.4.1dev -> 704010100
2049 // i.e. "a" < "b" < ... < "z" < "rc" < [stable] < "dev"
2052 else if ( tag == "dev" )
2055 dev1 = (int)( QChar('z').toLatin1() ) - (int)( tag[ 0 ].toLatin1() ) + 30;
2057 if ( !vers_exp.cap( 3 ).isEmpty() )
2058 dev2 = vers_exp.cap( 3 ).toInt();
2062 int dev = dev1*100-dev2;
2065 id*=100; id+=release;
2074 #include <X11/Xlib.h>
2078 \brief Open the default X display and returns pointer to it.
2079 This method is available on Linux only.
2080 \return Pointer to X display.
2083 void* Qtx::getDisplay()
2085 static Display* pDisplay = NULL;
2087 pDisplay = XOpenDisplay( NULL );
2092 \brief Returns pointer to X visual suitable for 3D rendering.
2093 This method is available on Linux only.
2094 \return Pointer to X visual.
2097 Qt::HANDLE Qtx::getVisual()
2099 Qt::HANDLE res = (Qt::HANDLE)NULL;
2101 Display* pDisplay = (Display*)getDisplay();
2108 // Make sure OpenGL's GLX extension supported
2109 if( !glXQueryExtension( pDisplay, &errorBase, &eventBase ) ){
2110 qCritical( "Could not find glx extension" );
2114 // Find an appropriate visual
2116 int doubleBufferVisual[] = {
2117 GLX_RGBA, // Needs to support OpenGL
2118 GLX_DEPTH_SIZE, 16, // Needs to support a 16 bit depth buffer
2119 GLX_DOUBLEBUFFER, // Needs to support double-buffering
2120 GLX_STENCIL_SIZE, 1,
2124 // Try for the double-bufferd visual first
2125 XVisualInfo *visualInfo = NULL;
2126 visualInfo = glXChooseVisual( pDisplay, DefaultScreen(pDisplay), doubleBufferVisual );
2128 if( visualInfo == NULL ){
2129 qCritical( "Could not find matching glx visual" );
2133 qDebug() << "Picked visual 0x" << hex << XVisualIDFromVisual( visualInfo->visual );
2134 res = (Qt::HANDLE)( visualInfo->visual );