Skip to content

Commit 4910276

Browse files
committed
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
1 parent b754f07 commit 4910276

File tree

3 files changed

+111
-34
lines changed

3 files changed

+111
-34
lines changed

src/app/qgisapp.cpp

+39-25
Original file line numberDiff line numberDiff line change
@@ -515,20 +515,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
515515
legendLayerSelectionChanged();
516516
activateDeactivateLayerRelatedActions( NULL );
517517

518-
// create the notification widget for macros
519-
mMacrosWarn = QgsMessageBar::createMessage( tr( "Security warning:" ),
520-
tr( "macros have been disabled." ),
521-
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
522-
mInfoBar );
523-
524-
QToolButton *btnEnableMacros = new QToolButton( mMacrosWarn );
525-
btnEnableMacros->setText( tr( "Enable" ) );
526-
btnEnableMacros->setStyleSheet( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" );
527-
btnEnableMacros->setCursor( Qt::PointingHandCursor );
528-
connect( btnEnableMacros, SIGNAL( clicked() ), mInfoBar, SLOT( popWidget() ) );
529-
connect( btnEnableMacros, SIGNAL( clicked() ), this, SLOT( enableProjectMacros() ) );
530-
mMacrosWarn->layout()->addWidget( btnEnableMacros );
531-
532518
addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget );
533519
mUndoWidget->hide();
534520

@@ -3368,8 +3354,24 @@ bool QgisApp::addProject( QString projectFile )
33683354
}
33693355
else if ( enableMacros == 1 ) // ask
33703356
{
3357+
// create the notification widget for macros
3358+
3359+
QWidget *macroMsg = QgsMessageBar::createMessage( tr( "Security warning:" ),
3360+
tr( "project macros have been disabled." ),
3361+
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
3362+
mInfoBar );
3363+
3364+
QToolButton *btnEnableMacros = new QToolButton( macroMsg );
3365+
btnEnableMacros->setText( tr( "Enable macros" ) );
3366+
btnEnableMacros->setStyleSheet( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" );
3367+
btnEnableMacros->setCursor( Qt::PointingHandCursor );
3368+
btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
3369+
connect( btnEnableMacros, SIGNAL( clicked() ), mInfoBar, SLOT( popWidget() ) );
3370+
connect( btnEnableMacros, SIGNAL( clicked() ), this, SLOT( enableProjectMacros() ) );
3371+
macroMsg->layout()->addWidget( btnEnableMacros );
3372+
33713373
// display the macros notification widget
3372-
mInfoBar->pushWidget( mMacrosWarn, 1 );
3374+
mInfoBar->pushWidget( macroMsg, 1 );
33733375
}
33743376
}
33753377
}
@@ -5386,6 +5388,7 @@ void QgisApp::duplicateLayers( QList<QgsMapLayer *> lyrList )
53865388
mMapCanvas->freeze();
53875389
QgsMapLayer *dupLayer;
53885390
QString layerDupName, unSppType;
5391+
QList<QWidget *> msgBars;
53895392

53905393
foreach ( QgsMapLayer * selectedLyr, selectedLyrs )
53915394
{
@@ -5437,19 +5440,23 @@ void QgisApp::duplicateLayers( QList<QgsMapLayer *> lyrList )
54375440

54385441
if ( unSppType.isEmpty() && dupLayer && !dupLayer->isValid() )
54395442
{
5440-
QMessageBox::information( this,
5441-
tr( "Invalid Layer" ),
5442-
tr( "%1\n\nDuplication resulted in invalid layer." ).arg( selectedLyr->name() ) );
5443+
msgBars.append( QgsMessageBar::createMessage(
5444+
tr( "Duplicate layer: " ),
5445+
tr( "%1 (duplication resulted in invalid layer)" ).arg( selectedLyr->name() ) ,
5446+
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
5447+
mInfoBar ) );
54435448
continue;
54445449
}
54455450

54465451
if ( !unSppType.isEmpty() || !dupLayer )
54475452
{
5448-
QMessageBox::information( this,
5449-
tr( "Unsupported Layer" ),
5450-
tr( "%1\n%2\n\nDuplication of layer type is unsupported." )
5451-
.arg( selectedLyr->name() )
5452-
.arg( !unSppType.isEmpty() ? QString( " (" ) + unSppType + QString( ")" ) : "" ) );
5453+
msgBars.append( QgsMessageBar::createMessage(
5454+
tr( "Duplicate layer: " ),
5455+
tr( "%1 (%2type unsupported)" )
5456+
.arg( selectedLyr->name() )
5457+
.arg( !unSppType.isEmpty() ? QString( "'" ) + unSppType + "' " : "" ),
5458+
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
5459+
mInfoBar ) );
54535460
continue;
54545461
}
54555462

@@ -5478,6 +5485,13 @@ void QgisApp::duplicateLayers( QList<QgsMapLayer *> lyrList )
54785485
qApp->processEvents();
54795486

54805487
mMapCanvas->freeze( false );
5488+
5489+
// display errors in message bar after duplication of layers
5490+
foreach ( QWidget * msgBar, msgBars )
5491+
{
5492+
mInfoBar->pushWidget( msgBar, 1 );
5493+
}
5494+
54815495
}
54825496

