QGIS API Documentation  master-28efcda
src/gui/qgsmessagebar.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           qgsmessagebar.cpp  -  description
00003                              -------------------
00004     begin                : June 2012
00005     copyright            : (C) 2012 by Giuseppe Sucameli
00006     email                : sucameli at faunalia dot it
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgsmessagebar.h"
00019 #include "qgsapplication.h"
00020 
00021 #include <QWidget>
00022 #include <QPalette>
00023 #include <QStackedWidget>
00024 #include <QLabel>
00025 #include <QProgressBar>
00026 #include <QToolButton>
00027 #include <QTimer>
00028 #include <QGridLayout>
00029 #include <QMenu>
00030 #include <QMouseEvent>
00031 #include <QTextEdit>
00032 
00033 
00034 QgsMessageBar::QgsMessageBar( QWidget *parent )
00035     : QFrame( parent ), mCurrentItem( NULL )
00036 {
00037   QPalette pal = palette();
00038   pal.setBrush( backgroundRole(), pal.window() );
00039   setPalette( pal );
00040   setAutoFillBackground( true );
00041   setFrameShape( QFrame::StyledPanel );
00042   setFrameShadow( QFrame::Plain );
00043 
00044   mLayout = new QGridLayout( this );
00045   mLayout->setContentsMargins( 9, 1, 9, 1 );
00046   setLayout( mLayout );
00047 
00048   mCountProgress = new QProgressBar( this );
00049   mCountProgress->setObjectName( "mCountProgress" );
00050   mCountStyleSheet = QString( "QProgressBar { border: 1px solid rgba(0, 0, 0, 75%);"
00051                               " border-radius: 2px; background: rgba(0, 0, 0, 0);"
00052                               " image: url(:/images/themes/default/%1) }"
00053                               "QProgressBar::chunk { background-color: rgba(0, 0, 0, 30%); width: 5px; }" );
00054 
00055   mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
00056   mCountProgress->setObjectName( "mCountdown" );
00057   mCountProgress->setFixedSize( 25, 14 );
00058   mCountProgress->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00059   mCountProgress->setTextVisible( false );
00060   mCountProgress->setRange( 0, 5 );
00061   mCountProgress->setHidden( true );
00062   mLayout->addWidget( mCountProgress, 0, 0, 1, 1 );
00063 
00064   mItemCount = new QLabel( this );
00065   mItemCount->setObjectName( "mItemCount" );
00066   mItemCount->setToolTip( tr( "Remaining messages" ) );
00067   mItemCount->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
00068   mLayout->addWidget( mItemCount, 0, 2, 1, 1 );
00069 
00070   mCloseMenu = new QMenu( this );
00071   mCloseMenu->setObjectName( "mCloseMenu" );
00072   mActionCloseAll = new QAction( tr( "Close all" ), this );
00073   mCloseMenu->addAction( mActionCloseAll );
00074   connect( mActionCloseAll, SIGNAL( triggered() ), this, SLOT( clearWidgets() ) );
00075 
00076   mCloseBtn = new QToolButton( this );
00077   mCloseMenu->setObjectName( "mCloseMenu" );
00078   mCloseBtn->setToolTip( tr( "Close" ) );
00079   mCloseBtn->setMinimumWidth( 40 );
00080   mCloseBtn->setStyleSheet(
00081     "QToolButton { background-color: rgba(255, 255, 255, 0); } "
00082     "QToolButton::menu-indicator { subcontrol-position: right bottom; subcontrol-origin: padding; bottom: 2px; }" );
00083   mCloseBtn->setCursor( Qt::PointingHandCursor );
00084   mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.png" ) );
00085   mCloseBtn->setIconSize( QSize( 18, 18 ) );
00086   mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
00087   mCloseBtn->setMenu( mCloseMenu );
00088   connect( mCloseBtn, SIGNAL( clicked() ), this, SLOT( popWidget() ) );
00089   mLayout->addWidget( mCloseBtn, 0, 3, 1, 1 );
00090 
00091   mCountdownTimer = new QTimer( this );
00092   mCountdownTimer->setInterval( 1000 );
00093   connect( mCountdownTimer, SIGNAL( timeout() ), this, SLOT( updateCountdown() ) );
00094 
00095   connect( this, SIGNAL( widgetAdded( QWidget* ) ), this, SLOT( updateItemCount() ) );
00096   connect( this, SIGNAL( widgetRemoved( QWidget* ) ), this, SLOT( updateItemCount() ) );
00097 
00098   // start hidden
00099   setVisible( false );
00100 }
00101 
00102 QgsMessageBar::~QgsMessageBar()
00103 {
00104 }
00105 
00106 void QgsMessageBar::mousePressEvent( QMouseEvent * e )
00107 {
00108   // stop/start mCountdownTimer
00109   QProgressBar *pb = static_cast<QProgressBar *>( childAt( e->pos() ) );
00110   if ( pb && pb->objectName() == QString( "mCountdown" ) && e->button() == Qt::LeftButton )
00111   {
00112     if ( mCountdownTimer->isActive() )
00113     {
00114       mCountdownTimer->stop();
00115       pb->setStyleSheet( mCountStyleSheet.arg( "mIconTimerContinue.png" ) );
00116     }
00117     else
00118     {
00119       mCountdownTimer->start();
00120       pb->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
00121     }
00122   }
00123 }
00124 
00125 void QgsMessageBar::popItem( QgsMessageBarItem *item )
00126 {
00127   Q_ASSERT( item );
00128 
00129   if ( item != mCurrentItem && !mList.contains( item ) )
00130     return;
00131 
00132   if ( item == mCurrentItem )
00133   {
00134     if ( mCurrentItem )
00135     {
00136       mLayout->removeWidget( mCurrentItem->widget() );
00137       mCurrentItem->widget()->hide();
00138       if ( mCurrentItem->widget()->parent() == this )
00139       {
00140         delete mCurrentItem->widget();
00141       }
00142       delete mCurrentItem;
00143       mCurrentItem = 0;
00144     }
00145 
00146     if ( !mList.isEmpty() )
00147     {
00148       pushItem( mList.first() );
00149     }
00150     else
00151     {
00152       hide();
00153     }
00154   }
00155   else
00156   {
00157     mList.removeOne( item );
00158   }
00159 
00160   emit widgetRemoved( item->widget() );
00161 }
00162 
00163 bool QgsMessageBar::popWidget( QWidget *widget )
00164 {
00165   if ( !widget || !mCurrentItem )
00166     return false;
00167 
00168   if ( widget == mCurrentItem->widget() )
00169   {
00170     popItem( mCurrentItem );
00171     return true;
00172   }
00173 
00174   foreach ( QgsMessageBarItem *item, mList )
00175   {
00176     if ( item->widget() == widget )
00177     {
00178       mList.removeOne( item );
00179       if ( item->widget()->parent() == this )
00180       {
00181         delete item->widget();
00182       }
00183       delete item;
00184       return true;
00185     }
00186   }
00187 
00188   return false;
00189 }
00190 
00191 bool QgsMessageBar::popWidget()
00192 {
00193   if ( !mCurrentItem )
00194     return false;
00195 
00196   resetCountdown();
00197 
00198   QgsMessageBarItem *item = mCurrentItem;
00199   popItem( item );
00200 
00201   return true;
00202 }
00203 
00204 bool QgsMessageBar::clearWidgets()
00205 {
00206   if ( !mCurrentItem && mList.empty() )
00207     return true;
00208 
00209   while ( mList.count() > 0 )
00210   {
00211     popWidget();
00212   }
00213   popWidget();
00214 
00215   return !mCurrentItem && mList.empty();
00216 }
00217 
00218 void QgsMessageBar::pushItem( QgsMessageBarItem *item )
00219 {
00220   Q_ASSERT( item );
00221 
00222   if ( item == mCurrentItem )
00223     return;
00224 
00225   if ( mList.contains( item ) )
00226     mList.removeOne( item );
00227 
00228   if ( mCurrentItem )
00229   {
00230     mList.prepend( mCurrentItem );
00231     mLayout->removeWidget( mCurrentItem->widget() );
00232     mCurrentItem->widget()->hide();
00233   }
00234 
00235   mCurrentItem = item;
00236   mLayout->addWidget( item->widget(), 0, 1, 1, 1 );
00237   mCurrentItem->widget()->show();
00238 
00239   if ( item->duration() > 0 )
00240   {
00241     mCountProgress->setRange( 0, item->duration() );
00242     mCountProgress->setValue( item->duration() );
00243     mCountProgress->setVisible( true );
00244     mCountdownTimer->start();
00245   }
00246 
00247   setStyleSheet( item->styleSheet() );
00248   show();
00249 
00250   emit widgetAdded( item->widget() );
00251 }
00252 
00253 void QgsMessageBar::pushWidget( QWidget *widget, MessageLevel level, int duration )
00254 {
00255   resetCountdown();
00256 
00257   QString stylesheet;
00258   if ( level >= CRITICAL )
00259   {
00260     stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } "
00261                  "QLabel,QTextEdit { color: white; } ";
00262   }
00263   else if ( level == WARNING )
00264   {
00265     stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } "
00266                  "QLabel,QTextEdit { color: black; } ";
00267   }
00268   else if ( level <= INFO )
00269   {
00270     stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } "
00271                  "QLabel,QTextEdit { color: #2554a1; } ";
00272   }
00273   stylesheet += "QLabel#mItemCount { font-style: italic; }";
00274   pushWidget( widget, stylesheet, duration );
00275 }
00276 
00277 void QgsMessageBar::pushWidget( QWidget *widget, const QString &styleSheet, int duration )
00278 {
00279   if ( !widget )
00280     return;
00281 
00282   // avoid duplicated widget
00283   popWidget( widget );
00284 
00285   pushItem( new QgsMessageBarItem( widget, styleSheet, duration ) );
00286 }
00287 
00288 QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent )
00289 {
00290   QWidget *widget = new QWidget( parent );
00291 
00292   QHBoxLayout *layout = new QHBoxLayout( widget );
00293   layout->setContentsMargins( 0, 0, 0, 0 );
00294 
00295   if ( !icon.isNull() )
00296   {
00297     QLabel *lblIcon = new QLabel( widget );
00298     lblIcon->setPixmap( icon.pixmap( 24 ) );
00299     layout->addWidget( lblIcon );
00300   }
00301 
00302   QTextEdit *msgText = new QTextEdit( widget );
00303   msgText->setObjectName( "mMsgText" );
00304   QString content = text;
00305   if ( !title.isEmpty() )
00306   {
00307     // add ':' to end of title
00308     QString t = title.trimmed();
00309     if ( !t.endsWith( ":" ) )
00310       t += ": ";
00311     content.prepend( QString( "<b>" ) + t + "</b>" );
00312   }
00313   msgText->setText( content );
00314   msgText->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Maximum );
00315   msgText->setReadOnly( true );
00316   msgText->setFrameShape( QFrame::NoFrame );
00317   // stylesheet set here so Qt-style substitued scrollbar arrows can show within limited height
00318   // adjusts to height of font set in app options
00319   msgText->setStyleSheet( "* { background-color: rgba(0,0,0,0); margin-top: 0.25em; max-height: 1.75em; min-height: 1.75em; } "
00320                           "QScrollBar::add-page,QScrollBar::sub-page,QScrollBar::handle { background-color: rgba(0,0,0,0); color: rgba(0,0,0,0); }" );
00321   layout->addWidget( msgText );
00322 
00323   return widget;
00324 }
00325 
00326 void QgsMessageBar::pushMessage( const QString &title, const QString &text, MessageLevel level, int duration )
00327 {
00328   QString msgIcon( "/mIconInfo.png" );
00329   switch ( level )
00330   {
00331     case QgsMessageBar::CRITICAL:
00332       msgIcon = QString( "/mIconCritical.png" );
00333       break;
00334     case QgsMessageBar::WARNING:
00335       msgIcon = QString( "/mIconWarn.png" );
00336       break;
00337     default:
00338       break;
00339   }
00340 
00341   QWidget *msg = QgsMessageBar::createMessage( title, text, QgsApplication::getThemeIcon( msgIcon ), this );
00342   pushWidget( msg, level, duration );
00343 }
00344 
00345 void QgsMessageBar::updateCountdown()
00346 {
00347   if ( !mCountdownTimer->isActive() )
00348   {
00349     resetCountdown();
00350     return;
00351   }
00352   if ( mCountProgress->value() < 2 )
00353   {
00354     popWidget();
00355   }
00356   else
00357   {
00358     mCountProgress->setValue( mCountProgress->value() - 1 );
00359   }
00360 }
00361 
00362 void QgsMessageBar::resetCountdown()
00363 {
00364   if ( mCountdownTimer->isActive() )
00365     mCountdownTimer->stop();
00366 
00367   mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
00368   mCountProgress->setVisible( false );
00369 }
00370 
00371 void QgsMessageBar::updateItemCount()
00372 {
00373   mItemCount->setText( mList.count() > 0 ? QString::number( mList.count() ) + QString( " " ) + tr( "more" ) : QString( "" ) );
00374 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines