From 4f109a5e657a55066f866324f5514eea8c8bed31 Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 31 May 2007 13:36:37 +0000 Subject: [PATCH] Porting to Qt 4 --- src/Qtx/QtxSplash.cxx | 757 ++++++++++++++++++++++++++++++++---------- src/Qtx/QtxSplash.h | 178 ++++++---- 2 files changed, 688 insertions(+), 247 deletions(-) diff --git a/src/Qtx/QtxSplash.cxx b/src/Qtx/QtxSplash.cxx index d3244efc9..09c8f1d37 100644 --- a/src/Qtx/QtxSplash.cxx +++ b/src/Qtx/QtxSplash.cxx @@ -21,57 +21,156 @@ #include "QtxSplash.h" -#include -#include -#include -#include - -const int _PROGRESS_EVENT = QEvent::User + 10; -const int _PROGRESS_WIDTH = 10; +#include +#include +#include +#include /*! - Class ProgressEvent [ internal ]. + \class ProgressEvent + \internal + \brief Progress change custom event. */ -class ProgressEvent: public QCustomEvent + +class ProgressEvent: public QEvent { public: + /*! + \brief Constructor. + \param msg progress message + \param progress current progress (for example, in %) + */ ProgressEvent( const QString& msg, const int progress = 0 ) - : QCustomEvent( id() ), + : QEvent( (QEvent::Type)id() ), myMessage( msg ), myProgress( progress ) {} - QString message() const { return myMessage; } - int progress() const { return myProgress; } - static int id() { return _PROGRESS_EVENT; } + /*! + \brief Get progress message. + \return message + */ + QString message() const { return myMessage; } + /*! + \brief Get current progress. + \return current progress + */ + int progress() const { return myProgress; } + /*! + \brief Get message identifier. + \return custom message ID + */ + static int id() { return QEvent::User + 10; } private: QString myMessage; int myProgress; }; -// Only one instance of splash screen is allowed +/*! + \class QtxSplash + \brief The QtxSplash widget provides a splash screen that can be shown during application startup.. + + A splash screen is a widget that is usually displayed when an application is being started. + Splash screens are often used for applications that have long start up times to provide + the user with feedback that the application is loading. + + Only one instance of the QtxSplash widget can be created. To access to the splash screen widget, + use static method QtxSplash::splash(), which creates and instance of the QtxSplash widget if + necessary and returns pointer to it. You should not destroy yhis instance - it is done automatically + after application main window is shown. Just use methods finish() to make splash screen wait untill + main window is shown. + + The splash screen appears in the center of the screen. The most common usage is to show a splash + screen before the main widget is displayed on the screen. + For example, + \code + int main(int argc, char *argv[]) + { + QApplication app(argc, argv); + QPixmap pixmap(":/splash.png"); + QtxSplash* splash = QtxsSplash::splash(pixmap); + splash->show(); + app.processEvents(); + ... // do application loading and initialization + MainWindow window; + window.show(); + splash->finish(&window); + return app.exec(); + } + \endcode + + The user can hide the splash screen by clicking on it with the mouse. Since the splash screen is + typically displayed before the event loop has started running, it is necessary to periodically call + QApplication::processEvents() to receive the mouse clicks. + This feature can be switched off by using method setHideOnClick() with \c false parameter. + + It is sometimes useful to update the splash screen with messages and/or progress information, + for example, announcing connections established or modules loaded as the application starts up. + QtxSplash class provides the functionality to show status messages and(or) progress bar. + + \code + QPixmap pixmap(":/splash.png"); + QtxSplash* splash = QtxSplash::splash(pixmap); + splash->setProgress(0, 5); + splash->show(); + app.processEvents(); + // doing first step + splash->message("Step 1"); + splash->ress(1); + qApp->processEvents(); + // ... perform some actions + // doing second step + splash->message("Step 2"); + splash->setProgress(2); + qApp->processEvents(); + // ... perform some actions + ... et cetera + \endcode + + There is a static function QtxSplash::setStatus() which allows to put next status message + and progress with one call. It can substitue two calls: message() and setProgress(). + + QtxSplash class provides alos a lot of functions to set-up its behavior. Set progress + bar width with setProgressWidth() method, its position and direction with setProgressFlags(). + It can be single-colored or gradient-colored. Use setProgressColors() method for this. + You can even set your own gradient scale with QLinearGradient and use it for the progress + bar coloring: setProgressGradient(). + + To change the progress bar and status message transparency, use setOpacity() function. + The methods setTextAlignment(), setTextColor() and setTextColors() can be used to change + the attributes of the status message. +*/ + +//! The only one instance of splash screen QtxSplash* QtxSplash::mySplash = 0; /*! - Construct a splash screen that will display the \a pixmap. + \brief Constructor. + \brief Construct a splash screen that will display the \a pixmap. + \param pixmap splash screen pixmap */ QtxSplash::QtxSplash( const QPixmap& pixmap ) - : QWidget( 0, 0, WStyle_Customize | WStyle_StaysOnTop | WX11BypassWM | WStyle_NoBorder ) -{ - myAlignment = AlignBottom | AlignRight; - myColor = white; - myHideOnClick = false; - myProgress = 0; - myTotal = 0; - myGradientType = Vertical; - myError = 0; - myStartColor = red; - +: QWidget( 0, Qt::SplashScreen ), + myAlignment( Qt::AlignBottom | Qt::AlignRight ), + myColor( Qt::white ), + myHideOnClick( false ), + myProgress( 0 ), + myTotal( 0 ), + myStartColor( Qt::red ), + myGradientType( Vertical ), + myProgressWidth( 10 ), + myProgressFlags( BottomSide | LeftToRight ), + myMargin( 5 ), + myOpacity( 1.0 ), + myError( 0 ), + myGradientUsed( false ) +{ + setAttribute( Qt::WA_DeleteOnClose, true ); setPixmap( pixmap ); } /*! - Destructor. + \brief Destructor. */ QtxSplash::~QtxSplash() { @@ -79,8 +178,13 @@ QtxSplash::~QtxSplash() } /*! - Returns an only instance of splash screen. - If \a px is valid sets this pixmap to the splash screen. + \brief Get the only instance of the splash screen widget. + + If the splash screen widget does not exist yet, it is created with specified + pixmap. Otherwise, pixmap \a px is set to existing widget. + + \param px splash screen pixmap + \return splash screen widget */ QtxSplash* QtxSplash::splash( const QPixmap& px ) { @@ -92,24 +196,32 @@ QtxSplash* QtxSplash::splash( const QPixmap& px ) } /*! - Sends the status message and (optionally) progress to the splash screen. - Can be used, for example, from the progress thread. + \brief Send the status message and (optionally) current progress + to the splash screen. + + This function can be used, for example, from an external thread + which checks the application loading progress. + + \param msg progress status message + \param progress current progress + \sa message(), setProgress() */ -void QtxSplash::setStatus( const QString& msg, - const int progress ) +void QtxSplash::setStatus( const QString& msg, const int progress ) { if ( mySplash ) { QApplication::postEvent( mySplash, new ProgressEvent( msg, progress ) ); - qApp->processEvents(); + QApplication::instance()->processEvents(); } } /*! - Sets error status and shows error message box to the user. + \brief Set error status and show error message box to the user. + \param error error message + \param title message box title + \param code error code */ void QtxSplash::error( const QString& error, const QString& title, const int code ) { - printf("QtxSplash::error: %s\n",error.latin1()); if ( mySplash ) { mySplash->setError( code ); QMessageBox::critical( mySplash, @@ -117,23 +229,42 @@ void QtxSplash::error( const QString& error, const QString& title, const int cod error, tr( "&OK" ) ); } + else { + printf( "QtxSplash::error: %s\n",error.toLatin1().constData() ); + } } /*! - Sets the pixmap that will be used as the splash screen's image to - \a pixmap. + \brief Set the pixmap that will be used as the splash screen's image. + \param pixmap spash screen image pixmap + \sa pixmap() */ void QtxSplash::setPixmap( const QPixmap& pixmap ) { - myPixmap = pixmap; + if ( pixmap.hasAlpha() ) { + QPixmap opaque( pixmap.size() ); + QPainter p( &opaque ); + p.fillRect( 0, 0, pixmap.width(), pixmap.height(), palette().background() ); + p.drawPixmap( 0, 0, pixmap ); + p.end(); + myPixmap = opaque; + } + else { + myPixmap = pixmap; + } QRect r( 0, 0, myPixmap.size().width(), myPixmap.size().height() ); resize( myPixmap.size() ); move( QApplication::desktop()->screenGeometry().center() - r.center() ); - repaint(); + if ( !isVisible() ) + drawContents(); + else + repaint(); } /*! - Returns the pixmap that is used in the splash screen. + \brief Get the pixmap that is used as the splash screen's image. + \return spash screen image pixmap + \sa setPixmap() */ QPixmap QtxSplash::pixmap() const { @@ -141,14 +272,19 @@ QPixmap QtxSplash::pixmap() const } /*! - Sets/clear the 'hide on mouse click' flag. - Default is FALSE. + \brief Set/clear the 'hide on mouse click' flag. + When this flag is set, user can hide the splash screen window by clicking on it with mouse. But for this to work it is necessary to call periodically QApplication::processEvents() in order to allow event loop to process events because usually main application loop is not yet started at that moment. + + By default this flag is set to \c false. + + \param on new flag state + \sa hideOnClick() */ void QtxSplash::setHideOnClick( const bool on ) { @@ -156,7 +292,9 @@ void QtxSplash::setHideOnClick( const bool on ) } /*! - Returns the 'hide on mouse click' flag. + \brief Get the 'hide on mouse click' flag. + \return 'hide on mouse click' flag + \sa setHideOnClick() */ bool QtxSplash::hideOnClick() const { @@ -164,7 +302,9 @@ bool QtxSplash::hideOnClick() const } /*! - Sets total progress steps to \a total. + \brief Set total progress steps to \a total. + \param total total number of progress steps + \sa totalSteps(), setProgress(), progress() */ void QtxSplash::setTotalSteps( const int total ) { @@ -173,8 +313,9 @@ void QtxSplash::setTotalSteps( const int total ) } /*! - Return total progress steps number. - \sa setTotalSteps(), setProgress() + \brief Get total progress steps number. + \return total number of progress steps + \sa setTotalSteps(), setProgress(), progress() */ int QtxSplash::totalSteps() const { @@ -182,17 +323,20 @@ int QtxSplash::totalSteps() const } /*! - Sets progress to \a progress. + \brief Set current progress. + \param progress current progress + \sa progress(), setTotalSteps(), setTotalSteps(), */ void QtxSplash::setProgress( const int progress ) { - myProgress = progress; + myProgress = progress > 0 ? progress : 0; repaint(); } /*! - Return current progress. - \sa setProgress(), setTotalSteps() + \brief Get current progress. + \return current progress + \sa setProgress(), setTotalSteps(), setTotalSteps(), */ int QtxSplash::progress() const { @@ -200,37 +344,129 @@ int QtxSplash::progress() const } /*! - Sets progress to \a progress and total progress steps to \a total. + \brief Set current progress to \a progress and total number of + progress steps to \a total. + \param progress current progress + \param total total number of progress steps */ void QtxSplash::setProgress( const int progress, const int total ) { myTotal = total; - myProgress = progress; + myProgress = progress > 0 ? progress : 0; repaint(); } /*! - Sets progress bar colors to \a startColor and \a endColor. - If the colors differ the gradient color bar is drawed. - If the \a endColor is not valid, \a startColor is used instead. - \a gradientType sets the type of gradient to be used for progress - bar - horizontal or vertical. Default is vertical. + \brief Set margin (a border width). + \param margin new margin width + \sa margin() */ -void QtxSplash::setProgressColors( const QColor& startColor, - const QColor& endColor, - const int gradientType ) +void QtxSplash::setMargin( const int margin ) { - myStartColor = startColor; + myMargin = margin > 0 ? margin : 0; + repaint(); +} + +/*! + \brief Get margin (a border width). + \return current margin width + \sa setMargin() +*/ +int QtxSplash::margin() const +{ + return myMargin; +} + +/*! + \brief Set progress bar width. + \param width new progress bar width + \sa progressWidth() +*/ +void QtxSplash::setProgressWidth( const int width ) +{ + myProgressWidth = width > 0 ? width : 0; + repaint(); +} + +/*! + \brief Get progress bar width. + \return current progress bar width + \sa setProgressWidth() +*/ +int QtxSplash::progressWidth() const +{ + return myProgressWidth; +} + +/*! + \brief Set progress bar position and direction. + + By default, progress bar is displayed at the bottom side and + shows progress from left to right. + + \param flags ORed progress bar flags (QtxSplash::ProgressBarFlags) + \sa progressFlags() +*/ +void QtxSplash::setProgressFlags( const int flags ) +{ + myProgressFlags = flags; + if ( !( myProgressFlags & ( LeftSide | RightSide | TopSide | BottomSide ) ) ) + myProgressFlags |= BottomSide; + if ( !( myProgressFlags & ( LeftToRight | RightToLeft ) ) ) + myProgressFlags |= LeftToRight ; + repaint(); +} + +/*! + \brief Get progress bar flags: position and direction. + \return ORed progress bar flags (QtxSplash::ProgressBarFlags) + \sa setProgressFlags() +*/ +int QtxSplash::progressFlags() const +{ + return myProgressFlags; +} + +/*! + \brief Set progress bar colors. + + If the colors differ the gradient color bar is drawn. + + If the \a endColor is not valid, \a startColor is used instead + (no gradient coloring). + + The parameter \a gradientType defines the type of gradient + to be drawn - horizontal or vertical. Default is vertical. + + Note, that methods setProgressGradient() and setProgresColors() are + alternative. Only the latest used is taken into account. + + \param startColor start gradient color (or mono-color) + \param endColor end gradient color + \param gradientType gradient type (QtxSplash::GradientType) + \sa progressColors(), setProgressGradient() +*/ +void QtxSplash::setProgressColors( const QColor& startColor, + const QColor& endColor, + const GradientType gradientType ) +{ + if ( startColor.isValid() ) + myStartColor = startColor; myEndColor = endColor; myGradientType = gradientType; + myGradientUsed = false; repaint(); } /*! - Return progress colors and gradient type (horizontal or vertical). + \brief Get progress colors and gradient type. + \param startColor start gradient color (or mono-color) + \param endColor end gradient color + \return gradient type (QtxSplash::GradientType) \sa setProgressColors() */ -int QtxSplash::progressColors( QColor& startColor, QColor& endColor ) +QtxSplash::GradientType QtxSplash::progressColors( QColor& startColor, + QColor& endColor ) const { startColor = myStartColor; endColor = myEndColor; @@ -238,8 +474,77 @@ int QtxSplash::progressColors( QColor& startColor, QColor& endColor ) } /*! - Sets message text alignment flags to \a alignment. - Default is AlignBottom | AlignRight. + \brief Set custom progress bar colors. + + The gradient start and final stops are scaled to the actual progress + bar size. For example: + \code + QLinearGradient lg(0.5, 0, 1, 1); + lg.setColorAt(0.2, Qt::blue); + lg.setColorAt(0.6, Qt::red); + lg.setSpread(QGradient::RepeatSpread); + splash->setProgressGradient(lg); + \endcode + The above code creates linear gradient, which sets start stop to the + center of the progress bar; the final stop is always in the end of + the progress bar. The color scale (blue to red) is changed by the + progress bar diagonal. + + Note, that methods setProgressGradient() and setProgresColors() are + alternative. Only the latest used is taken into account. + + \param gradient color gradient to be used for progress bar coloring + \sa progressGradient(), setProgresColors() +*/ +void QtxSplash::setProgressGradient( const QLinearGradient& gradient ) +{ + myGradient = gradient; + myGradientUsed = true; + repaint(); +} + +/*! + \brief Get custom progress bar colors. + \return color gradient used for progress bar coloring + \sa setProgressGradient() +*/ +QLinearGradient QtxSplash::progressGradient() const +{ + return myGradient; +} + +/*! + \brief Set progress bar and status text message opacity. + + The value should be in the range 0.0 to 1.0, where 0.0 is fully + transparent and 1.0 is fully opaque. + + \param opacity new opacity value + \sa opacity() +*/ +void QtxSplash::setOpacity( const double opacity ) +{ + myOpacity = opacity < 0.0 ? 0.0 : ( opacity > 1.0 ? 1.0 : opacity ); + repaint(); +} + +/*! + \brief Get progress bar and status text message opacity. + \return current opacity value + \sa setOpacity() +*/ +double QtxSplash::opacity() const +{ + return myOpacity; +} + +/*! + \brief Set message text alignment flags. + + Default flags are Qt::AlignBottom | Qt::AlignRight. + + \param alignment alignment flags (Qt::Alignment) + \sa textAlignment() */ void QtxSplash::setTextAlignment( const int alignment ) { @@ -248,7 +553,8 @@ void QtxSplash::setTextAlignment( const int alignment ) } /*! - Return message text alignment flags. + \brief Get message text alignment flags. + \return alignment flags (Qt::Alignment) \sa setTextAlignment() */ int QtxSplash::textAlignment() const @@ -257,19 +563,24 @@ int QtxSplash::textAlignment() const } /*! - Sets message text color to \a color. - Default is white. + \brief Set message text color. + + Default message color is white. + + \param color message text color \sa setTextColors() */ void QtxSplash::setTextColor( const QColor& color ) { - myColor = color; + if ( myColor.isValid() ) + myColor = color; myShadowColor = QColor(); repaint(); } /*! - Return message text color. + \brief Get message text color. + \return color message text color \sa setTextColor() */ QColor QtxSplash::textColor() const @@ -278,19 +589,24 @@ QColor QtxSplash::textColor() const } /*! - Sets message text color to \a color and text shadow color to \a shadow. - \sa setTextColor() + \brief Set message text color and text shadow color. + \param color message text color + \param shadow message text shadow color + \sa textColors(), textColor(), setTextColor() */ void QtxSplash::setTextColors( const QColor& color, const QColor& shadow ) { - myColor = color; + if ( myColor.isValid() ) + myColor = color; myShadowColor = shadow; repaint(); } /*! - Return message text color and text shadow color. - \sa setTextColors() + \brief Get message text color and text shadow color. + \param color message text color + \param shadow message text shadow color + \sa setTextColors(), textColor(), setTextColor() */ void QtxSplash::textColors( QColor& color, QColor& shadow ) const { @@ -299,7 +615,8 @@ void QtxSplash::textColors( QColor& color, QColor& shadow ) const } /*! - Returns current status message. + \brief Get current status message. + \return status message */ QString QtxSplash::message() const { @@ -307,8 +624,13 @@ QString QtxSplash::message() const } /*! - Return error code. If no errors were occured returns 0. - Error code can be set by error( QString&, QString, int ). + \brief Get error code. + + This function returns error code, set previoiusly with setError() or + error( QString&, QString, int ) methods. + If no error code has been set, 0 is returned. + + \return last error code */ int QtxSplash::error() const { @@ -316,22 +638,26 @@ int QtxSplash::error() const } /*! - Makes the splash screen wait until the widget \a mainWin is displayed - before calling close() on itself. + \brief Wait until widget \a mainWin is displayed. + + Makes the splash screen wait until the widget \a mainWin is displayed + and then hide and close splash window. + + \param mainWin application main window */ void QtxSplash::finish( QWidget* mainWin ) { if ( mainWin ) { #if defined(Q_WS_X11) - extern void qt_wait_for_window_manager( QWidget* w ); - qt_wait_for_window_manager( mainWin ); + extern void qt_x11_wait_for_window_manager(QWidget *mainWin); + qt_x11_wait_for_window_manager(mainWin); #endif } close(); } /*! - Repaint the splash screen. + \brief Repaint the splash screen. */ void QtxSplash::repaint() { @@ -341,8 +667,11 @@ void QtxSplash::repaint() } /*! - Draws the \a message text onto the splash screen with color \a - color and aligns the text according to the flags in \a alignment. + \brief Set status message for the splash screen and define its color + and aligment flags. + \param msg status message + \param alignment message text alignment flags (Qt::Alignment) + \param color message text color */ void QtxSplash::message( const QString& msg, int alignment, @@ -350,15 +679,15 @@ void QtxSplash::message( const QString& msg, { myMessage = msg; myAlignment = alignment; - myColor = color; + if ( color.isValid() ) + myColor = color; repaint(); } /*! - This is an overloaded member function, provided for convenience. - It behaves essentially like the above function. - Draws the \a message text onto the splash screen with default color - and aligns the text according to the default alignment flags. + \overload + \brief Set status message for the splash screen. + \param msg status message */ void QtxSplash::message( const QString& msg ) { @@ -367,7 +696,7 @@ void QtxSplash::message( const QString& msg ) } /*! - Removes the message being displayed on the splash screen. + \brief Remove the message being displayed on the splash screen. \sa message() */ void QtxSplash::clear() @@ -377,131 +706,201 @@ void QtxSplash::clear() } /*! - Draw the contents of the splash screen using painter \a painter. + \brief Draw the contents of the splash screen. + \param painter painter */ -void QtxSplash::drawContents( QPainter* painter ) +void QtxSplash::drawContents( QPainter* p ) { - QRect r = rect(); + // draw progress bar if ( myTotal > 0 ) { - // draw progress bar outline rectangle - painter->setPen( palette().active().dark() ); - painter->drawLine( r.x()+5, - r.height()-5-_PROGRESS_WIDTH, - r.width()-5, - r.height()-5-_PROGRESS_WIDTH ); - painter->drawLine( r.x()+5, - r.height()-5-_PROGRESS_WIDTH, - r.x()+5, - r.height()-5 ); - painter->setPen( palette().active().light() ); - painter->drawLine( r.x()+5, - r.height()-5, - r.width()-5, - r.height()-5 ); - painter->drawLine( r.width()-5, - r.height()-5-_PROGRESS_WIDTH, - r.width()-5, - r.height()-5 ); - // draw progress bar - if ( myGradientType == Horizontal ) { - int tng = r.width() - r.x() - 11; - int ng = (int) ( 1.0 * tng * ( myProgress > 0 ? myProgress : 0 ) / myTotal ); - int h1, h2, s1, s2, v1, v2; - myStartColor.hsv( &h1, &s1, &v1 ); - myEndColor.isValid() ? myEndColor.hsv( &h2, &s2, &v2 ) : - myStartColor.hsv( &h2, &s2, &v2 ); - for ( int i = 0; i < ng; i++ ) { - painter->setPen( QColor( h1 + ((h2-h1)*i)/(tng-1), - s1 + ((s2-s1)*i)/(tng-1), - v1 + ((v2-v1)*i)/(tng-1), - QColor::Hsv ) ); - painter->drawLine( r.x()+6+i, - r.height()-5-_PROGRESS_WIDTH+1, - r.x()+6+i, - r.height()-6 ); - } - } - else { - int ng = (int) ( 1.0 * (r.width() - r.x() - 11) * ( myProgress > 0 ? myProgress : 0 ) / myTotal ); - int h1, h2, s1, s2, v1, v2; - myStartColor.hsv( &h1, &s1, &v1 ); - myEndColor.isValid() ? myEndColor.hsv( &h2, &s2, &v2 ) : - myStartColor.hsv( &h2, &s2, &v2 ); - for ( int i = 0; i < _PROGRESS_WIDTH-1; i++ ) { - painter->setPen( QColor( h1 + ((h2-h1)*i)/(_PROGRESS_WIDTH-2), - s1 + ((s2-s1)*i)/(_PROGRESS_WIDTH-2), - v1 + ((v2-v1)*i)/(_PROGRESS_WIDTH-2), - QColor::Hsv ) ); - painter->drawLine( r.x()+6, - r.height()-5-_PROGRESS_WIDTH+1+i, - r.x()+6+ng-1, - r.height()-5-_PROGRESS_WIDTH+1+i ); - } - } + p->save(); + drawProgressBar( p ); + p->restore(); } - // draw status + + // draw status message if ( !myMessage.isEmpty() ) { - QFontMetrics f( font() ); - int spacing = f.lineSpacing(); - int shift = myTotal > 0 ? _PROGRESS_WIDTH : _PROGRESS_WIDTH; // : 0 - int i = myMessage.length() - 1; - while( i >= 0 && myMessage[ i-- ] == '\n' ) - shift += spacing; - QRect r1( r.x() + 5, r.y() + 5, r.width() - 10, r.height() - 10 - shift ); - QRect r2 = r1; - if ( myAlignment & Qt::AlignLeft ) r2.setLeft ( r2.left() + 1 ); - if ( myAlignment & Qt::AlignTop ) r2.setTop ( r2.top() + 1 ); - if ( myAlignment & Qt::AlignRight ) r2.setRight ( r2.right() + 1 ); - if ( myAlignment & Qt::AlignBottom ) r2.setBottom( r2.bottom() + 1 ); - if ( myShadowColor.isValid() ) { - painter->setPen( myShadowColor ); - painter->drawText( r2, myAlignment, myMessage ); - } - painter->setPen( myColor ); - painter->drawText( r1, myAlignment, myMessage ); + p->save(); + drawMessage( p ); + p->restore(); } } /*! - Mouse press event. + \brief Process mouse button pressing event. + Hides splash screen if the 'hide on mouse click' flag is set. - \sa setHideOnClick() + + \param me mouse event (not used) + \sa hideOnClick(), setHideOnClick() */ -void QtxSplash::mousePressEvent( QMouseEvent* ) +void QtxSplash::mousePressEvent( QMouseEvent* /*me*/ ) { if ( myHideOnClick ) hide(); } /*! - Processes custom event sent by setStatus() method. + \brief Process custom event sent by setStatus() method. + \param ce custom event \sa setStatus(). */ -void QtxSplash::customEvent( QCustomEvent* ce ) +void QtxSplash::customEvent( QEvent* ce ) { if ( ce->type() == ProgressEvent::id() ) { ProgressEvent* pe = (ProgressEvent*)ce; pe->message().isEmpty() ? clear() : message( pe->message() ); setProgress( pe->progress() ); - qApp->processEvents(); + QApplication::instance()->processEvents(); + } +} + +/*! + \brief Draw progress bar. + \param p painter +*/ +void QtxSplash::drawProgressBar( QPainter* p ) +{ + // get rect, margin, progress bar width + QRect r = rect(); + int m = margin(); + int pw = progressWidth(); + + // calculate drawing rect + // ... first set default position (if none or wrong position is set) + if ( myProgressFlags & BottomSide ) + r = QRect( r.x() + m, r.height() - (m + pw), r.width() - 2 * m, pw ); + else if ( myProgressFlags & TopSide ) + r = QRect( r.x() + m, r.y() + m, r.width() - 2 * m, pw ); + else if ( myProgressFlags & LeftSide ) + r = QRect( r.x() + m, r.y() + m, pw, r.height() - 2 * m ); + else if ( myProgressFlags & RightSide ) + r = QRect( r.width() - (m + pw), r.y() + m, pw, r.height() - 2 * m ); + + QRect cr = r; + if ( myProgressFlags & TopSide || myProgressFlags & BottomSide ) { + cr.setWidth( (int)( r.width() * ( myProgress > 0 ? myProgress : 0 ) / myTotal ) ); + if ( myProgressFlags & RightToLeft ) + cr.translate( r.width() - cr.width(), 0 ); + } + else if ( myProgressFlags & LeftSide || myProgressFlags & RightSide ) { + cr.setHeight( (int)( r.height() * ( myProgress > 0 ? myProgress : 0 ) / myTotal ) ); + if ( myProgressFlags & RightToLeft) + cr.translate( 0, r.height() - cr.height() ); + } + int x1, x2, y1, y2; + if ( myGradientType == Horizontal ) { + x1 = r.left(); x2 = r.right(); y1 = y2 = 0; + } + else { + x1 = x2 = 0; y1 = r.top(); y2 = r.bottom(); + } + QLinearGradient lg; + if ( myGradientUsed ) { + QPointF start = myGradient.start(); + QPointF final = myGradient.finalStop(); + qreal xd = final.x() - start.x(); + qreal yd = final.y() - start.y(); + lg.setStart( xd != 0 ? r.left() + r.width() * start.x() / xd : 0, + yd != 0 ? r.top() + r.height() * start.y() / yd : 0 ); + lg.setFinalStop( xd != 0 ? r.right() : 0, yd != 0 ? r.bottom() : 0 ); + lg.setStops( myGradient.stops() ); + lg.setSpread( myGradient.spread() ); + } + else { + lg.setStart( x1, y1 ); + lg.setFinalStop( x2, y2 ); + lg.setColorAt( 0, myStartColor ); + lg.setColorAt( 1, myEndColor.isValid() ? myEndColor : myStartColor ); } + p->setOpacity( myOpacity ); + p->setClipRect( cr ); + p->fillRect( r, lg ); + p->setClipping( false ); + + // draw progress bar outline rectangle + p->setPen( palette().color( QPalette::Dark ) ); + p->drawLine( r.left(), r.top(), r.right(), r.top() ); + p->drawLine( r.left(), r.top(), r.left(), r.bottom() ); + p->setPen( palette().color( QPalette::Light ) ); + p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); + p->drawLine( r.right(), r.top(), r.right(), r.bottom() ); +} + +/*! + \brief Draw status message. + \param p painter +*/ +void QtxSplash::drawMessage( QPainter* p ) +{ + // get rect, margin, progress bar width + QRect r = rect(); + int m = margin(); + int pw = progressWidth(); + + // calculate drawing rect + QFontMetrics f( font() ); + int spacing = f.lineSpacing(); + // ... base rect + QRect r1( r.x() + m, r.y() + m, r.width() - 2 * m, r.height() - 2 * m ); + r1.setY( r1.y() - f.leading() ); + // ... take into account progress bar + if ( 1 ) { // if ( myTotal > 0 ) : vsr changed: otherwise text is jumping + if ( myProgressFlags & BottomSide ) + r1.setHeight( r1.height() - pw ); + else if ( myProgressFlags & TopSide ) + r1.setY( r1.y() + pw ); + else if ( myProgressFlags & LeftSide ) + r1.setX( r1.x() + pw ); + else if ( myProgressFlags & RightSide ) + r1.setWidth( r1.width() - pw ); + } + + // ... take into account trailing '\n' symbols + int shift = 0; + int i = myMessage.length() - 1; + while( i >= 0 && myMessage[ i-- ] == '\n' ) + shift += spacing; + r1.setHeight( r1.height() - shift ); + + p->setOpacity( myOpacity ); + + // draw shadow status text + if ( myShadowColor.isValid() ) { + QRect r2 = r1; + if ( myAlignment & Qt::AlignLeft ) r2.setLeft ( r2.left() + 1 ); + if ( myAlignment & Qt::AlignTop ) r2.setTop ( r2.top() + 1 ); + if ( myAlignment & Qt::AlignRight ) r2.setRight ( r2.right() + 1 ); + if ( myAlignment & Qt::AlignBottom ) r2.setBottom( r2.bottom() + 1 ); + p->setPen( myShadowColor ); + p->drawText( r2, myAlignment, myMessage ); + } + + // draw foreground status text + p->setPen( myColor ); + p->drawText( r1, myAlignment, myMessage ); } /*! - Draws the splash screen window [ internal ]. + \brief Draw the splash screen window contents. */ void QtxSplash::drawContents() { QPixmap textPix = myPixmap; - QPainter painter( &textPix, this ); + QPainter painter( &textPix ); + painter.initFrom( this ); drawContents( &painter ); - setErasePixmap( textPix ); + QPalette pal = palette(); + pal.setBrush( backgroundRole(), QBrush( textPix ) ); + setPalette( pal ); } /*! - Sets error code [ internal ]. + \brief Sets error code. + \param code error code */ void QtxSplash::setError( const int code ) { myError = code; } + diff --git a/src/Qtx/QtxSplash.h b/src/Qtx/QtxSplash.h index b6ade167c..4fe766991 100644 --- a/src/Qtx/QtxSplash.h +++ b/src/Qtx/QtxSplash.h @@ -24,8 +24,9 @@ #include "Qtx.h" -#include -#include +#include +#include +#include #ifdef WIN32 #pragma warning( disable:4251 ) @@ -33,82 +34,123 @@ class QTX_EXPORT QtxSplash : public QWidget { - Q_OBJECT + Q_OBJECT private: - QtxSplash( const QPixmap& = QPixmap() ); + QtxSplash( const QPixmap& ); public: - enum { Horizontal, Vertical }; - - virtual ~QtxSplash(); - - static QtxSplash* splash( const QPixmap& = QPixmap() ); - static void setStatus( const QString&, const int = 0 ); - static void error( const QString&, const QString& = QString::null, const int = -1 ); - - void setPixmap( const QPixmap& ); - QPixmap pixmap() const; - - void setHideOnClick( const bool ); - bool hideOnClick() const; - - void setTotalSteps( const int ); - int totalSteps() const; - void setProgress( const int ); - int progress() const; - void setProgress( const int, const int ); - void setProgressColors( const QColor&, - const QColor& = QColor(), - const int = Vertical ); - int progressColors( QColor&, QColor& ); - - void setTextAlignment( const int ); - int textAlignment() const; - - void setTextColor( const QColor& ); - QColor textColor() const; - void setTextColors( const QColor&, const QColor& = QColor() ); - void textColors( QColor&, QColor& ) const; - - QString message() const; - - int error() const; - - void finish( QWidget* ); - void repaint(); - + //! Gradient type + typedef enum { + Horizontal, //!< horizontal + Vertical //!< vertical + } GradientType; + + //! Progress bar position and direction + typedef enum { + LeftSide = 0x0001, //!< progress bar is displayed at the left side + RightSide = 0x0002, //!< progress bar is displayed at the right side + TopSide = 0x0004, //!< progress bar is displayed at the top side + BottomSide = 0x0008, //!< progress bar is displayed at the bottom side + LeftToRight = 0x0010, //!< show progress from left to right (from top to bottom) + RightToLeft = 0x0020 //!< show progress from right to left (from bottom to top) + } ProgressBarFlags; + + virtual ~QtxSplash(); + + static QtxSplash* splash( const QPixmap& = QPixmap() ); + + static void setStatus( const QString&, const int = 0 ); + static void error( const QString&, const QString& = QString::null, const int = -1 ); + + void setPixmap( const QPixmap& ); + QPixmap pixmap() const; + + void setHideOnClick( const bool ); + bool hideOnClick() const; + + void setTotalSteps( const int ); + int totalSteps() const; + + void setProgress( const int ); + void setProgress( const int, const int ); + int progress() const; + + void setMargin( const int ); + int margin() const; + + void setProgressWidth( const int ); + int progressWidth() const; + + void setProgressFlags( const int ); + int progressFlags() const; + + void setProgressColors( const QColor&, + const QColor& = QColor(), + const GradientType = Vertical ); + GradientType progressColors( QColor&, QColor& ) const; + + void setProgressGradient( const QLinearGradient& ); + QLinearGradient progressGradient() const; + + void setOpacity( const double ); + double opacity() const; + + void setTextAlignment( const int ); + int textAlignment() const; + + void setTextColor( const QColor& ); + QColor textColor() const; + void setTextColors( const QColor&, const QColor& = QColor() ); + void textColors( QColor&, QColor& ) const; + + QString message() const; + + int error() const; + + void finish( QWidget* ); + void repaint(); + public slots: - void message( const QString&, - const int, - const QColor& = white ); - void message( const QString& ); - void clear(); - + void message( const QString&, + const int, + const QColor& = QColor() ); + void message( const QString& ); + void clear(); + protected: - virtual void mousePressEvent( QMouseEvent* ); - virtual void customEvent( QCustomEvent* ); - virtual void drawContents( QPainter* ); + virtual void mousePressEvent( QMouseEvent* ); + virtual void customEvent( QEvent* ); + virtual void drawContents( QPainter* ); + + virtual void drawProgressBar( QPainter* ); + virtual void drawMessage( QPainter* ); private: - void drawContents(); - void setError( const int ); + void drawContents(); + void setError( const int ); private: - static QtxSplash* mySplash; - - QPixmap myPixmap; - QString myMessage; - int myAlignment; - QColor myColor; - QColor myShadowColor; - bool myHideOnClick; - int myProgress; - int myTotal; - QColor myStartColor; - QColor myEndColor; - int myGradientType; - int myError; + static QtxSplash* mySplash; + + QPixmap myPixmap; //!< splash pixmap + QString myMessage; //!< current status message + int myAlignment; //!< text alignment flags (Qt::Alignment) + QColor myColor; //!< text color + QColor myShadowColor; //!< text shadow color + bool myHideOnClick; //!< 'hide on click' flag + int myProgress; //!< current progress + int myTotal; //!< total progress steps + QColor myStartColor; //!< progress bar gradient starting color + QColor myEndColor; //!< progress bar gradient ending color + GradientType myGradientType; //!< progress bar gradient direction + QLinearGradient myGradient; //!< progress bar custom gradient + int myProgressWidth; //!< progress bar width + int myProgressFlags; //!< progress bar flags (QtxSplash::ProgressBarFlags) + int myMargin; //!< margin (for progress bar and status message) + double myOpacity; //!< progress bar / status message opacity + int myError; //!< error code + bool myGradientUsed; //!< 'use custom gradient color scale' flag }; #endif -- 2.39.2