1 // Copyright (C) 2007-2008 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.
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
23 // Author: Sergey TELKOV
37 #include <QApplication>
38 #include <QDesktopWidget>
39 #include <QLinearGradient>
40 #include <QRadialGradient>
41 #include <QConicalGradient>
49 \brief A set of helpful utility functions.
51 The class implements a set of the static functions which can be used
52 for the different purposes:
53 - specify tab order for the set of widgets: setTabOrder()
54 - align one widget to the coordinates of the another one: alignWidget()
55 - remove extra separators from the menu or toolbar: simplifySeparators()
56 - retrieve directory, file name and extension parts of the path:
57 dir(), file(), extension()
58 - get the path to the temporary directory: tmpDir()
59 - create or remove a directory (recursively): mkDir(), rmDir()
60 - convert text file from DOS to UNIX native format: dos2unix()
61 - convert a picture to the gray scale: grayscale()
66 \brief Convert character array (ASCII string) to the QString.
67 \param str character array
68 \param len array length, if < 0, the array should be zero-terminated
69 \return QString object
71 QString Qtx::toQString( const char* str, const int len )
73 return toQString( (unsigned char*)str, len );
77 \brief Convert integer array (UNICODE string) to the QString.
78 \param str integer array
79 \param len array length, if < 0, the array should be zero-terminated
80 \return QString object
82 QString Qtx::toQString( const short* str, const int len )
84 return toQString( (unsigned short*)str, len );
88 \brief Convert character array (ASCII string) to the QString.
89 \param str character array
90 \param len array length, if < 0, the array should be zero-terminated
91 \return QString object
93 QString Qtx::toQString( const unsigned char* str, const int len )
96 const unsigned char* s = str;
97 while ( len < 0 || res.length() < len )
102 res.append( QChar( *s ) );
109 \brief Convert integer array (UNICODE string) to the QString.
110 \param str integer array
111 \param len array length, if < 0, the array should be zero-terminated
112 \return QString object
114 QString Qtx::toQString( const unsigned short* str, const int len )
117 const unsigned short* s = str;
118 while ( len < 0 || res.length() < len )
123 res.append( QChar( *s ) );
130 \brief Set tab order for specified list of widgets.
132 The function has arbitrary number of parameters, each should be
133 hovewer of QWidget* type. Last parameter should be null pointer.
135 \param first first widget in the sequence
137 void Qtx::setTabOrder( QWidget* first, ... )
140 va_start( wids, first );
144 QWidget* cur = first;
147 widList.append( cur );
148 cur = va_arg( wids, QWidget* );
151 setTabOrder( widList );
155 \brief Set tab order for specified list of widgets.
156 \param widgets list of widgets
158 void Qtx::setTabOrder( const QWidgetList& widgets )
160 if ( widgets.count() < 2 )
164 for ( QWidgetList::const_iterator it = widgets.begin(); it!= widgets.end(); ++it )
168 QWidget::setTabOrder( prev, next );
174 \brief Align widget \a src relative to widget \a ref acording to the
175 alignment flags \a alignFlags.
176 \param src source widget (being aligned)
177 \param ref reference widget (source widget being aligned to)
178 \param alignFlags alignment flags (Qtx::AlignmentFlags)
180 void Qtx::alignWidget( QWidget* src, const QWidget* ref, const int alignFlags )
182 if ( !src || !ref || !alignFlags )
185 QPoint srcOri = src->pos();
186 QPoint refOri = ref->pos();
187 if ( src->parentWidget() && !src->isTopLevel() )
188 srcOri = src->parentWidget()->mapToGlobal( srcOri );
189 if ( ref->parentWidget() && !ref->isTopLevel() )
190 refOri = ref->parentWidget()->mapToGlobal( refOri );
192 int x = srcOri.x(), y = srcOri.y();
193 int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
194 int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
197 srcWidth = src->sizeHint().width();
199 srcHei = src->sizeHint().height();
202 if ( ref->isTopLevel() && ref->isMaximized() &&
203 src->isTopLevel() && !src->isMaximized() )
204 border = ( src->frameGeometry().width() - src->width() ) / 2;
206 if ( alignFlags & Qtx::AlignLeft )
207 x = refOri.x() + border;
208 if ( alignFlags & Qtx::AlignOutLeft )
209 x = refOri.x() - srcWidth - border;
210 if ( alignFlags & Qtx::AlignRight )
211 x = refOri.x() + refWidth - srcWidth - border;
212 if ( alignFlags & Qtx::AlignOutRight )
213 x = refOri.x() + refWidth + border;
214 if ( alignFlags & Qtx::AlignTop )
215 y = refOri.y() + border;
216 if ( alignFlags & Qtx::AlignOutTop )
217 y = refOri.y() - srcHei - border;
218 if ( alignFlags & Qtx::AlignBottom )
219 y = refOri.y() + refHei - srcHei - border;
220 if ( alignFlags & Qtx::AlignOutBottom )
221 y = refOri.y() + refHei + border;
222 if ( alignFlags & Qtx::AlignHCenter )
223 x = refOri.x() + ( refWidth - srcWidth ) / 2;
224 if ( alignFlags & Qtx::AlignVCenter )
225 y = refOri.y() + ( refHei - srcHei ) / 2;
227 if ( src->parentWidget() && !src->isTopLevel() )
229 QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
234 QWidget* desk = QApplication::desktop();
235 if ( desk && x + srcWidth + border > desk->width() )
236 x = desk->width() - srcWidth - border;
237 if ( desk && y + srcHei + border > desk->height() )
238 y = desk->height() - srcHei - border;
247 \brief Remove (recursively) unnecessary separators from the menu or toolbar.
248 \param wid widget, should be of QMenu* or QToolBar* class
250 void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
255 QList<QAction*> items = wid->actions();
256 if ( items.isEmpty() )
259 QList<QAction*> toRemove;
260 for ( int i = 1; i < items.count(); i++ )
262 if ( items[i]->isSeparator() && items[i - 1]->isSeparator() )
263 toRemove.append( items[i] );
265 if ( recursive && items[i]->menu() )
266 simplifySeparators( items[i]->menu(), recursive );
269 for ( QList<QAction*>::iterator it = toRemove.begin(); it != toRemove.end(); ++it )
270 wid->removeAction( *it );
272 items = wid->actions();
273 if ( !items.isEmpty() && items[0]->isSeparator() )
274 wid->removeAction( items[0] );
276 items = wid->actions();
277 if ( !items.isEmpty() && items[items.count() - 1]->isSeparator() )
278 wid->removeAction( items[items.count() - 1] );
282 \brief Return \c true if specified \a parent is a parent object
283 of given \a child (in terms of QObject).
285 This function works recursively. It means that \a true is also
286 returned if \a parent is a grand-father, grand-grand-father, etc
287 of \a child. If the same object is given as both \a parent and
288 \a child, \c true is also returned.
290 \param child child object
291 \param parent parent object
292 \return \c true if the \a parent is a parent of \a child
294 bool Qtx::isParent( QObject* child, QObject* parent )
296 if ( !child || !parent )
300 QObject* obj = child;
301 while ( !res && obj )
310 \brief Find the parent object of class specified by \a className (in terms of QObject).
312 \param obj current object
313 \param className class name of the parent
314 \return parent object or null pointer if the parent not found
316 QObject* Qtx::findParent( QObject* obj, const char* className )
321 if ( !className || !strlen( className ) )
322 return obj->parent();
325 QObject* p = obj->parent();
328 if ( p->inherits( className ) )
337 \brief Return directory part of the file path.
339 If the file path does not include directory part (the file is in the
340 current directory), null string is returned.
342 \param path file path
343 \param abs if true (default) \a path parameter is treated as absolute file path
344 \return directory part of the file path
346 QString Qtx::dir( const QString& path, const bool abs )
348 QDir aDir = QFileInfo( path ).dir();
349 QString dirPath = abs ? aDir.absolutePath() : aDir.path();
350 if ( dirPath == QString( "." ) )
356 \brief Return file name part of the file path.
358 \param path file path
359 \param withExt if true (default) complete file name (with all
360 extension except the last) is returned, otherwise only base name
362 \return file name part of the file path
364 QString Qtx::file( const QString& path, bool withExt )
366 QString fPath = path;
367 while ( !fPath.isEmpty() && ( fPath[fPath.length() - 1] == '\\' || fPath[fPath.length() - 1] == '/' ) )
368 fPath.remove( fPath.length() - 1, 1 );
371 return QFileInfo( fPath ).fileName();
373 return QFileInfo( fPath ).baseName();
377 \brief Return extension part of the file path.
379 \param path file path
380 \param full if true complete extension (all extensions, dot separated)
381 is returned, otherwise (default) only last extension is returned
382 \return extension part of the file path
384 QString Qtx::extension( const QString& path, const bool full )
386 return full ? QFileInfo( path ).completeSuffix() : QFileInfo( path ).suffix();
390 \brief Convert the given parameter to the platform-specific library name.
392 The function appends platform-specific prefix (lib) and suffix (.dll/.so)
393 to the library file name.
394 For example, if \a str = "mylib", "libmylib.so" is returned for Linux and
395 mylib.dll for Windows.
397 \param str short library name
398 \return full library name
400 QString Qtx::library( const QString& str )
402 QString path = dir( str, false );
403 QString name = file( str, false );
404 QString ext = extension( str );
407 if ( !name.startsWith( "lib" ) )
408 name = QString( "lib" ) + name;
412 QString libExt( "dll" );
414 QString libExt( "so" );
417 if ( ext.toLower() != QString( "so" ) && ext.toLower() != QString( "dll" ) )
419 if ( !name.isEmpty() && !ext.isEmpty() )
420 name += QString( "." );
426 QString fileName = addSlash( path ) + name + QString( "." ) + ext;
432 \brief Get the temporary directory name.
433 \return temporary directory (platform specific)
435 QString Qtx::tmpDir()
437 char* tmpdir = ::getenv( "TEMP" );
439 tmpdir = ::getenv ( "TMP" );
448 return QString( tmpdir );
452 \brief Create directory recursively including all intermediate sub directories.
453 \return \c true if the directory is successfully created and \c false otherwise
455 bool Qtx::mkDir( const QString& dirPath )
457 return QDir().mkpath( dirPath );
461 \brief Remove directory recursively including all subdirectories and files.
462 \return \c true if the directory is successfully removed and \c false otherwise
464 bool Qtx::rmDir( const QString& thePath )
466 QFileInfo fi( thePath );
472 stat = QFile::remove( thePath );
473 else if ( fi.isDir() )
475 QDir aDir( thePath );
476 QFileInfoList anEntries = aDir.entryInfoList();
477 for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
480 if ( inf.fileName() == "." || inf.fileName() == ".." )
482 stat = stat && rmDir( inf.absoluteFilePath() );
484 stat = stat && aDir.rmdir( thePath );
490 \brief Add a slash (platform-specific) to the end of \a path
491 if it is not already there.
492 \param path directory path
493 \return modified path (with slash added to the end)
495 QString Qtx::addSlash( const QString& path )
498 if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
499 res.at( res.length() - 1 ) != QChar( '\\' ) )
500 res += QDir::separator();
505 \brief Convert text file from DOS format to UNIX.
507 The function replaces "LF/CR" symbols sequence by "LF" symbol.
509 \param absName file name
510 \return \c true if the file is converted successfully and \c false in
513 bool Qtx::dos2unix( const QString& absName )
515 FILE* src = ::fopen( absName.toLatin1(), "rb" );
519 /* we'll use temporary file */
520 char temp[512] = { '\0' };
521 QString dir = Qtx::dir( absName );
522 FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toLatin1(), "__x" ) ), "wb" );
526 /* temp -> result of conversion */
527 const char CR = 0x0d;
528 const char LF = 0x0a;
529 bool waitingLF = false;
534 char inbuf[512], outbuf[512];
537 int nbread = ::fread( inbuf, 1, sizeof( inbuf ), src );
538 for ( int incnt = 0; incnt < nbread; incnt++ )
543 if ( inbuf[incnt] == LF )
544 outbuf[outcnt++] = LF;
546 outbuf[outcnt++] = CR;
548 else if ( inbuf[incnt] == CR )
551 outbuf[outcnt++] = inbuf[incnt];
554 /* check last sym in buffer */
555 waitingLF = ( inbuf[nbread - 1] == CR );
557 /* write converted buffer to temp file */
558 int nbwri = ::fwrite( outbuf, 1, outcnt, tgt );
559 if ( nbwri != outcnt )
563 QFile::remove( QString( temp ) );
566 if ( nbread != sizeof( inbuf ) )
567 break; /* converted ok */
572 /* rename temp -> src */
573 if ( !QFile::remove( absName ) )
576 return QDir().rename( QString( temp ), absName );
580 \brief Create path completer which can be used in the widgets
581 to provide auto completions.
583 Create an instance of QCompleter class and returns the pointer on it.
584 The calling function is responsible to the desstroying of the created
587 The QCompleter class provides completions based on a item model and can be
588 used in such as QLineEdit and QComboBox.
589 When the user starts typing a word, QCompleter suggests possible ways of
590 completing the word, based on a word list.
592 \param type path type (Qtx::PathType)
593 \param filter file/directory filters (list of wildcards, separated by ";;")
594 \return a pointer to the created completer
596 QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
599 QStringList filterList = filter.split( ";;" );
600 for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
602 QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
604 while ( ( index = rx.indexIn( *it, index ) ) != -1 )
606 extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
607 index += rx.matchedLength();
611 QDir::Filters filters = 0;
616 filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
619 filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
623 QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
624 QCompleter* cmp = new QCompleter( dm, 0 );
625 dm->setParent( cmp );
631 \brief Pack the specified color into integer RGB set.
632 \param c unpacked color
635 int Qtx::rgbSet( const QColor& c )
637 return rgbSet( c.red(), c.green(), c.blue() );
641 \brief Pack the specified RGB color components into integer RGB set.
642 \param r red component
643 \param g green component
644 \param b blue component
647 int Qtx::rgbSet( const int r, const int g, const int b )
649 return ( ( ( 0xff & r ) << 16 ) + ( ( 0xff & g ) << 8 ) + ( 0xff & b ) );
653 \brief Unpack the specified integer RGB set to the color.
654 \param rgb packed color
655 \return unpacked color (QColor)
657 QColor Qtx::rgbSet( const int rgb )
660 rgbSet( rgb, r, g, b );
661 return QColor( r, g, b );
665 \brief Unpack the specified integer RGB set to the three RGB components.
666 \param rgb packed color
667 \param r returned unpacked red component
668 \param g returned unpacked green component
669 \param b returned unpacked blue component
671 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
673 r = ( rgb >> 16 ) & 0xff;
674 g = ( rgb >> 8 ) & 0xff;
679 \brief Return the color specified by the index between min (blue) and max (red).
680 \param index color index
681 \param min required minimum hue value
682 \param max required maximum hue value
683 \return resulting color
685 QColor Qtx::scaleColor( const int index, const int min, const int max )
687 static const int HUE[10] = {230, 210, 195, 180, 160, 80, 60, 50, 30, 0};
693 double aPosition = 9.0 * ( index - min ) / ( max - min );
694 if ( aPosition > 0.0 )
696 if ( aPosition >= 9.0 )
700 int idx = (int)aPosition;
701 hue = HUE[idx] + int( ( aPosition - idx ) * ( HUE[idx + 1] - HUE[idx] ) );
706 return QColor::fromHsv( hue, 255, 255 );
710 \brief Generate required number of colors aligned from blue to red.
711 \param num required number of colors
712 \param lst returned set of colors
714 void Qtx::scaleColors( const int num, QColorList& lst )
717 for ( int i = 0; i < num; i++ )
718 lst.append( scaleColor( i, 0, num - 1 ) );
722 \brief Scale the pixmap to the required size.
724 If \h is 0 (default) the value of \a w is used instead (to create
727 \param icon pixmap to be resized
728 \param w required pixmap width
729 \param h required pixmap height
730 \return scaled pixmap
732 QPixmap Qtx::scaleIcon( const QPixmap& icon, const unsigned w, const unsigned h )
735 int aw = w, ah = h <= 0 ? w : h;
736 if ( icon.isNull() || aw <= 0 || ah <= 0 || aw == icon.width() && ah == icon.height() )
739 p = icon.fromImage( icon.toImage().scaled( aw, ah, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
744 \brief Convert given image to the grayscale format.
745 \param img initial image
746 \return converted to the grayscale image
748 QImage Qtx::grayscale( const QImage& img )
752 int colNum = res.numColors();
755 for ( int i = 0; i < colNum; i++ )
756 res.setColor( i, qGray( res.color( i ) ) );
760 for ( int y = 0; y < res.height(); y++ )
762 for ( int x = 0; x < res.width(); x++ )
764 QRgb pix = res.pixel( x, y );
765 res.setPixel( x, y, qRgba( qGray( pix ), qGray( pix ), qGray( pix ), qAlpha( pix ) ) );
774 \brief Convert given pixmap to the grayscale format.
775 \param pix initial pixmap
776 \return converted to the grayscale pixmap
778 QPixmap Qtx::grayscale( const QPixmap& pix )
781 res.fromImage( grayscale( pix.toImage() ) );
786 \brief Create transparent image.
787 \param w required image width
788 \param h required image height
789 \param d required image depth
790 \return generated image
792 QImage Qtx::transparentImage( const int w, const int h, const int d )
798 fmt = QImage::Format_Mono;
801 fmt = QImage::Format_Indexed8;
807 fmt = QImage::Format_ARGB32;
811 QImage img( w, h, fmt );
814 // img.setAlphaBuffer( true );
815 for ( int i = 0; i < img.height(); i++ )
816 for ( int j = 0; j < img.width(); j++ )
817 img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) );
823 \brief Create transparent pixmap.
824 \param w required image width
825 \param h required pixmap height
826 \param d required pixmap depth
827 \return generated pixmap
829 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
832 QImage img = transparentImage( w, h, d );
834 pix.fromImage( img );
839 \brief Create composite pixmap.
841 Pixmap \a pix is drawn over pixmap \a dest with coordinates
842 specified relatively to the upper left corner of \a dest.
843 If \a dest is not given, the new empty pixmap with appropriate size created instead.
845 \param pix source pixmap
846 \param x horizontal shift
847 \param y vertical shift
848 \param dest background pixmap
849 \return resulting pixmap
851 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
856 int width = qMax( pix.width() + x, dest.width() );
857 int height = qMax( pix.height() + y, dest.height() );
859 QPixmap res( width, height );
860 QImage img = transparentImage( width, height, 32 );
864 p.fillRect( 0, 0, width, height, QBrush( Qt::white ) );
866 if ( !dest.isNull() )
868 p.drawPixmap( 0, 0, dest );
869 QImage temp = dest.toImage();
870 for ( int i = 0; i < temp.width() && i < img.width(); i++ )
872 for ( int j = 0; j < temp.height() && j < img.height(); j++ )
874 if ( temp.hasAlphaChannel() )
875 img.setPixel( i, j, temp.pixel( i, j ) );
878 QRgb p = temp.pixel( i, j );
879 img.setPixel( i, j, qRgba( qRed( p ), qGreen( p ), qBlue( p ), 255 ) );
885 p.drawPixmap( x, y, pix );
886 QImage temp = pix.toImage();
887 for ( int c = x; c < temp.width() + x && c < img.width(); c++ )
889 for ( int r = y; r < temp.height() + y && r < img.height(); r++ )
891 if ( qAlpha( temp.pixel( c - x, r - y ) ) > 0 )
892 img.setPixel( c, r, temp.pixel( c - x, r - y ) );
898 for ( int ai = 0; ai < img.width(); ai++ )
900 for ( int aj = 0; aj < img.height(); aj++ )
902 if ( qAlpha( img.pixel( ai, aj ) ) < 1 )
903 img.setPixel( ai, aj, qRgba( 255, 255, 255, 255 ) );
905 img.setPixel( ai, aj, qRgba( 0, 0, 0, 0 ) );
909 QBitmap bmp( width, height );
910 bmp.fromImage( img, Qt::ColorMode_Mask | Qt::ThresholdDither );
917 \brief Convert color to the string representation.
919 The resulting string is in the one of two possible formats
920 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
921 and alpha components of the color):
922 - if color has alpha channel : "#RR,#GG,#BB,#AA"
923 - if color does not have alpha channel : "#RRGGBB"
925 If color is invalid, null string is returned.
927 Backward conversion can be done with stringToColor() method.
929 \param color color to be converted
930 \return string representation of the color
934 QString Qtx::colorToString( const QColor& color )
937 if ( color.isValid() )
939 if ( color.alpha() != 255 )
942 vals << QString( "#%1" ).arg( color.red(), 0, 16 );
943 vals << QString( "#%1" ).arg( color.green(), 0, 16 );
944 vals << QString( "#%1" ).arg( color.blue(), 0, 16 );
945 vals << QString( "#%1" ).arg( color.alpha(), 0, 16 );
946 str = vals.join( "," );
957 \brief Create color from the string representation.
959 The parameter \a str must be in the one of following formats
960 (\c RR, \c GG, \c BB and \c AA value represent red, green, blue
961 and alpha components of the color):
962 - "#RR,#GG,#BB[,#AA]" or "#RR #GG #BB[ #AA]" (\c RR, \c GG, \c BB
963 and optional \c AA values represent red, green, blue and alpha
964 components of the color in hexadecimal form)
965 - "RR,GG,BB[,AA]" or "RR GG BB[ AA]" (\c RR, \c GG, \c BB
966 and optional \c AA values represent red, green, blue and alpha
967 components of the color in decimal form)
968 - #RRGGBB" - (\c RR, \c GG and \c BB values represent red, green and blue
969 components of the color in hexadecimal form)
970 - an integer value representing packed color components (see rgbSet())
971 - a name from the list of colors defined in the list of SVG color keyword names
972 provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
974 Backward conversion can be done with colorToString() method.
976 \param str string representation of the color
977 \param color resulting color value
978 \return \c true if the conversion is successful and \c false otherwise
980 \sa colorToString(), rgbSet()
982 bool Qtx::stringToColor( const QString& str, QColor& color )
985 QStringList vals = str.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
988 for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
991 if ( (*it).startsWith( "#" ) )
992 num = (*it).mid( 1 ).toInt( &res, 16 );
994 num = (*it).toInt( &res, 10 );
999 res = res && nums.count() >= 3;
1001 color.setRgb( nums[0], nums[1], nums[2] );
1005 int pack = str.toInt( &res );
1007 color = Qtx::rgbSet( pack );
1012 color = QColor( str );
1013 res = color.isValid();
1020 \brief Dump linear gradient to the string description.
1021 \param gradient linear gradient to be converted
1022 \return string representation of the linear gradient
1023 \sa stringToLinearGradient()
1025 QString Qtx::gradientToString( const QLinearGradient& gradient )
1029 data << QString::number( gradient.start().x() );
1030 data << QString::number( gradient.start().y() );
1031 data << QString::number( gradient.finalStop().x() );
1032 data << QString::number( gradient.finalStop().y() );
1033 switch( gradient.spread() )
1035 case QGradient::PadSpread:
1038 case QGradient::RepeatSpread:
1041 case QGradient::ReflectSpread:
1047 QGradientStops stops = gradient.stops();
1049 foreach ( stop, stops )
1051 data << QString::number( stop.first );
1052 data << colorToString( stop.second );
1054 return data.join( "|" );
1058 \brief Dump radial gradient to the string description.
1059 \param gradient radial gradient to be converted
1060 \return string representation of the radial gradient
1061 \sa stringToRadialGradient()
1063 QString Qtx::gradientToString( const QRadialGradient& gradient )
1067 data << QString::number( gradient.center().x() );
1068 data << QString::number( gradient.center().y() );
1069 data << QString::number( gradient.focalPoint().x() );
1070 data << QString::number( gradient.focalPoint().y() );
1071 data << QString::number( gradient.radius() );
1072 switch( gradient.spread() )
1074 case QGradient::PadSpread:
1077 case QGradient::RepeatSpread:
1080 case QGradient::ReflectSpread:
1086 QGradientStops stops = gradient.stops();
1088 foreach ( stop, stops )
1090 data << QString::number( stop.first );
1091 data << colorToString( stop.second );
1093 return data.join( "|" );
1097 \brief Dump conical gradient to the string description.
1098 \param gradient conical gradient to be converted
1099 \return string representation of the conical gradient
1100 \sa stringToConicalGradient()
1102 QString Qtx::gradientToString( const QConicalGradient& gradient )
1106 data << QString::number( gradient.center().x() );
1107 data << QString::number( gradient.center().y() );
1108 data << QString::number( gradient.angle() );
1109 switch( gradient.spread() )
1111 case QGradient::PadSpread:
1114 case QGradient::RepeatSpread:
1117 case QGradient::ReflectSpread:
1123 QGradientStops stops = gradient.stops();
1125 foreach ( stop, stops )
1127 data << QString::number( stop.first );
1128 data << colorToString( stop.second );
1130 return data.join( "|" );
1134 \brief Create linear gradient from its string representation.
1135 \param str string representation of the linear gradient
1136 \param gradient resulting linear gradient object
1137 \return \c true if the conversion is successful and \c false otherwise
1138 \sa gradientToString()
1140 bool Qtx::stringToLinearGradient( const QString& str, QLinearGradient& gradient )
1142 bool success = false;
1143 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1144 if ( vals.count() > 4 && ( vals[0] == "linear" || vals[0] == "lg" ) )
1146 // start and end points
1147 double x1, y1, x2, y2;
1148 bool bOk1, bOk2, bOk3, bOk4;
1149 x1 = vals[1].toDouble( &bOk1 );
1150 y1 = vals[2].toDouble( &bOk2 );
1151 x2 = vals[3].toDouble( &bOk3 );
1152 y2 = vals[4].toDouble( &bOk4 );
1153 if ( bOk1 && bOk2 && bOk3 && bOk4 )
1155 gradient = QLinearGradient( x1, y1, x2, y2 );
1157 if ( vals.count() > 5 )
1159 QString spread = vals[ 5 ].trimmed().toLower();
1160 if ( spread == "pad" || spread == "0" )
1161 gradient.setSpread( QGradient::PadSpread );
1162 else if ( spread == "repeat" || spread == "2" )
1163 gradient.setSpread( QGradient::RepeatSpread );
1164 else if ( spread == "reflect" || spread == "1" )
1165 gradient.setSpread( QGradient::ReflectSpread );
1168 QGradientStops stops;
1169 for ( int i = 6; i < vals.count(); i+=2 )
1171 bool bOk5, bOk6 = false;
1173 double stop = vals[i].toDouble( &bOk5 );
1174 if ( i+1 < vals.count() )
1175 bOk6 = stringToColor( vals[ i+1 ], c );
1176 if ( bOk5 && stop >= 0.0 && stop <= 1.0 && bOk6 && c.isValid() )
1177 stops.append( QGradientStop( stop, c ) );
1179 gradient.setStops( stops );
1187 \brief Create radial gradient from its string representation.
1188 \param str string representation of the radial gradient
1189 \param gradient resulting radial gradient object
1190 \return \c true if the conversion is successful and \c false otherwise
1191 \sa gradientToString()
1193 bool Qtx::stringToRadialGradient( const QString& str, QRadialGradient& gradient )
1195 bool success = false;
1196 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1197 if ( vals.count() > 5 && vals[0] == "radial" || vals[0] == "rg" )
1199 // center, radius and focal point
1200 double cx, cy, r, fx, fy;
1201 bool bOk1, bOk2, bOk3, bOk4, bOk5;
1202 cx = vals[1].toDouble( &bOk1 );
1203 cy = vals[2].toDouble( &bOk2 );
1204 fx = vals[3].toDouble( &bOk4 );
1205 fy = vals[4].toDouble( &bOk5 );
1206 r = vals[5].toDouble( &bOk3 );
1207 if ( bOk1 && bOk2 && bOk3 && bOk4 && bOk5 )
1209 gradient = QRadialGradient( cx, cy, r, fx, fy );
1211 if ( vals.count() > 6 )
1213 QString spread = vals[ 6 ].trimmed().toLower();
1214 if ( spread == "pad" || spread == "0" )
1215 gradient.setSpread( QGradient::PadSpread );
1216 else if ( spread == "repeat" || spread == "2" )
1217 gradient.setSpread( QGradient::RepeatSpread );
1218 else if ( spread == "reflect" || spread == "1" )
1219 gradient.setSpread( QGradient::ReflectSpread );
1222 QGradientStops stops;
1223 for ( int i = 7; i < vals.count(); i+=2 )
1225 bool bOk7, bOk8 = false;
1227 double stop = vals[i].toDouble( &bOk7 );
1228 if ( i+1 < vals.count() )
1229 bOk8 = stringToColor( vals[ i+1 ], c );
1230 if ( bOk7 && stop >= 0.0 && stop <= 1.0 && bOk8 && c.isValid() )
1231 stops.append( QGradientStop( stop, c ) );
1233 gradient.setStops( stops );
1241 \brief Create conical gradient from its string representation.
1242 \param str string representation of the conical gradient
1243 \param gradient resulting conical gradient object
1244 \return \c true if the conversion is successful and \c false otherwise
1245 \sa gradientToString()
1247 bool Qtx::stringToConicalGradient( const QString& str, QConicalGradient& gradient )
1249 bool success = false;
1250 QStringList vals = str.split( "|", QString::SkipEmptyParts );
1251 if ( vals.count() > 3 && vals[0] == "conical" || vals[0] == "cg" )
1255 bool bOk1, bOk2, bOk3;
1256 cx = vals[1].toDouble( &bOk1 );
1257 cy = vals[2].toDouble( &bOk2 );
1258 a = vals[3].toDouble( &bOk3 );
1259 if ( bOk1 && bOk2 && bOk3 )
1261 gradient = QConicalGradient( cx, cy, a );
1263 if ( vals.count() > 4 )
1265 QString spread = vals[ 4 ].trimmed().toLower();
1266 if ( spread == "pad" || spread == "0" )
1267 gradient.setSpread( QGradient::PadSpread );
1268 else if ( spread == "repeat" || spread == "2" )
1269 gradient.setSpread( QGradient::RepeatSpread );
1270 else if ( spread == "reflect" || spread == "1" )
1271 gradient.setSpread( QGradient::ReflectSpread );
1274 QGradientStops stops;
1275 for ( int i = 5; i < vals.count(); i+=2 )
1277 bool bOk4, bOk5 = false;
1279 double stop = vals[i].toDouble( &bOk4 );
1280 if ( i+1 < vals.count() )
1281 bOk5 = stringToColor( vals[ i+1 ], c );
1282 if ( bOk4 && stop >= 0.0 && stop <= 1.0 && bOk5 && c.isValid() )
1283 stops.append( QGradientStop( stop, c ) );
1285 gradient.setStops( stops );