From 4910276930a3c3ca684c684c653cef571a6dc2c3 Mon Sep 17 00:00:00 2001 From: Larry Shaffer Date: Mon, 5 Nov 2012 18:41:24 -0700 Subject: [PATCH] Update to QgsMessageBar and duplicateLayers() - Move project macros message into project open method (as app property, partially showed behind later messages) - Support for multi-line messages that also wrap at with canvas window width - Update text stylesheets to handle all text styling - Show count of remaining queued messages - Add popup menu to Close button with action to optionally close all messages at once - Add slot to clear all widgets, called on project close - Update QgisApp::duplicateLayers() to use QgsMessageBar instead of popup dialogs --- src/app/qgisapp.cpp | 64 ++++++++++++++++++++++++--------------- src/gui/qgsmessagebar.cpp | 61 ++++++++++++++++++++++++++++++++----- src/gui/qgsmessagebar.h | 20 +++++++++++- 3 files changed, 111 insertions(+), 34 deletions(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 02cc658115a8..286b4c9b9576 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -515,20 +515,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent, legendLayerSelectionChanged(); activateDeactivateLayerRelatedActions( NULL ); - // create the notification widget for macros - mMacrosWarn = QgsMessageBar::createMessage( tr( "Security warning:" ), - tr( "macros have been disabled." ), - QgsApplication::getThemeIcon( "/mIconWarn.png" ), - mInfoBar ); - - QToolButton *btnEnableMacros = new QToolButton( mMacrosWarn ); - btnEnableMacros->setText( tr( "Enable" ) ); - btnEnableMacros->setStyleSheet( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ); - btnEnableMacros->setCursor( Qt::PointingHandCursor ); - connect( btnEnableMacros, SIGNAL( clicked() ), mInfoBar, SLOT( popWidget() ) ); - connect( btnEnableMacros, SIGNAL( clicked() ), this, SLOT( enableProjectMacros() ) ); - mMacrosWarn->layout()->addWidget( btnEnableMacros ); - addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget ); mUndoWidget->hide(); @@ -3368,8 +3354,24 @@ bool QgisApp::addProject( QString projectFile ) } else if ( enableMacros == 1 ) // ask { + // create the notification widget for macros + + QWidget *macroMsg = QgsMessageBar::createMessage( tr( "Security warning:" ), + tr( "project macros have been disabled." ), + QgsApplication::getThemeIcon( "/mIconWarn.png" ), + mInfoBar ); + + QToolButton *btnEnableMacros = new QToolButton( macroMsg ); + btnEnableMacros->setText( tr( "Enable macros" ) ); + btnEnableMacros->setStyleSheet( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ); + btnEnableMacros->setCursor( Qt::PointingHandCursor ); + btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ); + connect( btnEnableMacros, SIGNAL( clicked() ), mInfoBar, SLOT( popWidget() ) ); + connect( btnEnableMacros, SIGNAL( clicked() ), this, SLOT( enableProjectMacros() ) ); + macroMsg->layout()->addWidget( btnEnableMacros ); + // display the macros notification widget - mInfoBar->pushWidget( mMacrosWarn, 1 ); + mInfoBar->pushWidget( macroMsg, 1 ); } } } @@ -5386,6 +5388,7 @@ void QgisApp::duplicateLayers( QList lyrList ) mMapCanvas->freeze(); QgsMapLayer *dupLayer; QString layerDupName, unSppType; + QList msgBars; foreach ( QgsMapLayer * selectedLyr, selectedLyrs ) { @@ -5437,19 +5440,23 @@ void QgisApp::duplicateLayers( QList lyrList ) if ( unSppType.isEmpty() && dupLayer && !dupLayer->isValid() ) { - QMessageBox::information( this, - tr( "Invalid Layer" ), - tr( "%1\n\nDuplication resulted in invalid layer." ).arg( selectedLyr->name() ) ); + msgBars.append( QgsMessageBar::createMessage( + tr( "Duplicate layer: " ), + tr( "%1 (duplication resulted in invalid layer)" ).arg( selectedLyr->name() ) , + QgsApplication::getThemeIcon( "/mIconWarn.png" ), + mInfoBar ) ); continue; } if ( !unSppType.isEmpty() || !dupLayer ) { - QMessageBox::information( this, - tr( "Unsupported Layer" ), - tr( "%1\n%2\n\nDuplication of layer type is unsupported." ) - .arg( selectedLyr->name() ) - .arg( !unSppType.isEmpty() ? QString( " (" ) + unSppType + QString( ")" ) : "" ) ); + msgBars.append( QgsMessageBar::createMessage( + tr( "Duplicate layer: " ), + tr( "%1 (%2type unsupported)" ) + .arg( selectedLyr->name() ) + .arg( !unSppType.isEmpty() ? QString( "'" ) + unSppType + "' " : "" ), + QgsApplication::getThemeIcon( "/mIconWarn.png" ), + mInfoBar ) ); continue; } @@ -5478,6 +5485,13 @@ void QgisApp::duplicateLayers( QList lyrList ) qApp->processEvents(); mMapCanvas->freeze( false ); + + // display errors in message bar after duplication of layers + foreach ( QWidget * msgBar, msgBars ) + { + mInfoBar->pushWidget( msgBar, 1 ); + } + } void QgisApp::setLayerCRS() @@ -6096,8 +6110,8 @@ void QgisApp::closeProject() QgsPythonRunner::run( "qgis.utils.unloadProjectMacros();" ); } - // remove the warning message from the bar if present - mInfoBar->popWidget( mMacrosWarn ); + // remove any message widgets from the message bar + mInfoBar->clearWidgets(); mTrustedMacros = false; diff --git a/src/gui/qgsmessagebar.cpp b/src/gui/qgsmessagebar.cpp index 313d27d6c84d..5e399c957823 100644 --- a/src/gui/qgsmessagebar.cpp +++ b/src/gui/qgsmessagebar.cpp @@ -24,6 +24,7 @@ #include #include #include +#include QgsMessageBar::QgsMessageBar( QWidget *parent ) @@ -40,16 +41,34 @@ QgsMessageBar::QgsMessageBar( QWidget *parent ) mLayout->setContentsMargins( 9, 1, 9, 1 ); setLayout( mLayout ); - mLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ), 0, 1, 1, 1 ); + mItemCount = new QLabel( this ); + mItemCount->setObjectName( "mItemCount" ); + mItemCount->setToolTip( tr( "Remaining messages" ) ); + mItemCount->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ); + mLayout->addWidget( mItemCount, 0, 1, 1, 1 ); + + mCloseMenu = new QMenu( this ); + mCloseMenu->setObjectName( "mCloseMenu" ); + mActionCloseAll = new QAction( tr( "Close all" ), this ); + mCloseMenu->addAction( mActionCloseAll ); + connect( mActionCloseAll, SIGNAL( triggered() ), this, SLOT( clearWidgets() ) ); mCloseBtn = new QToolButton( this ); mCloseBtn->setToolTip( tr( "Close" ) ); - mCloseBtn->setStyleSheet( "QToolButton {background-color: rgba(255, 255, 255, 0);}" ); + mCloseBtn->setMinimumWidth( 36 ); + mCloseBtn->setStyleSheet( + "QToolButton { background-color: rgba(255, 255, 255, 0); } " + "QToolButton::menu-indicator { subcontrol-position: right bottom; subcontrol-origin: padding; bottom: 6px; }" ); mCloseBtn->setCursor( Qt::PointingHandCursor ); mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.png" ) ); + mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ); + mCloseBtn->setMenu( mCloseMenu ); connect( mCloseBtn, SIGNAL( clicked() ), this, SLOT( popWidget() ) ); mLayout->addWidget( mCloseBtn, 0, 2, 1, 1 ); + connect( this, SIGNAL( widgetAdded( QWidget* ) ), this, SLOT( updateItemCount() ) ); + connect( this, SIGNAL( widgetRemoved( QWidget* ) ), this, SLOT( updateItemCount() ) ); + // start hidden setVisible( false ); } @@ -127,6 +146,20 @@ bool QgsMessageBar::popWidget() return true; } +bool QgsMessageBar::clearWidgets() +{ + if ( !mCurrentItem && mList.empty() ) + return true; + + while ( mList.count() > 0 ) + { + popWidget(); + } + popWidget(); + + return !mCurrentItem && mList.empty(); +} + void QgsMessageBar::pushItem( QgsMessageBarItem *item ) { Q_ASSERT( item ); @@ -150,6 +183,8 @@ void QgsMessageBar::pushItem( QgsMessageBarItem *item ) setStyleSheet( item->styleSheet() ); show(); + + emit widgetAdded( item->widget() ); } void QgsMessageBar::pushWidget( QWidget *widget, int level ) @@ -157,16 +192,20 @@ void QgsMessageBar::pushWidget( QWidget *widget, int level ) QString stylesheet; if ( level >= 2 ) { - stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } QLabel { color: white; }"; + stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } " + "QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: white; } "; } else if ( level == 1 ) { - stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } QLabel { color: black; }"; + stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } " + "QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: black; } "; } else if ( level <= 0 ) { - stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } QLabel { color: #2554a1; }"; + stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } " + "QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: #2554a1; } "; } + stylesheet += "QLabel#mMsgTitle { font-weight: bold; } QLabel#mItemCount { font-style: italic; }"; pushWidget( widget, stylesheet ); } @@ -198,14 +237,20 @@ QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text if ( !title.isEmpty() ) { QLabel *lblTitle = new QLabel( title, widget ); - QFont font = lblTitle->font(); - font.setBold( true ); - lblTitle->setFont( font ); + lblTitle->setObjectName( "mMsgTitle" ); layout->addWidget( lblTitle ); } QLabel *lblText = new QLabel( text, widget ); + lblText->setObjectName( "mMsgText" ); + lblText->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); + lblText->setWordWrap( true ); layout->addWidget( lblText ); return widget; } + +void QgsMessageBar::updateItemCount() +{ + mItemCount->setText( mList.count() > 0 ? QString::number( mList.count() ) + QString( " " ) + tr( "more" ) : QString( "" ) ); +} diff --git a/src/gui/qgsmessagebar.h b/src/gui/qgsmessagebar.h index 670682cc5a14..bc9a0c9661f9 100644 --- a/src/gui/qgsmessagebar.h +++ b/src/gui/qgsmessagebar.h @@ -27,7 +27,10 @@ class QWidget; class QGridLayout; +class QMenu; class QToolButton; +class QLabel; +class QAction; /** \ingroup gui * A bar for displaying non-blocking messages to the user. @@ -65,7 +68,10 @@ class GUI_EXPORT QgsMessageBar: public QFrame static QWidget* createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent = 0 ); signals: - //! emitted when a widget was removed from the bar + //! emitted when a message widget is added to the bar + void widgetAdded( QWidget *widget ); + + //! emitted when a message widget was removed from the bar void widgetRemoved( QWidget *widget ); public slots: @@ -75,6 +81,11 @@ class GUI_EXPORT QgsMessageBar: public QFrame */ bool popWidget(); + /*! remove all items from the bar's widget list + * @return true if all items were removed, false otherwise + */ + bool clearWidgets(); + private: class QgsMessageBarItem { @@ -99,8 +110,15 @@ class GUI_EXPORT QgsMessageBar: public QFrame QgsMessageBarItem *mCurrentItem; QList mList; + QMenu *mCloseMenu; QToolButton *mCloseBtn; QGridLayout *mLayout; + QLabel *mItemCount; + QAction *mActionCloseAll; + + private slots: + //! updates count of items in widget list + void updateItemCount(); }; #endif