54835497
void QgisApp::setLayerCRS()
@@ -6096,8 +6110,8 @@ void QgisApp::closeProject()
60966110
QgsPythonRunner::run( "qgis.utils.unloadProjectMacros();" );
60976111
}
60986112

6099-
// remove the warning message from the bar if present
6100-
mInfoBar->popWidget( mMacrosWarn );
6113+
// remove any message widgets from the message bar
6114+
mInfoBar->clearWidgets();
61016115

61026116
mTrustedMacros = false;
61036117

src/gui/qgsmessagebar.cpp

+53-8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <QLabel>
2525
#include <QToolButton>
2626
#include <QGridLayout>
27+
#include <QMenu>
2728

2829

2930
QgsMessageBar::QgsMessageBar( QWidget *parent )
@@ -40,16 +41,34 @@ QgsMessageBar::QgsMessageBar( QWidget *parent )
4041
mLayout->setContentsMargins( 9, 1, 9, 1 );
4142
setLayout( mLayout );
4243

43-
mLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ), 0, 1, 1, 1 );
44+
mItemCount = new QLabel( this );
45+
mItemCount->setObjectName( "mItemCount" );
46+
mItemCount->setToolTip( tr( "Remaining messages" ) );
47+
mItemCount->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
48+
mLayout->addWidget( mItemCount, 0, 1, 1, 1 );
49+
50+
mCloseMenu = new QMenu( this );
51+
mCloseMenu->setObjectName( "mCloseMenu" );
52+
mActionCloseAll = new QAction( tr( "Close all" ), this );
53+
mCloseMenu->addAction( mActionCloseAll );
54+
connect( mActionCloseAll, SIGNAL( triggered() ), this, SLOT( clearWidgets() ) );
4455

4556
mCloseBtn = new QToolButton( this );
4657
mCloseBtn->setToolTip( tr( "Close" ) );
47-
mCloseBtn->setStyleSheet( "QToolButton {background-color: rgba(255, 255, 255, 0);}" );
58+
mCloseBtn->setMinimumWidth( 36 );
59+
mCloseBtn->setStyleSheet(
60+
"QToolButton { background-color: rgba(255, 255, 255, 0); } "
61+
"QToolButton::menu-indicator { subcontrol-position: right bottom; subcontrol-origin: padding; bottom: 6px; }" );
4862
mCloseBtn->setCursor( Qt::PointingHandCursor );
4963
mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.png" ) );
64+
mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
65+
mCloseBtn->setMenu( mCloseMenu );
5066
connect( mCloseBtn, SIGNAL( clicked() ), this, SLOT( popWidget() ) );
5167
mLayout->addWidget( mCloseBtn, 0, 2, 1, 1 );
5268

69+
connect( this, SIGNAL( widgetAdded( QWidget* ) ), this, SLOT( updateItemCount() ) );
70+
connect( this, SIGNAL( widgetRemoved( QWidget* ) ), this, SLOT( updateItemCount() ) );
71+
5372
// start hidden
5473
setVisible( false );
5574
}
@@ -127,6 +146,20 @@ bool QgsMessageBar::popWidget()
127146
return true;
128147
}
129148

