QGIS API Documentation  2.8.2-Wien
 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 
33 QgsMessageBar::QgsMessageBar( QWidget *parent )
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 
105 void QgsMessageBar::mousePressEvent( QMouseEvent * e )
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 
298 QgsMessageBarItem* QgsMessageBar::createMessage( const QString &text, QWidget *parent )
299 {
300  QgsMessageBarItem* item = new QgsMessageBarItem( text, INFO, 0, parent );
301  return item;
302 }
303 
304 QgsMessageBarItem* QgsMessageBar::createMessage( const QString &title, const QString &text, QWidget *parent )
305 {
306  return new QgsMessageBarItem( title, text, QgsMessageBar::INFO, 0, parent );
307 }
308 
309 QgsMessageBarItem* QgsMessageBar::createMessage( QWidget *widget, QWidget *parent )
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 }