1 /***************************************************************************
2 testqgsmessagebar.cpp
3 --------------------------------------
4 Date : October 2018
5 Copyright : (C) 2018 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16
17 #include "qgstest.h"
18
19 #include "qgsmessagebar.h"
20 #include "qgsmessagebaritem.h"
21 #include <memory>
22
23 class TestQgsMessageBar: public QObject
24 {
25 Q_OBJECT
26 private slots:
27 void initTestCase(); // will be called before the first testfunction is executed.
28 void cleanupTestCase(); // will be called after the last testfunction was executed.
29 void init(); // will be called before each testfunction is executed.
30 void cleanup(); // will be called after every testfunction.
31 void dismiss();
32 void pushPop();
33 void autoDelete();
34
35 };
36
initTestCase()37 void TestQgsMessageBar::initTestCase()
38 {
39
40 }
41
cleanupTestCase()42 void TestQgsMessageBar::cleanupTestCase()
43 {
44 }
45
init()46 void TestQgsMessageBar::init()
47 {
48 }
49
cleanup()50 void TestQgsMessageBar::cleanup()
51 {
52 }
53
dismiss()54 void TestQgsMessageBar::dismiss()
55 {
56 QgsMessageBar bar;
57 bar.show();
58 QVERIFY( !bar.currentItem() );
59
60 QgsMessageBarItem *item = new QgsMessageBarItem( QStringLiteral( "test" ) );
61 const QPointer< QgsMessageBarItem > pItem( item );
62 item->dismiss(); // should do nothing, not in a bar yet
63 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
64 for ( int i = 1; i < 100; ++i )
65 {
66 QApplication::processEvents();
67 }
68 QCOMPARE( pItem.data(), item );
69
70
71 bar.pushItem( item );
72 QCOMPARE( bar.currentItem(), item );
73
74 item->dismiss();
75 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
76
77 for ( int i = 1; i < 100; ++i )
78 {
79 QApplication::processEvents();
80 }
81 QVERIFY( !bar.currentItem() );
82 QVERIFY( !pItem.data() );
83 }
84
pushPop()85 void TestQgsMessageBar::pushPop()
86 {
87 // test pushing/popping message logic
88 QgsMessageBar bar;
89 QCOMPARE( bar.items().size(), 0 );
90 QVERIFY( !bar.currentItem() );
91 bar.pushMessage( QStringLiteral( "1" ) );
92 QCOMPARE( bar.items().size(), 1 );
93 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "1" ) );
94 QCOMPARE( bar.currentItem()->text(), QStringLiteral( "1" ) );
95 const QPointer< QgsMessageBarItem > item1 = bar.currentItem();
96 // make sure correct item is the visible one
97 QCOMPARE( qobject_cast< QgsMessageBarItem * >( qgis::down_cast< QGridLayout * >( bar.layout() )->itemAt( 3 )->widget() )->text(), QStringLiteral( "1" ) );
98
99 bar.pushMessage( QStringLiteral( "2" ) );
100 QCOMPARE( bar.items().size(), 2 );
101 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "2" ) );
102 QCOMPARE( bar.items().at( 1 )->text(), QStringLiteral( "1" ) );
103 QCOMPARE( bar.currentItem()->text(), QStringLiteral( "2" ) );
104 const QPointer< QgsMessageBarItem > item2 = bar.currentItem();
105 QCOMPARE( qobject_cast< QgsMessageBarItem * >( qgis::down_cast< QGridLayout * >( bar.layout() )->itemAt( 3 )->widget() )->text(), QStringLiteral( "2" ) );
106
107 bar.pushMessage( QStringLiteral( "3" ) );
108 QCOMPARE( bar.items().size(), 3 );
109 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "3" ) );
110 QCOMPARE( bar.items().at( 1 )->text(), QStringLiteral( "2" ) );
111 QCOMPARE( bar.items().at( 2 )->text(), QStringLiteral( "1" ) );
112 QCOMPARE( bar.currentItem()->text(), QStringLiteral( "3" ) );
113 const QPointer< QgsMessageBarItem > item3 = bar.currentItem();
114 QCOMPARE( qobject_cast< QgsMessageBarItem * >( qgis::down_cast< QGridLayout * >( bar.layout() )->itemAt( 3 )->widget() )->text(), QStringLiteral( "3" ) );
115
116 const int childCount = bar.children().count();
117 QVERIFY( bar.popWidget() );
118 QCOMPARE( bar.items().size(), 2 );
119 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "2" ) );
120 QCOMPARE( bar.items().at( 1 )->text(), QStringLiteral( "1" ) );
121 QCOMPARE( bar.currentItem()->text(), QStringLiteral( "2" ) );
122 QCOMPARE( qobject_cast< QgsMessageBarItem * >( qgis::down_cast< QGridLayout * >( bar.layout() )->itemAt( 3 )->widget() )->text(), QStringLiteral( "2" ) );
123 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
124 QCOMPARE( bar.children().count(), childCount - 1 );
125 QVERIFY( !item3 );
126
127 QVERIFY( bar.popWidget() );
128 QCOMPARE( bar.items().size(), 1 );
129 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "1" ) );
130 QCOMPARE( bar.currentItem()->text(), QStringLiteral( "1" ) );
131 QCOMPARE( qobject_cast< QgsMessageBarItem * >( qgis::down_cast< QGridLayout * >( bar.layout() )->itemAt( 3 )->widget() )->text(), QStringLiteral( "1" ) );
132 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
133 QCOMPARE( bar.children().count(), childCount - 2 );
134 QVERIFY( !item2 );
135
136 QVERIFY( bar.popWidget() );
137 QCOMPARE( bar.items().size(), 0 );
138 QVERIFY( !bar.currentItem() );
139 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
140 QCOMPARE( bar.children().count(), childCount - 3 );
141 QVERIFY( !item1 );
142
143 QVERIFY( !bar.popWidget() );
144 QCOMPARE( bar.items().size(), 0 );
145 QVERIFY( !bar.currentItem() );
146 }
147
autoDelete()148 void TestQgsMessageBar::autoDelete()
149 {
150 // ensure that items are automatically deleted when queue grows too large
151 QgsMessageBar bar;
152 for ( int i = 0; i < bar.MAX_ITEMS; ++i )
153 {
154 bar.pushMessage( QString::number( i ), Qgis::MessageLevel::Warning );
155 }
156 QCOMPARE( bar.items().size(), 100 );
157 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "99" ) );
158 QCOMPARE( bar.items().at( 99 )->text(), QStringLiteral( "0" ) );
159 const QPointer< QgsMessageBarItem > oldest = bar.items().at( 99 );
160
161 // push one more item, oldest one should be auto-removed
162 bar.pushMessage( QStringLiteral( "100" ), Qgis::MessageLevel::Warning );
163 QCOMPARE( bar.items().size(), 100 );
164 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "100" ) );
165 QCOMPARE( bar.items().at( 99 )->text(), QStringLiteral( "1" ) );
166 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
167 QVERIFY( !oldest );
168
169 // but if we have a lower priority message we can pop, then do that instead
170 bar.pushMessage( QStringLiteral( "101" ), Qgis::MessageLevel::Info );
171 QCOMPARE( bar.items().size(), 100 );
172 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "101" ) );
173 QCOMPARE( bar.items().at( 1 )->text(), QStringLiteral( "100" ) );
174 QCOMPARE( bar.items().at( 99 )->text(), QStringLiteral( "2" ) );
175 bar.pushMessage( QStringLiteral( "102" ), Qgis::MessageLevel::Info );
176 QCOMPARE( bar.items().size(), 100 );
177 QCOMPARE( bar.items().at( 0 )->text(), QStringLiteral( "102" ) );
178 QCOMPARE( bar.items().at( 1 )->text(), QStringLiteral( "100" ) );
179 QCOMPARE( bar.items().at( 99 )->text(), QStringLiteral( "2" ) );
180 }
181
182 QGSTEST_MAIN( TestQgsMessageBar )
183 #include "testqgsmessagebar.moc"
184