149+
bool QgsMessageBar::clearWidgets()
150+
{
151+
if ( !mCurrentItem && mList.empty() )
152+
return true;
153+
154+
while ( mList.count() > 0 )
155+
{
156+
popWidget();
157+
}
158+
popWidget();
159+
160+
return !mCurrentItem && mList.empty();
161+
}
162+
130163
void QgsMessageBar::pushItem( QgsMessageBarItem *item )
131164
{
132165
Q_ASSERT( item );
@@ -150,23 +183,29 @@ void QgsMessageBar::pushItem( QgsMessageBarItem *item )
150183

151184
setStyleSheet( item->styleSheet() );
152185
show();
186+
187+
emit widgetAdded( item->widget() );
153188
}
154189

155190
void QgsMessageBar::pushWidget( QWidget *widget, int level )
156191
{
157192
QString stylesheet;
158193
if ( level >= 2 )
159194
{
160-
stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } QLabel { color: white; }";
195+
stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } "
196+
"QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: white; } ";
161197
}
162198
else if ( level == 1 )
163199
{
164-
stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } QLabel { color: black; }";
200+
stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } "
201+
"QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: black; } ";
165202
}
166203
else if ( level <= 0 )
167204
{
168-
stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } QLabel { color: #2554a1; }";
205+
stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } "
206+
"QLabel#mMsgTitle, QLabel#mMsgText, QLabel#mItemCount { color: #2554a1; } ";
169207
}
208+
stylesheet += "QLabel#mMsgTitle { font-weight: bold; } QLabel#mItemCount { font-style: italic; }";
170209
pushWidget( widget, stylesheet );
171210
}
172211

@@ -198,14 +237,20 @@ QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text
198237
if ( !title.isEmpty() )
199238
{
200239
QLabel *lblTitle = new QLabel( title, widget );
201-
QFont font = lblTitle->font();
202-
font.setBold( true );
203-
lblTitle->setFont( font );
240+
lblTitle->setObjectName( "mMsgTitle" );
204241
layout->addWidget( lblTitle );
205242
}
206243

207244
QLabel *lblText = new QLabel( text, widget );
245+
lblText->setObjectName( "mMsgText" );
246+
lblText->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
247+
lblText->setWordWrap( true );
208248
layout->addWidget( lblText );
209249

210250
return widget;
211251
}
252+
253+
void QgsMessageBar::updateItemCount()
254+
{
255+
mItemCount->setText( mList.count() > 0 ? QString::number( mList.count() ) + QString( " " ) + tr( "more" ) : QString( "" ) );
256+
}

src/gui/qgsmessagebar.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727

2828
class QWidget;
2929
class QGridLayout;
30+
class QMenu;
3031
class QToolButton;
32+
class QLabel;
33+
class QAction;
3134

3235
/** \ingroup gui
3336
* A bar for displaying non-blocking messages to the user.
@@ -65,7 +68,10 @@ class GUI_EXPORT QgsMessageBar: public QFrame
6568
static QWidget* createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent = 0 );
6669

6770
signals:
68-
//! emitted when a widget was removed from the bar
71+
//! emitted when a message widget is added to the bar
72+
void widgetAdded( QWidget *widget );
73+
74+
//! emitted when a message widget was removed from the bar
6975
void widgetRemoved( QWidget *widget );
7076

7177
public slots:
@@ -75,6 +81,11 @@ class GUI_EXPORT QgsMessageBar: public QFrame
7581
*/
7682
bool popWidget();
7783

84+
/*! remove all items from the bar's widget list
85+
* @return true if all items were removed, false otherwise
86+
*/
87+
bool clearWidgets();
88+
7889
private:
7990
class QgsMessageBarItem
8091
{
@@ -99,8 +110,15 @@ class GUI_EXPORT QgsMessageBar: public QFrame
99110

100111
QgsMessageBarItem *mCurrentItem;
101112
QList<QgsMessageBarItem *> mList;
113+
QMenu *mCloseMenu;
102114
QToolButton *mCloseBtn;
103115
QGridLayout *mLayout;
116+
QLabel *mItemCount;
117+
QAction *mActionCloseAll;
118+
119+
private slots:
120+
//! updates count of items in widget list
121+
void updateItemCount();
104122
};
105123

106124
#endif

0 commit comments

Comments
 (0)