QGIS API Documentation  2.2.0-Valmiera
 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 
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  {
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 
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 
210 {
211  Q_ASSERT( item );
212 
213  if ( mCurrentItem != 0 )
214  disconnect( mCurrentItem, SIGNAL( styleChanged( QString ) ), this, SLOT( setStyleSheet( QString ) ) );
215 
216  if ( item == mCurrentItem )
217  return;
218 
219  if ( mItems.contains( item ) )
220  mItems.removeOne( item );
221 
222  if ( mCurrentItem )
223  {
224  mItems.prepend( mCurrentItem );
225  mLayout->removeWidget( mCurrentItem );
226  mCurrentItem->hide();
227  }
228 
229  mCurrentItem = item;
230  mLayout->addWidget( item, 0, 1, 1, 1 );
231  mCurrentItem->show();
232 
233  if ( item->duration() > 0 )
234  {
235  mCountProgress->setRange( 0, item->duration() );
236  mCountProgress->setValue( item->duration() );
237  mCountProgress->setVisible( true );
238  mCountdownTimer->start();
239  }
240 
241  connect( mCurrentItem, SIGNAL( styleChanged( QString ) ), this, SLOT( setStyleSheet( QString ) ) );
242  setStyleSheet( item->getStyleSheet() );
243  show();
244 
245  emit widgetAdded( item );
246 }
247 
249 {
250  resetCountdown();
251  // avoid duplicated widget
252  popWidget( item );
253  showItem( item );
254 }
255 
257 {
258  QgsMessageBarItem *item;
259  item = dynamic_cast<QgsMessageBarItem*>( widget );
260  if ( item )
261  {
262  item->setLevel( level )->setDuration( duration );
263  }
264  else
265  {
266  item = new QgsMessageBarItem( widget, level, duration );
267  }
268  pushItem( item );
269  return item;
270 }
271 
272 void QgsMessageBar::pushMessage( const QString &title, const QString &text, QgsMessageBar::MessageLevel level, int duration )
273 {
274  QgsMessageBarItem *item = new QgsMessageBarItem( title, text, level, duration );
275  pushItem( item );
276 }
277 
278 QgsMessageBarItem* QgsMessageBar::createMessage( const QString &text, QWidget *parent )
279 {
280  QgsMessageBarItem* item = new QgsMessageBarItem( text, INFO, 0, parent );
281  return item;
282 }
283 
284 QgsMessageBarItem* QgsMessageBar::createMessage( const QString &title, const QString &text, QWidget *parent )
285 {
286  return new QgsMessageBarItem( title, text, QgsMessageBar::INFO, 0, parent );
287 }
288 
289 QgsMessageBarItem* QgsMessageBar::createMessage( QWidget *widget, QWidget *parent )
290 {
291  return new QgsMessageBarItem( widget, INFO, 0, parent );
292 }
293 
295 {
296  if ( !mCountdownTimer->isActive() )
297  {
298  resetCountdown();
299  return;
300  }
301  if ( mCountProgress->value() < 2 )
302  {
303  popWidget();
304  }
305  else
306  {
307  mCountProgress->setValue( mCountProgress->value() - 1 );
308  }
309 }
310 
312 {
313  if ( mCountdownTimer->isActive() )
314  mCountdownTimer->stop();
315 
316  mCountProgress->setStyleSheet( mCountStyleSheet.arg( "mIconTimerPause.png" ) );
317  mCountProgress->setVisible( false );
318 }
319 
321 {
322  mItemCount->setText( mItems.count() > 0 ? tr( "%n more", "unread messages", mItems.count() ) : QString( "" ) );
323 
324  // do not show the down arrow for opening menu with "close all" if there is just one message
325  mCloseBtn->setMenu( mItems.count() > 0 ? mCloseMenu : 0 );
326  mCloseBtn->setPopupMode( mItems.count() > 0 ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
327 }