@@ -124,7 +124,13 qreal QBarSeries::barMargin() const | |||
|
124 | 124 | bool QBarSeries::append(QBarSet *set) |
|
125 | 125 | { |
|
126 | 126 | Q_D(QBarSeries); |
|
127 |
|
|
|
127 | bool success = d->append(set); | |
|
128 | if (success) { | |
|
129 | QList<QBarSet*> sets; | |
|
130 | sets.append(set); | |
|
131 | emit barsetsAdded(sets); | |
|
132 | } | |
|
133 | return success; | |
|
128 | 134 | } |
|
129 | 135 | |
|
130 | 136 | /*! |
@@ -134,7 +140,13 bool QBarSeries::append(QBarSet *set) | |||
|
134 | 140 | bool QBarSeries::remove(QBarSet *set) |
|
135 | 141 | { |
|
136 | 142 | Q_D(QBarSeries); |
|
137 |
|
|
|
143 | bool success = d->remove(set); | |
|
144 | if (success) { | |
|
145 | QList<QBarSet*> sets; | |
|
146 | sets.append(set); | |
|
147 | emit barsetsRemoved(sets); | |
|
148 | } | |
|
149 | return success; | |
|
138 | 150 | } |
|
139 | 151 | |
|
140 | 152 | /*! |
@@ -146,7 +158,11 bool QBarSeries::remove(QBarSet *set) | |||
|
146 | 158 | bool QBarSeries::append(QList<QBarSet* > sets) |
|
147 | 159 | { |
|
148 | 160 | Q_D(QBarSeries); |
|
149 |
|
|
|
161 | bool success = d->append(sets); | |
|
162 | if (success) { | |
|
163 | emit barsetsAdded(sets); | |
|
164 | } | |
|
165 | return success; | |
|
150 | 166 | } |
|
151 | 167 | |
|
152 | 168 | /*! |
@@ -155,7 +171,11 bool QBarSeries::append(QList<QBarSet* > sets) | |||
|
155 | 171 | bool QBarSeries::remove(QList<QBarSet* > sets) |
|
156 | 172 | { |
|
157 | 173 | Q_D(QBarSeries); |
|
158 |
|
|
|
174 | bool success = d->remove(sets); | |
|
175 | if (success) { | |
|
176 | emit barsetsRemoved(sets); | |
|
177 | } | |
|
178 | return success; | |
|
159 | 179 | } |
|
160 | 180 | |
|
161 | 181 | void QBarSeries::clear() |
@@ -189,8 +209,8 void QBarSeries::setLabelsVisible(bool visible) | |||
|
189 | 209 | { |
|
190 | 210 | Q_D(QBarSeries); |
|
191 | 211 | if (d->m_labelsVisible != visible) { |
|
192 |
d-> |
|
|
193 |
emit |
|
|
212 | d->setLabelsVisible(visible); | |
|
213 | emit labelsVisibleChanged(); | |
|
194 | 214 | } |
|
195 | 215 | } |
|
196 | 216 | |
@@ -287,15 +307,14 QBarSet* QBarSeriesPrivate::barsetAt(int index) | |||
|
287 | 307 | |
|
288 | 308 | void QBarSeriesPrivate::setVisible(bool visible) |
|
289 | 309 | { |
|
290 |
|
|
|
291 | m_visible = visible; | |
|
292 | emit updatedBars(); | |
|
293 | } | |
|
310 | m_visible = visible; | |
|
311 | emit updatedBars(); | |
|
294 | 312 | } |
|
295 | 313 | |
|
296 |
|
|
|
314 | void QBarSeriesPrivate::setLabelsVisible(bool visible) | |
|
297 | 315 | { |
|
298 | return m_visible; | |
|
316 | m_labelsVisible = visible; | |
|
317 | emit labelsVisibleChanged(visible); | |
|
299 | 318 | } |
|
300 | 319 | |
|
301 | 320 | QString QBarSeriesPrivate::categoryName(int category) |
@@ -518,23 +537,28 bool QBarSeriesPrivate::append(QList<QBarSet* > sets) | |||
|
518 | 537 | bool QBarSeriesPrivate::remove(QList<QBarSet* > sets) |
|
519 | 538 | { |
|
520 | 539 | Q_Q(QBarSeries); |
|
521 | bool setsRemoved = false; | |
|
522 | 540 | foreach (QBarSet* set, sets) { |
|
523 | if (m_barSets.contains(set)) { | |
|
524 | m_barSets.removeOne(set); | |
|
525 | QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars())); | |
|
526 | QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars())); | |
|
527 | setsRemoved = true; | |
|
541 | if ((set == 0) || (!m_barSets.contains(set))) { | |
|
542 | // Fail if any of the sets is null or is not in series | |
|
543 | return false; | |
|
544 | } | |
|
545 | if (sets.count(set) != 1) { | |
|
546 | // Also fail if same set is more than once in given list. | |
|
547 | return false; | |
|
528 | 548 | } |
|
529 | 549 | } |
|
530 | 550 | |
|
531 | if (setsRemoved) { | |
|
532 | if (m_dataset) { | |
|
533 | m_dataset->updateSeries(q); // this notifies legend | |
|
534 | } | |
|
535 | emit restructuredBars(); // this notifies barchartitem | |
|
551 | foreach (QBarSet* set, sets) { | |
|
552 | m_barSets.removeOne(set); | |
|
553 | QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars())); | |
|
554 | QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars())); | |
|
536 | 555 | } |
|
537 | return setsRemoved; | |
|
556 | ||
|
557 | if (m_dataset) { | |
|
558 | m_dataset->updateSeries(q); // this notifies legend | |
|
559 | } | |
|
560 | emit restructuredBars(); // this notifies barchartitem | |
|
561 | return true; | |
|
538 | 562 | } |
|
539 | 563 | |
|
540 | 564 | #include "moc_qbarseries.cpp" |
@@ -63,6 +63,11 protected: | |||
|
63 | 63 | Q_SIGNALS: |
|
64 | 64 | void clicked(QBarSet *barset, int index); |
|
65 | 65 | void hovered(QBarSet* barset, bool status); |
|
66 | void visibleChanged(); | |
|
67 | void labelsVisibleChanged(); | |
|
68 | ||
|
69 | void barsetsAdded(QList<QBarSet*> sets); | |
|
70 | void barsetsRemoved(QList<QBarSet*> sets); | |
|
66 | 71 | |
|
67 | 72 | protected: |
|
68 | 73 | Q_DECLARE_PRIVATE(QBarSeries) |
@@ -55,7 +55,7 public: | |||
|
55 | 55 | qreal barMargin() const; |
|
56 | 56 | |
|
57 | 57 | void setVisible(bool visible); |
|
58 | bool isVisible() const; | |
|
58 | void setLabelsVisible(bool visible); | |
|
59 | 59 | |
|
60 | 60 | void scaleDomain(Domain& domain); |
|
61 | 61 | Chart* createGraphics(ChartPresenter* presenter); |
@@ -60,6 +60,7 QBarSet::~QBarSet() | |||
|
60 | 60 | void QBarSet::setName(const QString name) |
|
61 | 61 | { |
|
62 | 62 | d_ptr->m_name = name; |
|
63 | emit nameChanged(); | |
|
63 | 64 | } |
|
64 | 65 | |
|
65 | 66 | /*! |
@@ -78,8 +79,9 QString QBarSet::name() const | |||
|
78 | 79 | */ |
|
79 | 80 | void QBarSet::append(const QPointF value) |
|
80 | 81 | { |
|
81 |
d_ptr->m_values. |
|
|
82 | emit d_ptr->restructuredBars(); | |
|
82 | int index = d_ptr->m_values.count(); | |
|
83 | d_ptr->append(value); | |
|
84 | emit valuesAdded(index, 1); | |
|
83 | 85 | } |
|
84 | 86 | |
|
85 | 87 | /*! |
@@ -88,10 +90,9 void QBarSet::append(const QPointF value) | |||
|
88 | 90 | */ |
|
89 | 91 | void QBarSet::append(const QList<QPointF> values) |
|
90 | 92 | { |
|
91 |
|
|
|
92 |
|
|
|
93 | } | |
|
94 | emit d_ptr->restructuredBars(); | |
|
93 | int index = d_ptr->m_values.count(); | |
|
94 | d_ptr->append(values); | |
|
95 | emit valuesAdded(index, values.count()); | |
|
95 | 96 | } |
|
96 | 97 | |
|
97 | 98 | /*! |
@@ -100,6 +101,7 void QBarSet::append(const QList<QPointF> values) | |||
|
100 | 101 | */ |
|
101 | 102 | void QBarSet::append(const qreal value) |
|
102 | 103 | { |
|
104 | // Convert to QPointF and use other append(QPointF) method. | |
|
103 | 105 | append(QPointF(d_ptr->m_values.count(), value)); |
|
104 | 106 | } |
|
105 | 107 | |
@@ -111,11 +113,8 void QBarSet::append(const qreal value) | |||
|
111 | 113 | void QBarSet::append(const QList<qreal> values) |
|
112 | 114 | { |
|
113 | 115 | int index = d_ptr->m_values.count(); |
|
114 | for (int i=0; i<values.count(); i++) { | |
|
115 | d_ptr->m_values.append(QPointF(index,values.at(i))); | |
|
116 | index++; | |
|
117 | } | |
|
118 | emit d_ptr->restructuredBars(); | |
|
116 | d_ptr->append(values); | |
|
117 | emit valuesAdded(index, values.count()); | |
|
119 | 118 | } |
|
120 | 119 | |
|
121 | 120 | /*! |
@@ -145,18 +144,32 QBarSet& QBarSet::operator << (const QPointF &value) | |||
|
145 | 144 | */ |
|
146 | 145 | void QBarSet::insert(const int index, const qreal value) |
|
147 | 146 | { |
|
148 |
d_ptr-> |
|
|
149 | // emit d_ptr->updatedBars(); | |
|
147 | d_ptr->insert(index, value); | |
|
148 | emit valuesAdded(index,1); | |
|
149 | } | |
|
150 | ||
|
151 | /*! | |
|
152 | Inserts new \a value on the \a index position. | |
|
153 | The value that is currently at this postion is moved to postion index + 1 | |
|
154 | \sa remove() | |
|
155 | */ | |
|
156 | void QBarSet::insert(const int index, const QPointF value) | |
|
157 | { | |
|
158 | d_ptr->insert(index,value); | |
|
159 | emit valuesAdded(index,1); | |
|
150 | 160 | } |
|
151 | 161 | |
|
152 | 162 | /*! |
|
153 | 163 | Removes the value specified by \a index |
|
154 | 164 | \sa insert() |
|
155 | 165 | */ |
|
156 |
|
|
|
166 | bool QBarSet::remove(const int index, const int count) | |
|
157 | 167 | { |
|
158 |
d_ptr-> |
|
|
159 | // emit d_ptr->updatedBars(); | |
|
168 | bool success = d_ptr->remove(index,count); | |
|
169 | if (success) { | |
|
170 | emit valuesRemoved(index,count); | |
|
171 | } | |
|
172 | return success; | |
|
160 | 173 | } |
|
161 | 174 | |
|
162 | 175 | /*! |
@@ -164,8 +177,17 void QBarSet::remove(const int index) | |||
|
164 | 177 | */ |
|
165 | 178 | void QBarSet::replace(const int index, const qreal value) |
|
166 | 179 | { |
|
167 |
d_ptr-> |
|
|
168 | emit d_ptr->updatedBars(); | |
|
180 | d_ptr->replace(index,value); | |
|
181 | emit valueChanged(index); | |
|
182 | } | |
|
183 | ||
|
184 | /*! | |
|
185 | Sets a new value \a value to set, indexed by \a index | |
|
186 | */ | |
|
187 | void QBarSet::replace(const int index, const QPointF value) | |
|
188 | { | |
|
189 | d_ptr->replace(index,value); | |
|
190 | emit valueChanged(index); | |
|
169 | 191 | } |
|
170 | 192 | |
|
171 | 193 | /*! |
@@ -222,6 +244,7 void QBarSet::setPen(const QPen &pen) | |||
|
222 | 244 | if(d_ptr->m_pen!=pen){ |
|
223 | 245 | d_ptr->m_pen = pen; |
|
224 | 246 | emit d_ptr->updatedBars(); |
|
247 | emit penChanged(); | |
|
225 | 248 | } |
|
226 | 249 | } |
|
227 | 250 | |
@@ -241,6 +264,7 void QBarSet::setBrush(const QBrush &brush) | |||
|
241 | 264 | if(d_ptr->m_brush!=brush){ |
|
242 | 265 | d_ptr->m_brush = brush; |
|
243 | 266 | emit d_ptr->updatedBars(); |
|
267 | emit brushChanged(); | |
|
244 | 268 | } |
|
245 | 269 | } |
|
246 | 270 | |
@@ -260,6 +284,7 void QBarSet::setLabelBrush(const QBrush &brush) | |||
|
260 | 284 | if(d_ptr->m_labelBrush!=brush){ |
|
261 | 285 | d_ptr->m_labelBrush = brush; |
|
262 | 286 | emit d_ptr->updatedBars(); |
|
287 | emit labelBrushChanged(); | |
|
263 | 288 | } |
|
264 | 289 | } |
|
265 | 290 | |
@@ -279,6 +304,7 void QBarSet::setLabelFont(const QFont &font) | |||
|
279 | 304 | if(d_ptr->m_labelFont!=font) { |
|
280 | 305 | d_ptr->m_labelFont = font; |
|
281 | 306 | emit d_ptr->updatedBars(); |
|
307 | emit labelFontChanged(); | |
|
282 | 308 | } |
|
283 | 309 | |
|
284 | 310 | } |
@@ -303,6 +329,69 QBarSetPrivate::~QBarSetPrivate() | |||
|
303 | 329 | { |
|
304 | 330 | } |
|
305 | 331 | |
|
332 | void QBarSetPrivate::append(QPointF value) | |
|
333 | { | |
|
334 | m_values.append(value); | |
|
335 | emit restructuredBars(); | |
|
336 | } | |
|
337 | ||
|
338 | void QBarSetPrivate::append(QList<QPointF> values) | |
|
339 | { | |
|
340 | for (int i=0; i<values.count(); i++) { | |
|
341 | m_values.append(values.at(i)); | |
|
342 | } | |
|
343 | emit restructuredBars(); | |
|
344 | } | |
|
345 | ||
|
346 | void QBarSetPrivate::append(QList<qreal> values) | |
|
347 | { | |
|
348 | int index = m_values.count(); | |
|
349 | for (int i=0; i<values.count(); i++) { | |
|
350 | m_values.append(QPointF(index,values.at(i))); | |
|
351 | index++; | |
|
352 | } | |
|
353 | emit restructuredBars(); | |
|
354 | } | |
|
355 | ||
|
356 | void QBarSetPrivate::insert(const int index, const qreal value) | |
|
357 | { | |
|
358 | m_values.insert(index, QPointF(index, value)); | |
|
359 | emit restructuredBars(); | |
|
360 | } | |
|
361 | ||
|
362 | void QBarSetPrivate::insert(const int index, const QPointF value) | |
|
363 | { | |
|
364 | m_values.insert(index, value); | |
|
365 | emit restructuredBars(); | |
|
366 | } | |
|
367 | ||
|
368 | bool QBarSetPrivate::remove(const int index, const int count) | |
|
369 | { | |
|
370 | if ((index + count) > m_values.count()) { | |
|
371 | // cant remove more values than there are | |
|
372 | return false; | |
|
373 | } | |
|
374 | int c = count; | |
|
375 | while (c > 0) { | |
|
376 | m_values.removeAt(index); | |
|
377 | c--; | |
|
378 | } | |
|
379 | emit restructuredBars(); | |
|
380 | return true; | |
|
381 | } | |
|
382 | ||
|
383 | void QBarSetPrivate::replace(const int index, const qreal value) | |
|
384 | { | |
|
385 | m_values.replace(index,QPointF(index,value)); | |
|
386 | emit updatedBars(); | |
|
387 | } | |
|
388 | ||
|
389 | void QBarSetPrivate::replace(const int index, const QPointF value) | |
|
390 | { | |
|
391 | m_values.replace(index,value); | |
|
392 | emit updatedBars(); | |
|
393 | } | |
|
394 | ||
|
306 | 395 | #include "moc_qbarset.cpp" |
|
307 | 396 | #include "moc_qbarset_p.cpp" |
|
308 | 397 |
@@ -54,8 +54,10 public: | |||
|
54 | 54 | QBarSet& operator << (const QPointF &value); |
|
55 | 55 | |
|
56 | 56 | void insert(const int index, const qreal value); |
|
57 |
void |
|
|
57 | void insert(const int index, const QPointF value); | |
|
58 | bool remove(const int index, const int count = 1); | |
|
58 | 59 | void replace(const int index, const qreal value); |
|
60 | void replace(const int index, const QPointF value); | |
|
59 | 61 | QPointF at(const int index) const; |
|
60 | 62 | QPointF operator [] (const int index) const; |
|
61 | 63 | int count() const; |
@@ -73,6 +75,18 public: | |||
|
73 | 75 | void setLabelFont(const QFont &font); |
|
74 | 76 | QFont labelFont() const; |
|
75 | 77 | |
|
78 | Q_SIGNALS: | |
|
79 | void nameChanged(); | |
|
80 | void penChanged(); | |
|
81 | void brushChanged(); | |
|
82 | void labelChanged(); | |
|
83 | void labelBrushChanged(); | |
|
84 | void labelFontChanged(); | |
|
85 | ||
|
86 | void valuesAdded(int index, int count); | |
|
87 | void valuesRemoved(int index, int count); | |
|
88 | void valueChanged(int index); | |
|
89 | ||
|
76 | 90 | private: |
|
77 | 91 | QScopedPointer<QBarSetPrivate> d_ptr; |
|
78 | 92 | Q_DISABLE_COPY(QBarSet) |
@@ -46,6 +46,17 public: | |||
|
46 | 46 | QBarSetPrivate(const QString name, QBarSet *parent); |
|
47 | 47 | ~QBarSetPrivate(); |
|
48 | 48 | |
|
49 | void append(QPointF value); | |
|
50 | void append(QList<QPointF> values); | |
|
51 | void append(QList<qreal> values); | |
|
52 | ||
|
53 | void insert(const int index, const qreal value); | |
|
54 | void insert(const int index, const QPointF value); | |
|
55 | bool remove(const int index, const int count); | |
|
56 | ||
|
57 | void replace(const int index, const qreal value); | |
|
58 | void replace(const int index, const QPointF value); | |
|
59 | ||
|
49 | 60 | Q_SIGNALS: |
|
50 | 61 | void restructuredBars(); |
|
51 | 62 | void updatedBars(); |
@@ -108,8 +108,10 void tst_QBarSet::name() | |||
|
108 | 108 | QFETCH(QString, name); |
|
109 | 109 | QFETCH(QString, result); |
|
110 | 110 | |
|
111 | QSignalSpy nameSpy(m_barset,SIGNAL(nameChanged())); | |
|
111 | 112 | m_barset->setName(name); |
|
112 | 113 | QCOMPARE(m_barset->name(), result); |
|
114 | QVERIFY(nameSpy.count() == 1); | |
|
113 | 115 | } |
|
114 | 116 | |
|
115 | 117 | void tst_QBarSet::append_data() |
@@ -128,6 +130,8 void tst_QBarSet::append() | |||
|
128 | 130 | QCOMPARE(m_barset->count(), 0); |
|
129 | 131 | QVERIFY(qFuzzyIsNull(m_barset->sum())); |
|
130 | 132 | |
|
133 | QSignalSpy valueSpy(m_barset,SIGNAL(valuesAdded(int,int))); | |
|
134 | ||
|
131 | 135 | qreal sum(0.0); |
|
132 | 136 | qreal value(0.0); |
|
133 | 137 | |
@@ -140,6 +144,8 void tst_QBarSet::append() | |||
|
140 | 144 | |
|
141 | 145 | QCOMPARE(m_barset->count(), count); |
|
142 | 146 | QVERIFY(qFuzzyCompare(m_barset->sum(), sum)); |
|
147 | ||
|
148 | QVERIFY(valueSpy.count() == count); | |
|
143 | 149 | } |
|
144 | 150 | |
|
145 | 151 | void tst_QBarSet::appendOperator_data() |
@@ -154,6 +160,8 void tst_QBarSet::appendOperator() | |||
|
154 | 160 | QCOMPARE(m_barset->count(), 0); |
|
155 | 161 | QVERIFY(qFuzzyIsNull(m_barset->sum())); |
|
156 | 162 | |
|
163 | QSignalSpy valueSpy(m_barset,SIGNAL(valuesAdded(int,int))); | |
|
164 | ||
|
157 | 165 | qreal sum(0.0); |
|
158 | 166 | qreal value(0.0); |
|
159 | 167 | |
@@ -166,6 +174,8 void tst_QBarSet::appendOperator() | |||
|
166 | 174 | |
|
167 | 175 | QCOMPARE(m_barset->count(), count); |
|
168 | 176 | QVERIFY(qFuzzyCompare(m_barset->sum(), sum)); |
|
177 | QVERIFY(valueSpy.count() == count); | |
|
178 | ||
|
169 | 179 | } |
|
170 | 180 | |
|
171 | 181 | void tst_QBarSet::insert_data() |
@@ -176,6 +186,7 void tst_QBarSet::insert() | |||
|
176 | 186 | { |
|
177 | 187 | QCOMPARE(m_barset->count(), 0); |
|
178 | 188 | QVERIFY(qFuzzyIsNull(m_barset->sum())); |
|
189 | QSignalSpy valueSpy(m_barset,SIGNAL(valuesAdded(int,int))); | |
|
179 | 190 | |
|
180 | 191 | m_barset->insert(0, 1.0); // 1.0 |
|
181 | 192 | QCOMPARE(m_barset->at(0).y(), 1.0); |
@@ -194,6 +205,7 void tst_QBarSet::insert() | |||
|
194 | 205 | QCOMPARE(m_barset->at(2).y(), 1.0); |
|
195 | 206 | QCOMPARE(m_barset->count(), 3); |
|
196 | 207 | QVERIFY(qFuzzyCompare(m_barset->sum(), 6.0)); |
|
208 | QVERIFY(valueSpy.count() == 3); | |
|
197 | 209 | } |
|
198 | 210 | |
|
199 | 211 | void tst_QBarSet::remove_data() |
@@ -205,6 +217,8 void tst_QBarSet::remove() | |||
|
205 | 217 | QCOMPARE(m_barset->count(), 0); |
|
206 | 218 | QVERIFY(qFuzzyIsNull(m_barset->sum())); |
|
207 | 219 | |
|
220 | QSignalSpy valueSpy(m_barset,SIGNAL(valuesRemoved(int,int))); | |
|
221 | ||
|
208 | 222 | m_barset->append(1.0); |
|
209 | 223 | m_barset->append(2.0); |
|
210 | 224 | m_barset->append(3.0); |
@@ -225,6 +239,8 void tst_QBarSet::remove() | |||
|
225 | 239 | QCOMPARE(m_barset->at(1).y(), 4.0); |
|
226 | 240 | QCOMPARE(m_barset->count(), 2); |
|
227 | 241 | QCOMPARE(m_barset->sum(), 6.0); |
|
242 | ||
|
243 | QVERIFY(valueSpy.count() == 2); | |
|
228 | 244 | } |
|
229 | 245 | |
|
230 | 246 | void tst_QBarSet::replace_data() |
@@ -236,6 +252,7 void tst_QBarSet::replace() | |||
|
236 | 252 | { |
|
237 | 253 | QCOMPARE(m_barset->count(), 0); |
|
238 | 254 | QVERIFY(qFuzzyIsNull(m_barset->sum())); |
|
255 | QSignalSpy valueSpy(m_barset,SIGNAL(valueChanged(int))); | |
|
239 | 256 | |
|
240 | 257 | m_barset->append(1.0); |
|
241 | 258 | m_barset->append(2.0); |
@@ -257,6 +274,8 void tst_QBarSet::replace() | |||
|
257 | 274 | QCOMPARE(m_barset->at(1).y(), 2.0); |
|
258 | 275 | QCOMPARE(m_barset->at(2).y(), 3.0); |
|
259 | 276 | QCOMPARE(m_barset->at(3).y(), 6.0); |
|
277 | ||
|
278 | QVERIFY(valueSpy.count() == 2); | |
|
260 | 279 | } |
|
261 | 280 | |
|
262 | 281 | void tst_QBarSet::at_data() |
General Comments 0
You need to be logged in to leave comments.
Login now