Back to index

salome-gui  6.5.0
Qtx.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      Qtx.cxx
00024 // Author:    Sergey TELKOV
00025 //
00026 #include "Qtx.h"
00027 
00028 #include <QDir>
00029 #include <QMenu>
00030 #include <QRegExp>
00031 #include <QBitmap>
00032 #include <QWidget>
00033 #include <QLayout>
00034 #include <QPainter>
00035 #include <QDirModel>
00036 #include <QFileInfo>
00037 #include <QCompleter>
00038 #include <QApplication>
00039 #include <QDesktopWidget>
00040 #include <QtDebug>
00041 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <stdarg.h>
00045 #include <clocale>
00046 
00047 #define BICOLOR_CHANGE_HUE
00048 
00060 static int stringToInt( const QString& str, int defVal, int minVal, int maxVal )
00061 {
00062   bool ok;
00063   int v = str.toInt( &ok );
00064   if ( !ok ) v = defVal;
00065   return qMin( qMax( v, minVal ), maxVal );
00066 }
00067 
00092 QString Qtx::toQString( const char* str, const int len )
00093 {
00094   return toQString( (unsigned char*)str, len );
00095 }
00096 
00103 QString Qtx::toQString( const short* str, const int len )
00104 {
00105   return toQString( (unsigned short*)str, len );
00106 }
00107 
00114 QString Qtx::toQString( const unsigned char* str, const int len )
00115 {
00116   QString res;
00117   const unsigned char* s = str;
00118   while ( len < 0 || res.length() < len )
00119   {
00120     if ( *s == '\0' )
00121       break;
00122 
00123     res.append( QChar( *s ) );
00124     s++;
00125   }
00126   return res;
00127 }
00128 
00135 QString Qtx::toQString( const unsigned short* str, const int len )
00136 {
00137   QString res;
00138   const unsigned short* s = str;
00139   while ( len < 0 || res.length() < len )
00140   {
00141     if ( *s == '\0' )
00142       break;
00143 
00144     res.append( QChar( *s ) );
00145     s++;
00146   }
00147   return res;
00148 }
00149 
00158 void Qtx::setTabOrder( QWidget* first, ... )
00159 {
00160   va_list wids;
00161   va_start( wids, first );
00162 
00163   QWidgetList widList;
00164 
00165   QWidget* cur = first;
00166   while ( cur )
00167   {
00168     widList.append( cur );
00169     cur = va_arg( wids, QWidget* );
00170   }
00171 
00172   setTabOrder( widList );
00173 }
00174 
00179 void Qtx::setTabOrder( const QWidgetList& widgets )
00180 {
00181   if ( widgets.count() < 2 )
00182     return;
00183 
00184   QWidget* prev = 0;
00185   for ( QWidgetList::const_iterator it = widgets.begin(); it!= widgets.end(); ++it )
00186   {
00187     QWidget* next = *it;
00188     if ( prev && next )
00189       QWidget::setTabOrder( prev, next );
00190     prev = next;
00191   }
00192 }
00193 
00201 void Qtx::alignWidget( QWidget* src, const QWidget* ref, const int alignFlags )
00202 {
00203   if ( !src || !ref || !alignFlags )
00204     return;
00205 
00206   QPoint srcOri = src->pos();
00207   QPoint refOri = ref->pos();
00208   if ( src->parentWidget() && !src->isTopLevel() )
00209     srcOri = src->parentWidget()->mapToGlobal( srcOri );
00210   if ( ref->parentWidget() && !ref->isTopLevel() )
00211     refOri = ref->parentWidget()->mapToGlobal( refOri );
00212 
00213   int x = srcOri.x(), y = srcOri.y();
00214   int refWidth = ref->frameGeometry().width(), refHei = ref->frameGeometry().height();
00215   int srcWidth = src->frameGeometry().width(), srcHei = src->frameGeometry().height();
00216 
00217   if ( srcWidth <= 0 )
00218     srcWidth = src->sizeHint().width();
00219   if ( srcHei <= 0 )
00220     srcHei = src->sizeHint().height();
00221 
00222   int border = 0;
00223   if ( ref->isTopLevel() && ref->isMaximized() &&
00224        src->isTopLevel() && !src->isMaximized() )
00225     border = ( src->frameGeometry().width() - src->width() ) / 2;
00226 
00227   if ( alignFlags & Qtx::AlignLeft )
00228     x = refOri.x() + border;
00229   if ( alignFlags & Qtx::AlignOutLeft )
00230     x = refOri.x() - srcWidth - border;
00231   if ( alignFlags & Qtx::AlignRight )
00232     x = refOri.x() + refWidth - srcWidth - border;
00233   if ( alignFlags & Qtx::AlignOutRight )
00234     x = refOri.x() + refWidth + border;
00235   if ( alignFlags & Qtx::AlignTop )
00236     y = refOri.y() + border;
00237   if ( alignFlags & Qtx::AlignOutTop )
00238     y = refOri.y() - srcHei - border;
00239   if ( alignFlags & Qtx::AlignBottom )
00240     y = refOri.y() + refHei - srcHei - border;
00241   if ( alignFlags & Qtx::AlignOutBottom )
00242     y = refOri.y() + refHei + border;
00243   if ( alignFlags & Qtx::AlignHCenter )
00244     x = refOri.x() + ( refWidth - srcWidth ) / 2;
00245   if ( alignFlags & Qtx::AlignVCenter )
00246     y = refOri.y() + ( refHei - srcHei ) / 2;
00247 
00248   if ( src->parentWidget() && !src->isTopLevel() )
00249   {
00250     QPoint pos = src->parentWidget()->mapFromGlobal( QPoint( x, y ) );
00251     x = pos.x();
00252     y = pos.y();
00253   }
00254 
00255   QWidget* desk = QApplication::desktop();
00256   if ( desk && x + srcWidth + border > desk->width() )
00257     x = desk->width() - srcWidth - border;
00258   if ( desk && y + srcHei + border > desk->height() )
00259     y = desk->height() - srcHei - border;
00260 
00261   x = qMax( x, 0 );
00262   y = qMax( y, 0 );
00263 
00264   src->move( x, y );
00265 }
00266 
00271 void Qtx::simplifySeparators( QWidget* wid, const bool recursive )
00272 {
00273   if ( !wid )
00274     return;
00275 
00276   QList<QAction*> items = wid->actions();
00277   if ( items.isEmpty() )
00278     return;
00279 
00280   QList<QAction*> toRemove;
00281   for ( int i = 1; i < items.count(); i++ )
00282   {
00283     if ( items[i]->isSeparator() && items[i - 1]->isSeparator() )
00284       toRemove.append( items[i] );
00285 
00286     if ( recursive && items[i]->menu() )
00287       simplifySeparators( items[i]->menu(), recursive );
00288   }
00289 
00290   for ( QList<QAction*>::iterator it = toRemove.begin(); it != toRemove.end(); ++it )
00291     wid->removeAction( *it );
00292 
00293   items = wid->actions();
00294   if ( !items.isEmpty() && items[0]->isSeparator() )
00295     wid->removeAction( items[0] );
00296 
00297   items = wid->actions();
00298   if ( !items.isEmpty() && items[items.count() - 1]->isSeparator() )
00299     wid->removeAction( items[items.count() - 1] );
00300 }
00301 
00315 bool Qtx::isParent( QObject* child, QObject* parent )
00316 {
00317   if ( !child || !parent )
00318     return false;
00319 
00320   bool res = false;
00321   QObject* obj = child;
00322   while ( !res && obj )
00323   {
00324     res = obj == parent;
00325     obj = obj->parent();
00326   }
00327   return res;
00328 }
00329 
00337 QObject* Qtx::findParent( QObject* obj, const char* className )
00338 {
00339   if ( !obj )
00340     return 0;
00341 
00342   if ( !className || !strlen( className ) )
00343     return obj->parent();
00344 
00345   QObject* res = 0;
00346   QObject* p = obj->parent();
00347   while ( p && !res )
00348   {
00349     if ( p->inherits( className ) )
00350       res = p;
00351     p = p->parent();
00352   }
00353 
00354   return res;
00355 }
00356 
00367 QString Qtx::dir( const QString& path, const bool abs )
00368 {
00369   QDir aDir = QFileInfo( path ).dir();
00370   QString dirPath = abs ? aDir.absolutePath() : aDir.path();
00371   if ( dirPath == QString( "." ) )
00372     dirPath = QString();
00373   return dirPath;
00374 }
00375 
00385 QString Qtx::file( const QString& path, bool withExt )
00386 {
00387   QString fPath = path;
00388   while ( !fPath.isEmpty() && ( fPath[fPath.length() - 1] == '\\' || fPath[fPath.length() - 1] == '/' ) )
00389     fPath.remove( fPath.length() - 1, 1 );
00390 
00391   if ( withExt )
00392     return QFileInfo( fPath ).fileName();
00393   else
00394     return QFileInfo( fPath ).baseName();
00395 }
00396 
00405 QString Qtx::extension( const QString& path, const bool full )
00406 {
00407   return full ? QFileInfo( path ).completeSuffix() : QFileInfo( path ).suffix();
00408 }
00409 
00421 QString Qtx::library( const QString& str )
00422 {
00423   QString path = dir( str, false );
00424   QString name = file( str, false );
00425   QString ext  = extension( str );
00426 
00427 #ifndef WIN32
00428   if ( !name.startsWith( "lib" ) )
00429     name = QString( "lib" ) + name;
00430 #endif
00431 
00432 #ifdef WIN32
00433   QString libExt( "dll" );
00434 #else
00435   QString libExt( "so" );
00436 #endif
00437 
00438   if ( ext.toLower() != QString( "so" ) && ext.toLower() != QString( "dll" ) )
00439   {
00440     if ( !name.isEmpty() && !ext.isEmpty() )
00441       name += QString( "." );
00442     name += ext;
00443   }
00444 
00445   ext = libExt;
00446 
00447   QString fileName = addSlash( path ) + name + QString( "." ) + ext;
00448 
00449   return fileName;
00450 }
00451 
00456 QString Qtx::tmpDir()
00457 {
00458   const char* tmpdir = ::getenv( "TEMP" );
00459   if ( !tmpdir )
00460     tmpdir = ::getenv ( "TMP" );
00461   if ( !tmpdir )
00462   {
00463 #ifdef WIN32
00464     tmpdir = "C:\\";
00465 #else
00466     tmpdir = "/tmp";
00467 #endif
00468   }
00469   return QString( tmpdir );
00470 }
00471 
00476 bool Qtx::mkDir( const QString& dirPath )
00477 {
00478   return QDir().mkpath( dirPath );
00479 }
00480 
00485 bool Qtx::rmDir( const QString& thePath )
00486 {
00487   QFileInfo fi( thePath );
00488   if ( !fi.exists() )
00489     return true;
00490 
00491   bool stat = true;
00492   if ( fi.isFile() )
00493     stat = QFile::remove( thePath );
00494   else if ( fi.isDir() )
00495   {
00496     QDir aDir( thePath );
00497     QFileInfoList anEntries = aDir.entryInfoList();
00498     for ( QFileInfoList::iterator it = anEntries.begin(); it != anEntries.end(); ++it )
00499     {
00500       QFileInfo inf = *it;
00501       if ( inf.fileName() == "." || inf.fileName() == ".." )
00502         continue;
00503       stat = stat && rmDir( inf.absoluteFilePath() );
00504     }
00505     stat = stat && aDir.rmdir( thePath );
00506   }
00507   return stat;
00508 }
00509 
00516 QString Qtx::addSlash( const QString& path )
00517 {
00518   QString res = path;
00519   if ( !res.isEmpty() && res.at( res.length() - 1 ) != QChar( '/' ) &&
00520        res.at( res.length() - 1 ) != QChar( '\\' ) )
00521   res += QDir::separator();
00522   return res;
00523 }
00524 
00534 bool Qtx::dos2unix( const QString& absName )
00535 {
00536   FILE* src = ::fopen( absName.toLatin1(), "rb" );
00537   if ( !src )
00538     return false;
00539 
00540   /* we'll use temporary file */
00541   char temp[512] = { '\0' };
00542   QString dir = Qtx::dir( absName );
00543   FILE* tgt = ::fopen( strcpy( temp, ::tempnam( dir.toLatin1(), "__x" ) ), "wb" );
00544   if ( !tgt )
00545     return false;
00546 
00547   /* temp -> result of conversion */
00548   const char CR = 0x0d;
00549   const char LF = 0x0a;
00550   bool waitingLF = false;
00551 
00552   while( true )
00553   {
00554     int  outcnt = 0;
00555     char inbuf[512], outbuf[512];
00556 
00557     /* convert buffer */
00558     int nbread = ::fread( inbuf, 1, sizeof( inbuf ), src );
00559     for ( int incnt = 0; incnt < nbread; incnt++  )
00560     {
00561       if ( waitingLF )
00562       {
00563         waitingLF = false;
00564         if ( inbuf[incnt] == LF )
00565           outbuf[outcnt++] = LF;
00566         else
00567           outbuf[outcnt++] = CR;
00568       }
00569       else if ( inbuf[incnt] == CR )
00570         waitingLF = true;
00571       else
00572         outbuf[outcnt++] = inbuf[incnt];
00573     }
00574 
00575     /* check last sym in buffer */
00576     waitingLF = ( inbuf[nbread - 1] == CR );
00577 
00578     /* write converted buffer to temp file */
00579     int nbwri = ::fwrite( outbuf, 1, outcnt, tgt );
00580     if ( nbwri != outcnt )
00581     {
00582       ::fclose( src );
00583                         ::fclose( tgt );
00584       QFile::remove( QString( temp ) );
00585       return false;
00586     }
00587     if ( nbread != sizeof( inbuf ) )
00588       break;              /* converted ok */
00589   }
00590   ::fclose( src );
00591   ::fclose( tgt );
00592 
00593   /* rename temp -> src */
00594   if ( !QFile::remove( absName ) )
00595     return false;
00596 
00597   return QDir().rename( QString( temp ), absName );
00598 }
00599 
00617 QCompleter* Qtx::pathCompleter( const PathType type, const QString& filter )
00618 {
00619   QStringList extList;
00620   QStringList filterList = filter.split( ";;" );
00621   for ( QStringList::const_iterator it = filterList.begin(); it != filterList.end(); ++it )
00622   {
00623     QRegExp rx( "[\\s\\w,;]*\\(?\\*\\.([\\w]+)\\)?[\\d\\s\\w]*" );
00624     int index = 0;
00625     while ( ( index = rx.indexIn( *it, index ) ) != -1 )
00626     {
00627       extList.append( QString( "*.%1" ).arg( rx.cap( 1 ) ) );
00628       index += rx.matchedLength();
00629     }
00630   }
00631 
00632   QDir::Filters filters = 0;
00633   switch ( type )
00634   {
00635   case PT_OpenFile:
00636   case PT_SaveFile:
00637     filters = QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot;
00638     break;
00639   case PT_Directory:
00640     filters = QDir::Drives | QDir::Dirs | QDir::NoDotAndDotDot;
00641     break;
00642   }
00643 
00644   QDirModel* dm = new QDirModel( extList, filters, QDir::Unsorted );
00645   QCompleter* cmp = new QCompleter( dm, 0 );
00646   dm->setParent( cmp );
00647 
00648   return cmp;
00649 }
00650 
00665 QString Qtx::findEnvVar( const QString& str, int& start, int& len )
00666 {
00667   QString varName;
00668   len = 0;
00669 
00670   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_]*)(%[^%]|%$)" );
00671 
00672   int pos = rx.indexIn( str, start );
00673   if ( pos != -1 )
00674   {
00675     int i = 1;
00676     while ( i <= rx.numCaptures() && varName.isEmpty() )
00677     {
00678       QString capStr = rx.cap( i );
00679       if ( !capStr.contains( "%" ) && !capStr.contains( "$" ) )
00680         varName = capStr;
00681       i++;
00682     }
00683 
00684     if ( !varName.isEmpty() )
00685     {
00686       int capIdx = i - 1;
00687       start = rx.pos( capIdx );
00688       int end = start + varName.length();
00689       if ( capIdx > 1 && rx.cap( capIdx - 1 ).contains( QRegExp( "\\$|%" ) ) )
00690         start = rx.pos( capIdx - 1 ) + rx.cap( capIdx - 1 ).indexOf( QRegExp( "\\$|%" ) );
00691       if ( capIdx < rx.numCaptures() && !rx.cap( capIdx - 1 ).isEmpty() )
00692         end++;
00693       len = end - start;
00694     }
00695   }
00696   return varName;
00697 }
00698 
00707 QString Qtx::makeEnvVarSubst( const QString& str, const SubstMode mode )
00708 {
00709   QString res = str;
00710   if ( mode != Never )
00711   {
00712     QMap<QString, int> ignoreMap;
00713 
00714     int start( 0 ), len( 0 );
00715     while ( true )
00716     {
00717       QString envName = findEnvVar( res, start, len );
00718       if ( envName.isNull() )
00719         break;
00720 
00721       QString newStr;
00722       if ( ::getenv( envName.toLatin1() ) || mode == Always )
00723         newStr = QString( ::getenv( envName.toLatin1() ) );
00724 
00725       if ( newStr.isNull() )
00726       {
00727         if ( ignoreMap.contains( envName ) )
00728         {
00729           start += len;
00730           continue;
00731         }
00732         ignoreMap.insert( envName, 0 );
00733       }
00734       res.replace( start, len, newStr );
00735     }
00736 
00737     res.replace( "$$", "$" );
00738     res.replace( "%%", "%" );
00739   }
00740 
00741   return res;
00742 }
00743 
00749 int Qtx::rgbSet( const QColor& c )
00750 {
00751   return rgbSet( c.red(), c.green(), c.blue() );
00752 }
00753 
00761 int Qtx::rgbSet( const int r, const int g, const int b )
00762 {
00763   return ( ( ( 0xff & r ) << 16 ) + ( ( 0xff & g ) << 8 ) + ( 0xff & b ) );
00764 }
00765 
00771 QColor Qtx::rgbSet( const int rgb )
00772 {
00773   int r, g, b;
00774   rgbSet( rgb, r, g, b );
00775   return QColor( r, g, b );
00776 }
00777 
00785 void Qtx::rgbSet( const int rgb, int& r, int& g, int& b )
00786 {
00787   r = ( rgb >> 16 ) & 0xff;
00788   g = ( rgb >> 8 ) & 0xff;
00789   b = rgb & 0xff;
00790 }
00791 
00799 QColor Qtx::scaleColor( const int index, const int min, const int max )
00800 {
00801   static const int HUE[10] = {230, 210, 195, 180, 160, 80, 60, 50, 30, 0};
00802 
00803   int hue = HUE[0];
00804 
00805   if ( min != max )
00806   {
00807     double aPosition = 9.0 * ( index - min ) / ( max - min );
00808     if ( aPosition > 0.0 )
00809     {
00810       if ( aPosition >= 9.0 )
00811         hue = HUE[9];
00812       else
00813       {
00814         int idx = (int)aPosition;
00815         hue = HUE[idx] + int( ( aPosition - idx ) * ( HUE[idx + 1] - HUE[idx] ) );
00816       }
00817     }
00818   }
00819 
00820   return QColor::fromHsv( hue, 255, 255 );
00821 }
00822 
00828 void Qtx::scaleColors( const int num, QColorList& lst )
00829 {
00830   lst.clear();
00831   for ( int i = 0; i < num; i++ )
00832     lst.append( scaleColor( i, 0, num - 1 ) );
00833 }
00834 
00846 QPixmap Qtx::scaleIcon( const QPixmap& icon, const unsigned w, const unsigned h )
00847 {
00848   QPixmap p;
00849   int aw = w, ah = h <= 0 ? w : h;
00850   if ( icon.isNull() || aw <= 0 || ah <= 0 || ( aw == icon.width() && ah == icon.height() ) )
00851     p = icon;
00852   else
00853     p = icon.fromImage( icon.toImage().scaled( aw, ah, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
00854   return p;
00855 }
00856 
00862 QImage Qtx::grayscale( const QImage& img )
00863 {
00864   QImage res = img;
00865 
00866   int colNum = res.numColors();
00867   if ( colNum )
00868   {
00869     for ( int i = 0; i < colNum; i++ )
00870       res.setColor( i, qGray( res.color( i ) ) );
00871   }
00872   else
00873   {
00874     for ( int y = 0; y < res.height(); y++ )
00875     {
00876       for ( int x = 0; x < res.width(); x++ )
00877       {
00878         QRgb pix = res.pixel( x, y );
00879         res.setPixel( x, y, qRgba( qGray( pix ), qGray( pix ), qGray( pix ), qAlpha( pix ) ) );
00880       }
00881     }
00882   }
00883 
00884   return res;
00885 }
00886 
00892 QPixmap Qtx::grayscale( const QPixmap& pix )
00893 {
00894   QPixmap res;
00895   res.fromImage( grayscale( pix.toImage() ) );
00896   return res;
00897 }
00898 
00906 QImage Qtx::transparentImage( const int w, const int h, const int d )
00907 {
00908   QImage::Format fmt;
00909   switch ( d )
00910   {
00911   case 1:
00912     fmt = QImage::Format_Mono;
00913     break;
00914   case 8:
00915     fmt = QImage::Format_Indexed8;
00916     break;
00917   case 16:
00918   case 24:
00919   case 32:
00920   default:
00921     fmt = QImage::Format_ARGB32;
00922     break;
00923   }
00924 
00925   QImage img( w, h, fmt );
00926   if ( !img.isNull() )
00927   {
00928 //    img.setAlphaBuffer( true );
00929     for ( int i = 0; i < img.height(); i++ )
00930       for ( int j = 0; j < img.width(); j++ )
00931         img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) );
00932   }
00933   return img;
00934 }
00935 
00943 QPixmap Qtx::transparentPixmap( const int w, const int h, const int d )
00944 {
00945   QPixmap pix;
00946   QImage img = transparentImage( w, h, d );
00947   if ( !img.isNull() )
00948     pix.fromImage( img );
00949   return pix;
00950 }
00951 
00965 QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPixmap& dest )
00966 {
00967   if ( pix.isNull() )
00968     return dest;
00969 
00970   int width = qMax( pix.width() + x, dest.width() );
00971   int height = qMax( pix.height() + y, dest.height() );
00972 
00973   QPixmap res( width, height );
00974   QImage img = transparentImage( width, height, 32 );
00975 
00976   QPainter p;
00977   p.begin( &res );
00978   p.fillRect( 0, 0, width, height, QBrush( Qt::white ) );
00979 
00980   if ( !dest.isNull() )
00981   {
00982     p.drawPixmap( 0, 0, dest );
00983     QImage temp = dest.toImage();
00984     for ( int i = 0; i < temp.width() && i < img.width(); i++ )
00985     {
00986       for ( int j = 0; j < temp.height() && j < img.height(); j++ )
00987       {
00988         if ( temp.hasAlphaChannel() )
00989           img.setPixel( i, j, temp.pixel( i, j ) );
00990         else
00991         {
00992           QRgb p = temp.pixel( i, j );
00993           img.setPixel( i, j, qRgba( qRed( p ), qGreen( p ), qBlue( p ), 255 ) );
00994         }
00995       }
00996     }
00997   }
00998 
00999   p.drawPixmap( x, y, pix );
01000   QImage temp = pix.toImage();
01001   for ( int c = x; c < temp.width() + x && c < img.width(); c++ )
01002   {
01003     for ( int r = y; r < temp.height() + y && r < img.height(); r++ )
01004     {
01005       if ( qAlpha( temp.pixel( c - x, r - y ) ) > 0 )
01006         img.setPixel( c, r, temp.pixel( c - x, r - y ) );
01007     }
01008   }
01009 
01010   p.end();
01011 
01012   for ( int ai = 0; ai < img.width(); ai++ )
01013   {
01014     for ( int aj = 0; aj < img.height(); aj++ )
01015     {
01016       if ( qAlpha( img.pixel( ai, aj ) ) < 1 )
01017         img.setPixel( ai, aj, qRgba( 255, 255, 255, 255 ) );
01018       else
01019         img.setPixel( ai, aj, qRgba( 0, 0, 0, 0 ) );
01020     }
01021   }
01022 
01023   QBitmap bmp( width, height );
01024   bmp.fromImage( img, Qt::ColorMode_Mask | Qt::ThresholdDither );
01025   res.setMask( bmp );
01026 
01027   return res;
01028 }
01029 
01048 QString Qtx::colorToString( const QColor& color )
01049 {
01050   QString str;
01051   if ( color.isValid() )
01052   {
01053     if ( color.alpha() != 255 )
01054     {
01055       QStringList vals;
01056       vals << QString( "#%1" ).arg( color.red(),   0, 16 );
01057       vals << QString( "#%1" ).arg( color.green(), 0, 16 );
01058       vals << QString( "#%1" ).arg( color.blue(),  0, 16 );
01059       vals << QString( "#%1" ).arg( color.alpha(), 0, 16 );
01060       str = vals.join( "," );
01061     }
01062     else
01063     {
01064       str = color.name();
01065     }
01066   }
01067   return str;
01068 }
01069 
01096 bool Qtx::stringToColor( const QString& str, QColor& color )
01097 {
01098   bool res = true;
01099   QStringList vals = str.split( QRegExp( "[\\s|,]" ), QString::SkipEmptyParts );
01100 
01101   QIntList nums;
01102   for ( QStringList::const_iterator it = vals.begin(); it != vals.end() && res; ++it )
01103   {
01104     int num = 0;
01105     if ( (*it).startsWith( "#" ) )
01106       num = (*it).mid( 1 ).toInt( &res, 16 );
01107     else
01108       num = (*it).toInt( &res, 10 );
01109     if ( res )
01110       nums.append( num );
01111   }
01112 
01113   res = res && nums.count() >= 3;
01114   if ( res )
01115     color.setRgb( nums[0], nums[1], nums[2] );
01116 
01117   if ( !res )
01118   {
01119     int pack = str.toInt( &res );
01120     if ( res )
01121       color = Qtx::rgbSet( pack );
01122   }
01123 
01124   if ( !res )
01125   {
01126     color = QColor( str );
01127     res = color.isValid();
01128   }
01129 
01130   return res;
01131 }
01132 
01154 QString Qtx::biColorToString( const QColor& color, const int delta )
01155 {
01156   return QString("%1|%2").arg( Qtx::colorToString( color ) ).arg( delta );
01157 }
01158 
01181 bool Qtx::stringToBiColor( const QString& str, QColor& color, int& delta )
01182 {
01183   QStringList data = str.split( "|", QString::KeepEmptyParts );
01184   QColor c;
01185   int d = 0;
01186   bool ok = data.count() > 0 && Qtx::stringToColor( data[0], c );
01187   bool dok = false;
01188   if ( data.count() > 1 ) d = data[1].toInt( &dok );
01189   ok = ok && dok;
01190   color = ok ? c : QColor();
01191   delta = ok ? d : 0;
01192   return ok;
01193 }
01194 
01211 QColor Qtx::mainColorToSecondary( const QColor& color, int delta )
01212 {
01213   QColor cs = color;
01214   if ( cs.isValid() ) {
01215     int val = qMin( 255, qMax( cs.value() + delta, 0 ) );
01216     int sat = qMin( 255, qMax( cs.saturation() + delta-(val-cs.value()), 0 ) );
01217 #ifdef BICOLOR_CHANGE_HUE
01218     const int BICOLOR_HUE_MAXDELTA = 40;
01219     int dh = delta-(val-cs.value())-(sat-cs.saturation());
01220     dh = qMin( BICOLOR_HUE_MAXDELTA, qAbs( dh ) ) * ( dh > 0 ? 1 : -1 );
01221     //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-(sat-cs.saturation()), 0 ) );
01222     //int hue = qMin( 359, qMax( cs.hue() + delta-(val-cs.value())-ds, 0 ) );
01223     int hue = cs.hue() + dh;
01224     if ( hue < 0 ) hue = 360 - hue;
01225 #else
01226     int hue = cs.hue();
01227 #endif
01228     cs.setHsv( hue, sat, val );
01229   }
01230   return cs;
01231 }
01232 
01239 QString Qtx::gradientToString( const QLinearGradient& gradient )
01240 {
01241   QStringList data;
01242   data << "linear";
01243   data << QString::number( gradient.start().x() );
01244   data << QString::number( gradient.start().y() );
01245   data << QString::number( gradient.finalStop().x() );
01246   data << QString::number( gradient.finalStop().y() );
01247   switch( gradient.spread() ) 
01248   {
01249   case QGradient::PadSpread:
01250     data << "pad";
01251     break;
01252   case QGradient::RepeatSpread:
01253     data << "repeat";
01254     break;
01255   case QGradient::ReflectSpread:
01256     data << "reflect";
01257     break;
01258   default:
01259     break;
01260   }
01261   QGradientStops stops = gradient.stops();
01262   QGradientStop stop;
01263   foreach ( stop, stops ) 
01264   {
01265     data << QString::number( stop.first );
01266     data << colorToString( stop.second );
01267   }
01268   return data.join( "|" );
01269 }
01270 
01277 QString Qtx::gradientToString( const QRadialGradient& gradient )
01278 {
01279   QStringList data;
01280   data << "radial";
01281   data << QString::number( gradient.center().x() );
01282   data << QString::number( gradient.center().y() );
01283   data << QString::number( gradient.focalPoint().x() );
01284   data << QString::number( gradient.focalPoint().y() );
01285   data << QString::number( gradient.radius() );
01286   switch( gradient.spread() ) 
01287   {
01288   case QGradient::PadSpread:
01289     data << "pad";
01290     break;
01291   case QGradient::RepeatSpread:
01292     data << "repeat";
01293     break;
01294   case QGradient::ReflectSpread:
01295     data << "reflect";
01296     break;
01297   default:
01298     break;
01299   }
01300   QGradientStops stops = gradient.stops();
01301   QGradientStop stop;
01302   foreach ( stop, stops ) 
01303   {
01304     data << QString::number( stop.first );
01305     data << colorToString( stop.second );
01306   }
01307   return data.join( "|" );
01308 }
01309 
01316 QString Qtx::gradientToString( const QConicalGradient& gradient )
01317 {
01318   QStringList data;
01319   data << "conical";
01320   data << QString::number( gradient.center().x() );
01321   data << QString::number( gradient.center().y() );
01322   data << QString::number( gradient.angle() );
01323   switch( gradient.spread() ) 
01324   {
01325   case QGradient::PadSpread:
01326     data << "pad";
01327     break;
01328   case QGradient::RepeatSpread:
01329     data << "repeat";
01330     break;
01331   case QGradient::ReflectSpread:
01332     data << "reflect";
01333     break;
01334   default:
01335     break;
01336   }
01337   QGradientStops stops = gradient.stops();
01338   QGradientStop stop;
01339   foreach ( stop, stops ) 
01340   {
01341     data << QString::number( stop.first );
01342     data << colorToString( stop.second );
01343   }
01344   return data.join( "|" );
01345 }
01346 
01354 bool Qtx::stringToLinearGradient( const QString& str, QLinearGradient& gradient )
01355 {
01356   bool success = false;
01357   QStringList vals = str.split( "|", QString::SkipEmptyParts );
01358   if ( vals.count() > 4 && ( vals[0] == "linear" || vals[0] == "lg" ) )
01359   {
01360     // start and end points 
01361     double x1, y1, x2, y2;
01362     bool bOk1, bOk2, bOk3, bOk4;
01363     x1 = vals[1].toDouble( &bOk1 );
01364     y1 = vals[2].toDouble( &bOk2 );
01365     x2 = vals[3].toDouble( &bOk3 );
01366     y2 = vals[4].toDouble( &bOk4 );
01367     if ( bOk1 && bOk2 && bOk3 && bOk4 )
01368     {
01369       gradient = QLinearGradient( x1, y1, x2, y2 );
01370       // spread type
01371       if ( vals.count() > 5 )
01372       {
01373         QString spread = vals[ 5 ].trimmed().toLower();
01374         if ( spread == "pad" || spread == "0" )
01375           gradient.setSpread( QGradient::PadSpread );
01376         else if ( spread == "repeat" || spread == "2" )
01377           gradient.setSpread( QGradient::RepeatSpread );
01378         else if ( spread == "reflect" || spread == "1" )
01379           gradient.setSpread( QGradient::ReflectSpread );
01380       }
01381       // stop points
01382       QGradientStops stops;
01383       for ( int i = 6; i < vals.count(); i+=2 )
01384       {
01385         bool bOk5, bOk6 = false;
01386         QColor c;
01387         double stop = vals[i].toDouble( &bOk5 );
01388         if ( i+1 < vals.count() )
01389           bOk6 = stringToColor( vals[ i+1 ], c );
01390         if ( bOk5 && stop >= 0.0 && stop <= 1.0 && bOk6 && c.isValid() )
01391           stops.append( QGradientStop( stop, c ) );
01392       }
01393       gradient.setStops( stops );
01394       success = true;
01395     }
01396   }
01397   return success;
01398 }
01399 
01407 bool Qtx::stringToRadialGradient( const QString& str, QRadialGradient& gradient )
01408 {
01409   bool success = false;
01410   QStringList vals = str.split( "|", QString::SkipEmptyParts );
01411   if ( vals.count() > 5 && ( vals[0] == "radial" || vals[0] == "rg" ) )
01412   {
01413     // center, radius and focal point
01414     double cx, cy, r, fx, fy;
01415     bool bOk1, bOk2, bOk3, bOk4, bOk5;
01416     cx = vals[1].toDouble( &bOk1 );
01417     cy = vals[2].toDouble( &bOk2 );
01418     fx = vals[3].toDouble( &bOk4 );
01419     fy = vals[4].toDouble( &bOk5 );
01420     r  = vals[5].toDouble( &bOk3 );
01421     if ( bOk1 && bOk2 && bOk3 && bOk4 && bOk5 )
01422     {
01423       gradient = QRadialGradient( cx, cy, r, fx, fy );
01424       // spread type
01425       if ( vals.count() > 6 )
01426       {
01427         QString spread = vals[ 6 ].trimmed().toLower();
01428         if ( spread == "pad" || spread == "0" )
01429           gradient.setSpread( QGradient::PadSpread );
01430         else if ( spread == "repeat" || spread == "2" )
01431           gradient.setSpread( QGradient::RepeatSpread );
01432         else if ( spread == "reflect" || spread == "1" )
01433           gradient.setSpread( QGradient::ReflectSpread );
01434       }
01435       // stop points
01436       QGradientStops stops;
01437       for ( int i = 7; i < vals.count(); i+=2 )
01438       {
01439         bool bOk7, bOk8 = false;
01440         QColor c;
01441         double stop = vals[i].toDouble( &bOk7 );
01442         if ( i+1 < vals.count() )
01443           bOk8 = stringToColor( vals[ i+1 ], c );
01444         if ( bOk7 && stop >= 0.0 && stop <= 1.0 && bOk8 && c.isValid() )
01445           stops.append( QGradientStop( stop, c ) );
01446       }
01447       gradient.setStops( stops );
01448       success = true;
01449     }
01450   }
01451   return success;
01452 }
01453 
01461 bool Qtx::stringToConicalGradient( const QString& str, QConicalGradient& gradient )
01462 {
01463   bool success = false;
01464   QStringList vals = str.split( "|", QString::SkipEmptyParts );
01465   if ( vals.count() > 3 && ( vals[0] == "conical" || vals[0] == "cg" ) )
01466   {
01467     // center and angle
01468     double cx, cy, a;
01469     bool bOk1, bOk2, bOk3;
01470     cx = vals[1].toDouble( &bOk1 );
01471     cy = vals[2].toDouble( &bOk2 );
01472     a = vals[3].toDouble( &bOk3 );
01473     if ( bOk1 && bOk2 && bOk3 )
01474     {
01475       gradient = QConicalGradient( cx, cy, a );
01476       // spread type
01477       if ( vals.count() > 4 )
01478       {
01479         QString spread = vals[ 4 ].trimmed().toLower();
01480         if ( spread == "pad" || spread == "0" )
01481           gradient.setSpread( QGradient::PadSpread );
01482         else if ( spread == "repeat" || spread == "2" )
01483           gradient.setSpread( QGradient::RepeatSpread );
01484         else if ( spread == "reflect" || spread == "1" )
01485           gradient.setSpread( QGradient::ReflectSpread );
01486       }
01487       // stop points
01488       QGradientStops stops;
01489       for ( int i = 5; i < vals.count(); i+=2 )
01490       {
01491         bool bOk4, bOk5 = false;
01492         QColor c;
01493         double stop = vals[i].toDouble( &bOk4 );
01494         if ( i+1 < vals.count() )
01495           bOk5 = stringToColor( vals[ i+1 ], c );
01496         if ( bOk4 && stop >= 0.0 && stop <= 1.0 && bOk5 && c.isValid() )
01497           stops.append( QGradientStop( stop, c ) );
01498       }
01499       gradient.setStops( stops );
01500       success = true;
01501     }
01502   }
01503   return success;
01504 }
01505 
01527 QString Qtx::backgroundToString( const Qtx::BackgroundData& bgData )
01528 {
01529   const QString dtSep         = ";";
01530   const QString kwSep         = "=";
01531   const QString kwBgType      = "bt";
01532   const QString kwFileName    = "fn";
01533   const QString kwTextureMode = "tm";
01534   const QString kwShowTexture = "ts";
01535   const QString kwFirstColor  = "c1";
01536   const QString kwSecondColor = "c2";
01537   const QString kwGrType      = "gt";
01538   const QString kwGrData      = "gr";
01539 
01540   Qtx::BackgroundMode bgMode       = bgData.mode();
01541   QString             fileName;
01542   Qtx::TextureMode    textureMode  = bgData.texture( fileName );
01543   bool                showTexture  = bgData.isTextureShown();
01544   QColor              c1, c2;
01545   int                 gradientType = bgData.gradient( c1, c2 );
01546   const QGradient*    gradient     = bgData.gradient();
01547   QString             grString;
01548   if ( gradient ) {
01549     switch ( gradient->type() ) {
01550     case QGradient::LinearGradient:
01551       grString = gradientToString( *(static_cast<const QLinearGradient*>( gradient )) );
01552       break;
01553     case QGradient::RadialGradient:
01554       grString = gradientToString( *(static_cast<const QRadialGradient*>( gradient )) );
01555       break;
01556     case QGradient::ConicalGradient:
01557       grString = gradientToString( *(static_cast<const QConicalGradient*>( gradient )) );
01558       break;
01559     default:
01560       break;
01561     }
01562   }
01563   QStringList data;
01564   data << QString( "%1%2%3" ).arg( kwBgType ).arg( kwSep ).arg( (int)bgMode );
01565   data << QString( "%1%2%3" ).arg( kwFileName ).arg( kwSep ).arg( fileName );
01566   data << QString( "%1%2%3" ).arg( kwTextureMode ).arg( kwSep ).arg( (int)textureMode );
01567   data << QString( "%1%2%3" ).arg( kwShowTexture ).arg( kwSep ).arg( showTexture ? "true" : "false" );
01568   data << QString( "%1%2%3" ).arg( kwFirstColor ).arg( kwSep ).arg( Qtx::colorToString( c1 ) );
01569   data << QString( "%1%2%3" ).arg( kwSecondColor ).arg( kwSep ).arg( Qtx::colorToString( c2 ) );
01570   data << QString( "%1%2%3" ).arg( kwGrType ).arg( kwSep ).arg( gradientType );
01571   data << QString( "%1%2%3" ).arg( kwGrData ).arg( kwSep ).arg( grString );
01572 
01573   return data.join( dtSep );
01574 }
01575 
01609 Qtx::BackgroundData Qtx::stringToBackground( const QString& str )
01610 {
01611   const QString dtSep         = ";";
01612   const QString kwSep         = "=";
01613   const QString kwBgType      = "bt";
01614   const QString kwFileName    = "fn";
01615   const QString kwTextureMode = "tm";
01616   const QString kwShowTexture = "ts";
01617   const QString kwFirstColor  = "c1";
01618   const QString kwSecondColor = "c2";
01619   const QString kwGrType      = "gt";
01620   const QString kwGrData      = "gr";
01621 
01622   Qtx::BackgroundData bgData = BackgroundData();
01623 
01624   QStringList data = str.split( dtSep, QString::KeepEmptyParts );
01625   
01626   QColor c;
01627   if ( data.count() == 1 && !data.contains( kwSep ) && stringToColor( data[0], c ) ) {
01628     // solid color mode, for backward compatibility
01629     bgData.setColor( c );
01630   }
01631   else {
01632     QMap<QString, QString> dmap;
01633     // background data
01634     foreach( QString d, data ) {
01635       QStringList items = d.split( kwSep, QString::KeepEmptyParts );
01636       if ( items.count() > 0 ) {
01637        QString kw  = items.takeFirst().trimmed().toLower(); // keyword
01638        QString val = items.join( kwSep ).trimmed(); // if value contains "=" symbol, we have to restore it
01639        dmap[ kw ] = val;
01640       }
01641     }
01642     QString bgMode       = dmap.value( kwBgType,      QString() );
01643     QString fileName     = dmap.value( kwFileName,    QString() );
01644     QString textureMode  = dmap.value( kwTextureMode, QString() );
01645     QString showTexture  = dmap.value( kwShowTexture, QString() );
01646     QString color1       = dmap.value( kwFirstColor,  QString() );
01647     QString color2       = dmap.value( kwSecondColor, QString() );
01648     QString gradientType = dmap.value( kwGrType,      QString() );
01649     QString gradient     = dmap.value( kwGrData,      QString() );
01650     
01651     // texture data
01652     if ( !fileName.isEmpty() || !textureMode.isEmpty() || !showTexture.isEmpty() ) {
01653       Qtx::TextureMode m = (Qtx::TextureMode)( stringToInt( textureMode,        Qtx::CenterTexture, 
01654                                                      Qtx::CenterTexture, Qtx::StretchTexture ) );
01655       bgData.setTexture( fileName, m );
01656       QStringList boolvars; boolvars << "true" << "yes" << "ok" << "1";
01657       if ( boolvars.contains( showTexture.trimmed().toLower() ) )
01658        bgData.setTextureShown( true );
01659     }
01660     QColor c1, c2;
01661     // try color mode
01662     bool ok = Qtx::stringToColor( color1, c1 );
01663     if ( ok ) {
01664       bgData.setColor( c1 );
01665     }
01666     // try simple gradient mode
01667     ok = Qtx::stringToColor( color2, c2 );
01668     if ( ok || !gradientType.isEmpty() ) {
01669       int gt = gradientType.toInt( &ok );
01670       bgData.setGradient( ok ? gt : -1, c1, c2 );
01671     }
01672     // try custom gradient mode
01673     QLinearGradient  lg;
01674     QConicalGradient cg;
01675     QRadialGradient  rg;
01676     ok = Qtx::stringToLinearGradient( gradient, lg );
01677     if ( ok ) {
01678       bgData.setGradient( lg );
01679     }
01680     ok = Qtx::stringToRadialGradient( gradient, rg );
01681     if ( ok ) {
01682       bgData.setGradient( rg );
01683     }
01684     ok = Qtx::stringToConicalGradient( gradient, cg );
01685     if ( ok ) {
01686       bgData.setGradient( cg );
01687     }
01688     
01689     // finally set background mode
01690     Qtx::BackgroundMode m = (Qtx::BackgroundMode)( stringToInt( bgMode,            Qtx::ColorBackground, 
01691                                                         Qtx::NoBackground, Qtx::CustomGradientBackground ) );
01692     bgData.setMode( m );
01693   }
01694 
01695   return bgData;
01696 }
01697 
01723 Qtx::Localizer::Localizer()
01724 {
01725   myCurLocale = setlocale( LC_NUMERIC, 0 );
01726   setlocale( LC_NUMERIC, "C" );
01727 }
01728 
01732 Qtx::Localizer::~Localizer()
01733 {
01734   setlocale( LC_NUMERIC, myCurLocale.toLatin1().constData() );
01735 }
01736 
01776 Qtx::BackgroundData::BackgroundData()
01777   : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
01778 {
01779   setMode( Qtx::NoBackground );
01780 }
01781 
01787 Qtx::BackgroundData::BackgroundData( const QColor& c )
01788   : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
01789 {
01790   setColor( c );
01791 }
01792 
01801 Qtx::BackgroundData::BackgroundData( int type, const QColor& c1, const QColor& c2 )
01802   : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
01803 {
01804   setGradient( type, c1, c2 );
01805 }
01806 
01812 Qtx::BackgroundData::BackgroundData( const QGradient& grad )
01813   : myTextureMode( Qtx::CenterTexture ), myGradientType( -1 ), myTextureShown( false )
01814 {
01815   setGradient( grad );
01816 }
01817 
01821 Qtx::BackgroundData::~BackgroundData()
01822 {
01823 }
01824 
01828 bool Qtx::BackgroundData::operator==( const Qtx::BackgroundData& other ) const
01829 {
01830   return 
01831     ( myMode         == other.myMode )         && 
01832     ( myTextureMode  == other.myTextureMode )  &&
01833     ( myFileName     == other.myFileName )     &&
01834     ( myColors       == other.myColors )       &&
01835     ( myGradientType == other.myGradientType ) &&
01836     ( myGradient     == other.myGradient )     &&
01837     ( myTextureShown == other.myTextureShown );
01838 }
01839 
01845 bool Qtx::BackgroundData::isValid() const
01846 {
01847   return myMode != Qtx::NoBackground;
01848 }
01849 
01855 Qtx::BackgroundMode Qtx::BackgroundData::mode() const
01856 {
01857   return myMode;
01858 }
01859 
01865 void Qtx::BackgroundData::setMode( const Qtx::BackgroundMode m )
01866 {
01867   myMode = m;
01868 }
01869 
01875 Qtx::TextureMode Qtx::BackgroundData::texture( QString& fileName ) const
01876 {
01877   fileName = myFileName;
01878   return myTextureMode;
01879 }
01880 
01891 void Qtx::BackgroundData::setTexture( const QString& fileName, const Qtx::TextureMode m )
01892 {
01893   myFileName = fileName;
01894   myTextureMode = m;
01895 }
01896 
01902 bool Qtx::BackgroundData::isTextureShown() const
01903 {
01904   return myTextureShown;
01905 }
01906 
01912 void Qtx::BackgroundData::setTextureShown( bool on )
01913 {
01914   myTextureShown = on;
01915 }
01916 
01922 QColor Qtx::BackgroundData::color() const
01923 {
01924   return myColors.count() > 0 ? myColors[0] : QColor();
01925 }
01926 
01932 void Qtx::BackgroundData::setColor( const QColor& c )
01933 {
01934   myColors.clear();
01935   myColors << c;
01936   setMode( Qtx::ColorBackground );
01937 }
01938 
01948 int Qtx::BackgroundData::gradient( QColor& c1, QColor& c2 ) const
01949 {
01950   c1 = myColors.count() > 0 ? myColors[0] : QColor();
01951   c2 = myColors.count() > 1 ? myColors[1] : ( myColors.count() > 0 ? myColors[0] : QColor() );
01952   return myGradientType;
01953 }
01954 
01963 void Qtx::BackgroundData::setGradient( int type, const QColor& c1, const QColor& c2 )
01964 {
01965   myColors.clear();
01966   myColors << c1 << c2;
01967   myGradientType = type;
01968   setMode( Qtx::SimpleGradientBackground );
01969 }
01970 
01979 const QGradient* Qtx::BackgroundData::gradient() const
01980 {
01981   return &myGradient;
01982 }
01983 
01989 void Qtx::BackgroundData::setGradient( const QGradient& grad )
01990 {
01991   myGradient = grad;
01992   setMode( Qtx::CustomGradientBackground );
01993 }
01994   
01995 
01996 #ifndef WIN32
01997 
01998 #include <X11/Xlib.h>
01999 #include <GL/glx.h>
02000 
02007 void* Qtx::getDisplay()
02008 {
02009   static Display* pDisplay = NULL;
02010   if ( !pDisplay )
02011     pDisplay = XOpenDisplay( NULL );
02012   return pDisplay;
02013 }
02014 
02021 Qt::HANDLE Qtx::getVisual()
02022 {
02023   Qt::HANDLE res = (Qt::HANDLE)NULL;
02024 
02025   Display* pDisplay = (Display*)getDisplay();
02026   if ( !pDisplay )
02027     return res;
02028 
02029   int errorBase;
02030   int eventBase;
02031 
02032   // Make sure OpenGL's GLX extension supported
02033   if( !glXQueryExtension( pDisplay, &errorBase, &eventBase ) ){
02034     qCritical( "Could not find glx extension" );
02035     return res;
02036   }
02037 
02038   // Find an appropriate visual
02039 
02040   int doubleBufferVisual[]  = {
02041     GLX_RGBA,           // Needs to support OpenGL
02042     GLX_DEPTH_SIZE, 16, // Needs to support a 16 bit depth buffer
02043     GLX_DOUBLEBUFFER,   // Needs to support double-buffering
02044     None                // end of list
02045   };
02046 
02047   // Try for the double-bufferd visual first
02048   XVisualInfo *visualInfo = NULL;
02049   visualInfo = glXChooseVisual( pDisplay, DefaultScreen(pDisplay), doubleBufferVisual );
02050 
02051   if( visualInfo == NULL ){
02052     qCritical( "Could not find matching glx visual" );
02053     return res;
02054   }
02055 
02056   qDebug() << "Picked visual 0x" << hex << XVisualIDFromVisual( visualInfo->visual );
02057   res = (Qt::HANDLE)( visualInfo->visual );
02058  
02059   return res;
02060 }
02061 #endif // WIN32