Update copyright headers
[qt:qt.git] / demos / embedded / digiflip / digiflip.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtCore>
43 #include <QtGui>
44
45 class Digits: public QWidget
46 {
47     Q_OBJECT
48
49 public:
50
51     enum {
52         Slide,
53         Flip,
54         Rotate
55     };
56
57     Digits(QWidget *parent)
58         : QWidget(parent)
59         , m_number(0)
60         , m_transition(Slide)
61     {
62         setAttribute(Qt::WA_OpaquePaintEvent, true);
63         setAttribute(Qt::WA_NoSystemBackground, true);
64         connect(&m_animator, SIGNAL(frameChanged(int)), SLOT(update()));
65         m_animator.setFrameRange(0, 100);
66         m_animator.setDuration(600);
67         m_animator.setCurveShape(QTimeLine::EaseInOutCurve);
68     }
69
70     void setTransition(int tr) {
71         m_transition = tr;
72     }
73
74     int transition() const {
75         return m_transition;
76     }
77
78     void setNumber(int n) {
79         if (m_number != n) {
80             m_number = qBound(0, n, 99);
81             preparePixmap();
82             update();
83         }
84     }
85
86     void flipTo(int n) {
87         if (m_number != n) {
88             m_number = qBound(0, n, 99);
89             m_lastPixmap = m_pixmap;
90             preparePixmap();
91             m_animator.stop();
92             m_animator.start();
93         }
94     }
95
96 protected:
97
98     void drawFrame(QPainter *p, const QRect &rect) {
99         p->setPen(Qt::NoPen);
100         QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
101         gradient.setColorAt(0.00, QColor(245, 245, 245));
102         gradient.setColorAt(0.49, QColor(192, 192, 192));
103         gradient.setColorAt(0.51, QColor(245, 245, 245));
104         gradient.setColorAt(1.00, QColor(192, 192, 192));
105         p->setBrush(gradient);
106         QRect r = rect;
107         p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
108         r.adjust(1, 4, -1, -4);
109         p->setPen(QColor(181, 181, 181));
110         p->setBrush(Qt::NoBrush);
111         p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
112         p->setPen(QColor(159, 159, 159));
113         int y = rect.top() + rect.height() / 2 - 1;
114         p->drawLine(rect.left(), y, rect.right(), y);
115     }
116
117     QPixmap drawDigits(int n, const QRect &rect) {
118
119         int scaleFactor = 2;
120 #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
121         if (rect.height() > 240)
122             scaleFactor = 1;
123 #endif
124
125         QString str = QString::number(n);
126         if (str.length() == 1)
127             str.prepend("0");
128
129         QFont font;
130         font.setFamily("Helvetica");
131         int fontHeight = scaleFactor * 0.55 * rect.height();
132         font.setPixelSize(fontHeight);
133         font.setBold(true);
134
135         QPixmap pixmap(rect.size() * scaleFactor);
136         pixmap.fill(Qt::transparent);
137
138         QLinearGradient gradient(QPoint(0, 0), QPoint(0, pixmap.height()));
139         gradient.setColorAt(0.00, QColor(128, 128, 128));
140         gradient.setColorAt(0.49, QColor(64, 64, 64));
141         gradient.setColorAt(0.51, QColor(128, 128, 128));
142         gradient.setColorAt(1.00, QColor(16, 16, 16));
143
144         QPainter p;
145         p.begin(&pixmap);
146         p.setFont(font);
147         QPen pen;
148         pen.setBrush(QBrush(gradient));
149         p.setPen(pen);
150         p.drawText(pixmap.rect(), Qt::AlignCenter, str);
151         p.end();
152
153         return pixmap.scaledToWidth(width(), Qt::SmoothTransformation);
154     }
155
156     void preparePixmap() {
157         m_pixmap = QPixmap(size());
158         m_pixmap.fill(Qt::transparent);
159         QPainter p;
160         p.begin(&m_pixmap);
161         p.drawPixmap(0, 0, drawDigits(m_number, rect()));
162         p.end();
163     }
164
165     void resizeEvent(QResizeEvent*) {
166         preparePixmap();
167         update();
168     }
169
170     void paintStatic() {
171         QPainter p(this);
172         p.fillRect(rect(), Qt::black);
173
174         int pad = width() / 10;
175         drawFrame(&p, rect().adjusted(pad, pad, -pad, -pad));
176         p.drawPixmap(0, 0, m_pixmap);
177     }
178
179     void paintSlide() {
180         QPainter p(this);
181         p.fillRect(rect(), Qt::black);
182
183         int pad = width() / 10;
184         QRect fr = rect().adjusted(pad, pad, -pad, -pad);
185         drawFrame(&p, fr);
186         p.setClipRect(fr);
187
188         int y = height() * m_animator.currentFrame() / 100;
189         p.drawPixmap(0, y, m_lastPixmap);
190         p.drawPixmap(0, y - height(), m_pixmap);
191     }
192
193     void paintFlip() {
194         QPainter p(this);
195 #if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WINCE_WM)
196         p.setRenderHint(QPainter::SmoothPixmapTransform, true);
197         p.setRenderHint(QPainter::Antialiasing, true);
198 #endif
199         p.fillRect(rect(), Qt::black);
200
201         int hw = width() / 2;
202         int hh = height() / 2;
203
204         // behind is the new pixmap
205         int pad = width() / 10;
206         QRect fr = rect().adjusted(pad, pad, -pad, -pad);
207         drawFrame(&p, fr);
208         p.drawPixmap(0, 0, m_pixmap);
209
210         int index = m_animator.currentFrame();
211
212         if (index <= 50) {
213
214             // the top part of the old pixmap is flipping
215             int angle = -180 * index / 100;
216             QTransform transform;
217             transform.translate(hw, hh);
218             transform.rotate(angle, Qt::XAxis);
219             p.setTransform(transform);
220             drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
221             p.drawPixmap(-hw, -hh, m_lastPixmap);
222
223             // the bottom part is still the old pixmap
224             p.resetTransform();
225             p.setClipRect(0, hh, width(), hh);
226             drawFrame(&p, fr);
227             p.drawPixmap(0, 0, m_lastPixmap);
228         } else {
229
230             p.setClipRect(0, hh, width(), hh);
231
232             // the bottom part is still the old pixmap
233             drawFrame(&p, fr);
234             p.drawPixmap(0, 0, m_lastPixmap);
235
236             // the bottom part of the new pixmap is flipping
237             int angle = 180 - 180 * m_animator.currentFrame() / 100;
238             QTransform transform;
239             transform.translate(hw, hh);
240             transform.rotate(angle, Qt::XAxis);
241             p.setTransform(transform);
242             drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
243             p.drawPixmap(-hw, -hh, m_pixmap);
244
245         }
246
247     }
248
249     void paintRotate() {
250         QPainter p(this);
251
252         int pad = width() / 10;
253         QRect fr = rect().adjusted(pad, pad, -pad, -pad);
254         drawFrame(&p, fr);
255         p.setClipRect(fr);
256
257         int angle1 = -180 * m_animator.currentFrame() / 100;
258         int angle2 = 180 - 180 * m_animator.currentFrame() / 100;
259         int angle = (m_animator.currentFrame() <= 50) ? angle1 : angle2;
260         QPixmap pix = (m_animator.currentFrame() <= 50) ? m_lastPixmap : m_pixmap;
261
262         QTransform transform;
263         transform.translate(width() / 2, height() / 2);
264         transform.rotate(angle, Qt::XAxis);
265
266         p.setTransform(transform);
267         p.setRenderHint(QPainter::SmoothPixmapTransform, true);
268         p.drawPixmap(-width() / 2, -height() / 2, pix);
269     }
270
271     void paintEvent(QPaintEvent *event) {
272         Q_UNUSED(event);
273         if (m_animator.state() == QTimeLine::Running) {
274             if (m_transition == Slide)
275                 paintSlide();
276             if (m_transition == Flip)
277                 paintFlip();
278             if (m_transition == Rotate)
279                 paintRotate();
280         } else {
281             paintStatic();
282         }
283     }
284
285 private:
286     int m_number;
287     int m_transition;
288     QPixmap m_pixmap;
289     QPixmap m_lastPixmap;
290     QTimeLine m_animator;
291 };
292
293 class DigiFlip : public QMainWindow
294 {
295     Q_OBJECT
296
297 public:
298     DigiFlip(QWidget *parent = 0)
299         : QMainWindow(parent)
300     {
301         m_hour = new Digits(this);
302         m_hour->show();
303         m_minute = new Digits(this);
304         m_minute->show();
305
306         QPalette pal = palette();
307         pal.setColor(QPalette::Window, Qt::black);
308         setPalette(pal);
309
310         m_ticker.start(1000, this);
311         QTime t = QTime::currentTime();
312         m_hour->setNumber(t.hour());
313         m_minute->setNumber(t.minute());
314         updateTime();
315
316         QAction *slideAction = new QAction("&Slide", this);
317         QAction *flipAction = new QAction("&Flip", this);
318         QAction *rotateAction = new QAction("&Rotate", this);
319         connect(slideAction, SIGNAL(triggered()), SLOT(chooseSlide()));
320         connect(flipAction, SIGNAL(triggered()), SLOT(chooseFlip()));
321         connect(rotateAction, SIGNAL(triggered()), SLOT(chooseRotate()));
322 #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
323         menuBar()->addAction(slideAction);
324         menuBar()->addAction(flipAction);
325         menuBar()->addAction(rotateAction);
326 #else
327         addAction(slideAction);
328         addAction(flipAction);
329         addAction(rotateAction);
330         setContextMenuPolicy(Qt::ActionsContextMenu);
331 #endif
332     }
333
334     void updateTime() {
335         QTime t = QTime::currentTime();
336         m_hour->flipTo(t.hour());
337         m_minute->flipTo(t.minute());
338         QString str = t.toString("hh:mm:ss");
339         str.prepend(": ");
340         if (m_hour->transition() == Digits::Slide)
341             str.prepend("Slide");
342         if (m_hour->transition() == Digits::Flip)
343             str.prepend("Flip");
344         if (m_hour->transition() == Digits::Rotate)
345             str.prepend("Rotate");
346         setWindowTitle(str);
347     }
348
349     void switchTransition(int delta) {
350         int i = (m_hour->transition() + delta + 3) % 3;
351         m_hour->setTransition(i);
352         m_minute->setTransition(i);
353         updateTime();
354     }
355
356 protected:
357     void resizeEvent(QResizeEvent*) {
358         int digitsWidth = width() / 2;
359         int digitsHeight = digitsWidth * 1.2;
360
361         int y = (height() - digitsHeight) / 3;
362
363         m_hour->resize(digitsWidth, digitsHeight);
364         m_hour->move(0, y);
365
366         m_minute->resize(digitsWidth, digitsHeight);
367         m_minute->move(width() / 2, y);
368     }
369
370     void timerEvent(QTimerEvent*) {
371         updateTime();
372     }
373
374     void keyPressEvent(QKeyEvent *event) {
375         if (event->key() == Qt::Key_Right) {
376             switchTransition(1);
377             event->accept();
378         }
379         if (event->key() == Qt::Key_Left) {
380             switchTransition(-1);
381             event->accept();
382         }
383     }
384
385 private slots:
386     void chooseSlide() {
387         m_hour->setTransition(0);
388         m_minute->setTransition(0);
389         updateTime();
390     }
391
392     void chooseFlip() {
393         m_hour->setTransition(1);
394         m_minute->setTransition(1);
395         updateTime();
396     }
397
398     void chooseRotate() {
399         m_hour->setTransition(2);
400         m_minute->setTransition(2);
401         updateTime();
402     }
403
404 private:
405     QBasicTimer m_ticker;
406     Digits *m_hour;
407     Digits *m_minute;
408 };
409
410 #include "digiflip.moc"
411
412 int main(int argc, char *argv[])
413 {
414     QApplication app(argc, argv);
415
416     DigiFlip time;
417 #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
418     time.showMaximized();
419 #else
420     time.resize(320, 240);
421     time.show();
422 #endif
423
424     return app.exec();
425 }