QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsmessagebar.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmessagebar.cpp - description
3  -------------------
4  begin : June 2012
5  copyright : (C) 2012 by Giuseppe Sucameli
6  email : sucameli at faunalia dot it
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsmessagebar.h"
19 #include "qgsmessagebaritem.h"
20 #include "qgsapplication.h"
21 
22 #include <QWidget>
23 #include <QPalette>
24 #include <QStackedWidget>
25 #include <QProgressBar>
26 #include <QToolButton>
27 #include <QTimer>
28 #include <QGridLayout>
29 #include <QMenu>
30 #include <QMouseEvent>
31 #include <QLabel>
32 
34  : QFrame( parent ), mCurrentItem( NULL )
35 {
36  QPalette pal = palette();
37  pal.setBrush( backgroundRole(), pal.window() );
38  setPalette( pal );
39  setAutoFillBackground( true );
40  setFrameShape( QFrame::StyledPanel );
41  setFrameShadow( QFrame::Plain );
42 
43  mLayout = new QGridLayout( this );
44  mLayout->setContentsMargins( 9, 1, 9, 1 );
45  setLayout( mLayout );
46 
47  mCountProgress = new QProgressBar( this );
48  mCountStyleSheet = QString( "QProgressBar { border: 1px solid rgba(0, 0, 0, 75%);"
49  " border-radius: 2px; background: rgba(0, 0, 0, 0);"
50  " image: url(:/images/themes/default/%1) }"
51  "QProgressBar::chunk { background-color: rgba(0, 0, 0, 30%); width: 5px; }" );
52 
53  mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
54  mCountProgress->setObjectName( "mCountdown" );
55  mCountProgress->setFixedSize( 25, 14 );
56  mCountProgress->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
57  mCountProgress->setTextVisible( false );
58  mCountProgress->setRange( 0, 5 );
59  mCountProgress->setHidden( true );
60  mLayout->addWidget( mCountProgress, 0, 0, 1, 1 );
61 
62  mItemCount = new QLabel( this );
63  mItemCount->setObjectName( "mItemCount" );
64  mItemCount->setToolTip( tr( "Remaining messages" ) );
65  mItemCount->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
66  mLayout->addWidget( mItemCount, 0, 2, 1, 1 );
67 
68  mCloseMenu = new QMenu( this );
69  mCloseMenu->setObjectName( "mCloseMenu" );
70  mActionCloseAll = new QAction( tr( "Close all" ), this );
71  mCloseMenu->addAction( mActionCloseAll );
72  connect( mActionCloseAll, SIGNAL( triggered() ), this, SLOT( clearWidgets() ) );
73 
74  mCloseBtn = new QToolButton( this );
75  mCloseMenu->setObjectName( "mCloseMenu" );
76  mCloseBtn->setToolTip( tr( "Close" ) );
77  mCloseBtn->setMinimumWidth( 40 );
78  mCloseBtn->setStyleSheet(
79  "QToolButton { background-color: rgba(0, 0, 0, 0); }"
80  "QToolButton::menu-button { background-color: rgba(0, 0, 0, 0); }" );
81  mCloseBtn->setCursor( Qt::PointingHandCursor );
82  mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.png" ) );
83  mCloseBtn->setIconSize( QSize( 18, 18 ) );
84  mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
85  mCloseBtn->setMenu( mCloseMenu );
86  mCloseBtn->setPopupMode( QToolButton::MenuButtonPopup );
87  connect( mCloseBtn, SIGNAL( clicked() ), this, SLOT( popWidget() ) );
88  mLayout->addWidget( mCloseBtn, 0, 3, 1, 1 );
89 
90  mCountdownTimer = new QTimer( this );
91  mCountdownTimer->setInterval( 1000 );
92  connect( mCountdownTimer, SIGNAL( timeout() ), this, SLOT( updateCountdown() ) );
93 
94  connect( this, SIGNAL( widgetAdded( QgsMessageBarItem* ) ), this, SLOT( updateItemCount() ) );
95  connect( this, SIGNAL( widgetRemoved( QgsMessageBarItem* ) ), this, SLOT( updateItemCount() ) );
96 
97  // start hidden
98  setVisible( false );
99 }
100 
102 {
103 }
104 
106 {
107  if ( mCountProgress == childAt( e->pos() ) && e->button() == Qt::LeftButton )
108  {
109  if ( mCountdownTimer->isActive() )
110  {
111  mCountdownTimer->stop();
112  mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerContinue.png" ) );
113  }
114  else
115  {
116  mCountdownTimer->start();
117  mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
118  }
119  }
120 }
121 
122 void QgsMessageBar::popItem( QgsMessageBarItem *item )
123 {
124  Q_ASSERT( item );
125 
126  if ( item != mCurrentItem && !mItems.contains( item ) )
127  return;
128 
129  if ( item == mCurrentItem )
130  {
131  if ( mCurrentItem )
132  {
133  QWidget *widget = dynamic_cast<QWidget*>( mCurrentItem );
134  mLayout->removeWidget( widget );
135  mCurrentItem->hide();
136  disconnect( mCurrentItem, SIGNAL( styleChanged( QString ) ), this, SLOT( setStyleSheet( QString ) ) );
137  delete mCurrentItem;
138  mCurrentItem = 0;
139  }
140 
141  if ( !mItems.isEmpty() )
142  {
143  showItem( mItems.first() );
144  }
145  else
146  {
147  hide();
148  }
149  }
150  else
151  {
152  mItems.removeOne( item );
153  }
154 
155  emit widgetRemoved( item );
156 }
157 
159 {
160  if ( !item || !mCurrentItem )
161  return false;
162 
163  if ( item == mCurrentItem )
164  {
165  popItem( mCurrentItem );
166  return true;
167  }
168 
169  foreach ( QgsMessageBarItem *existingItem, mItems )
170  {
171  if ( existingItem == item )
172  {
173  mItems.removeOne( existingItem );
174  delete existingItem;
175  return true;
176  }
177  }
178 
179  return false;
180 }
181 
183 {
184  if ( !mCurrentItem )
185  return false;
186 
187  resetCountdown();
188 
189  QgsMessageBarItem *item = mCurrentItem;
190  popItem( item );
191 
192  return true;
193 }
194 
196 {
197  if ( !mCurrentItem && mItems.empty() )
198  return true;
199 
200  while ( mItems.count() > 0 )
201  {
202  popWidget();
203  }
204  popWidget();
205 
206  return !mCurrentItem && mItems.empty();
207 }
208 
209 void QgsMessageBar::pushSuccess( const QString& title, const QString& message )
210 {
211  pushMessage( title, message, SUCCESS );
212 }
213 
214 void QgsMessageBar::pushInfo( const QString& title, const QString& message )
215 {
216  pushMessage( title, message, INFO );
217 }
218 
219 void QgsMessageBar::pushWarning( const QString& title, const QString& message )
220 {
221  pushMessage( title, message, WARNING );
222 }
223 
224 void QgsMessageBar::pushCritical( const QString& title, const QString& message )
225 {
226  pushMessage( title, message, CRITICAL );
227 }
228 
229 void QgsMessageBar::showItem( QgsMessageBarItem *item )
230 {
231  Q_ASSERT( item );
232 
233  if ( mCurrentItem != 0 )
234  disconnect( mCurrentItem, SIGNAL( styleChanged( QString ) ), this, SLOT( setStyleSheet( QString ) ) );
235 
236  if ( item == mCurrentItem )
237  return;
238 
239  if ( mItems.contains( item ) )
240  mItems.removeOne( item );
241 
242  if ( mCurrentItem )
243  {
244  mItems.prepend( mCurrentItem );
245  mLayout->removeWidget( mCurrentItem );
246  mCurrentItem->hide();
247  }
248 
249  mCurrentItem = item;
250  mLayout->addWidget( item, 0, 1, 1, 1 );
251  mCurrentItem->show();
252 
253  if ( item->duration() > 0 )
254  {
255  mCountProgress->setRange( 0, item->duration() );
256  mCountProgress->setValue( item->duration() );
257  mCountProgress->setVisible( true );
258  mCountdownTimer->start();
259  }
260 
261  connect( mCurrentItem, SIGNAL( styleChanged( QString ) ), this, SLOT( setStyleSheet( QString ) ) );
262  setStyleSheet( item->getStyleSheet() );
263  show();
264 
265  emit widgetAdded( item );
266 }
267 
269 {
270  resetCountdown();
271  // avoid duplicated widget
272  popWidget( item );
273  showItem( item );
274 }
275 
277 {
278  QgsMessageBarItem *item;
279  item = dynamic_cast<QgsMessageBarItem*>( widget );
280  if ( item )
281  {
282  item->setLevel( level )->setDuration( duration );
283  }
284  else
285  {
286  item = new QgsMessageBarItem( widget, level, duration );
287  }
288  pushItem( item );
289  return item;
290 }
291 
292 void QgsMessageBar::pushMessage( const QString &title, const QString &text, QgsMessageBar::MessageLevel level, int duration )
293 {
294  QgsMessageBarItem *item = new QgsMessageBarItem( title, text, level, duration );
295  pushItem( item );
296 }
297 
299 {
300  QgsMessageBarItem* item = new QgsMessageBarItem( text, INFO, 0, parent );
301  return item;
302 }
303 
305 {
306  return new QgsMessageBarItem( title, text, QgsMessageBar::INFO, 0, parent );
307 }
308 
310 {
311  return new QgsMessageBarItem( widget, INFO, 0, parent );
312 }
313 
314 void QgsMessageBar::updateCountdown()
315 {
316  if ( !mCountdownTimer->isActive() )
317  {
318  resetCountdown();
319  return;
320  }
321  if ( mCountProgress->value() < 2 )
322  {
323  popWidget();
324  }
325  else
326  {
327  mCountProgress->setValue( mCountProgress->value() - 1 );
328  }
329 }
330 
331 void QgsMessageBar::resetCountdown()
332 {
333  if ( mCountdownTimer->isActive() )
334  mCountdownTimer->stop();
335 
336  mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
337  mCountProgress->setVisible( false );
338 }
339 
340 void QgsMessageBar::updateItemCount()
341 {
342  mItemCount->setText( mItems.count() > 0 ? tr( "%n more", "unread messages", mItems.count() ) : QString( "" ) );
343 
344  // do not show the down arrow for opening menu with "close all" if there is just one message
345  mCloseBtn->setMenu( mItems.count() > 0 ? mCloseMenu : 0 );
346  mCloseBtn->setPopupMode( mItems.count() > 0 ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
347 }
void setInterval(int msec)
void setBrush(ColorRole role, const QBrush &brush)
void pushMessage(const QString &text, MessageLevel level=INFO, int duration=0)
convenience method for pushing a message to the bar
Definition: qgsmessagebar.h:90
void setStyleSheet(const QString &styleSheet)
void setMenu(QMenu *menu)
void setContentsMargins(int left, int top, int right, int bottom)
const QPalette & palette() const
void setCursor(const QCursor &)
void mousePressEvent(QMouseEvent *e) override
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
void pushInfo(const QString &title, const QString &message)
Pushes a information message with default timeout to the message bar.
void setFrameShape(Shape)
void widgetRemoved(QgsMessageBarItem *item)
emitted when a message widget was removed from the bar
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void setMinimumWidth(int minw)
QWidget * childAt(int x, int y) const
void addAction(QAction *action)
virtual void setVisible(bool visible)
void setValue(int value)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void setIcon(const QIcon &icon)
QString tr(const char *sourceText, const char *disambiguation, int n)
void pushSuccess(const QString &title, const QString &message)
Pushes a success message with default timeout to the message bar.
void removeWidget(QWidget *widget)
void pushWarning(const QString &title, const QString &message)
Pushes a warning with default timeout to the message bar.
int count(const T &value) const
void setLayout(QLayout *layout)
bool empty() const
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=0)
make out a widget containing a message to be displayed on the bar
void setIconSize(const QSize &size)
Qt::MouseButton button() const
QPalette::ColorRole backgroundRole() const
bool isEmpty() const
void setObjectName(const QString &name)
int duration() const
returns the duration in second of the message
void widgetAdded(QgsMessageBarItem *item)
emitted when a message widget is added to the bar
T & first()
void setText(const QString &)
void hide()
void setSizePolicy(QSizePolicy)
void setFixedSize(const QSize &s)
bool contains(const T &value) const
void stop()
void setFrameShadow(Shadow)
QgsMessageBarItem * pushWidget(QWidget *widget, MessageLevel level=INFO, int duration=0)
QString getStyleSheet()
returns the styleSheet
void pushItem(QgsMessageBarItem *item)
Display a message item on the bar after hiding the currently visible one and putting it in a stack...
QgsMessageBarItem * setLevel(QgsMessageBar::MessageLevel level)
QgsMessageBarItem * setDuration(int duration)
void setPopupMode(ToolButtonPopupMode mode)
QgsMessageBar(QWidget *parent=0)
void start(int msec)
void prepend(const T &value)
void setAutoFillBackground(bool enabled)
void show()
const QPoint & pos() const
void setToolTip(const QString &)
const QBrush & window() const
bool isActive() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setTextVisible(bool visible)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setRange(int minimum, int maximum)
bool removeOne(const T &value)
void setHidden(bool hidden)
void pushCritical(const QString &title, const QString &message)
Pushes a critical warning with default timeout to the message bar.