copy your favourite nokia app with qt

Post on 12-May-2015

2.695 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Weather service, maps and navigation, photo viewer, instant messaging, web browser, flick list or kinetic scrolling. You want all these with Qt? You get it! Presentation by Ariya Hidayat held during Qt Developer Days 2009. http://qt.nokia.com/developer/learning/elearning

TRANSCRIPT

Copy Your Favorite Nokia AppsAriya Hidayat 09/25/09

Agenda

• Mobile platform challenges:– differences vs desktop– things to keep in mind

• Examples which demonstrate:– Low-level painting– Graphics View– Network and web stack

2

Spread the Love

3

All examples are available from...

labs.qt.nokia.com

bit.ly/graphicsdojo

Desktop vs Mobile Platforms

• Hardware power

• Screen size and resolutions

• Input method

• Network access

4

Nokia N95

• CPU: 332 MHz ARM11

• RAM: 128 MB

• Screen: 240 x 320 (QVGA)

• 9-Button keypad

5

Nokia E71

• CPU: 369 MHz ARM11

• RAM: 128 MB

• Screen: 320x240 (QVGA)

• Full QWERTY Keypad

6

Nokia 5800 XpressMusic

• CPU: 434 MHz ARM11

• RAM: 128 MB

• Screen: 360 x 640 (nHD)

• Touch interface

7

Processing Power

• ARM architecture– Different than x86

• Limited memory

8

Graphics Power

• Lower resolution

• Software rendering– hardware acceleration with OpenGL ES

• Font metrics

9

Input Methods

• Keypad, not keyboard– often not full QWERTY

• No mouse– don't bother with mouse move event

• Touch interface– single vs multitouch– stylus vs finger

• Sensors: accelerometer, GPS, compass, ...

10

Network Access

• Wireless LAN– sometimes not available

• Other data access– slower data rate

11

Development Flow

• Device emulator

• Remote debugging

• Performance test

• Profiling tools

12

Example #1

Digital Clock

Digital (Vintage) Clock

14

Framed Digits

15

plain digits with frame

gradient

Gradient is Expensive, so...

16

QLinearGradient gr(QPoint(0, 0), QPoint(0, height));gr.setColorAt(0.00, QColor(128, 128, 128));gr.setColorAt(0.49, QColor(64, 64, 64));gr.setColorAt(0.51, QColor(128, 128, 128));gr.setColorAt(1.00, QColor(16, 16, 16));

QPainter p;p.begin(&pixmap);p.setFont(font);QPen pen;pen.setBrush(QBrush(gr));p.setPen(pen);p.drawText(pixmap.rect(), Qt::AlignCenter, str);p.end();

Cache to a pixmap

Sliding Effect

17

translating both pixmaps

Sliding Effect: The Code

18

QPainter p(this);int y = height() * currentFrame / 100;p.drawPixmap(0, y, m_lastPixmap);p.drawPixmap(0, y - height(), m_pixmap);p.end();

Rotation

19

transform.rotate(30, Qt::ZAxis)

Perspective Transformation

20

transform.rotate(60, Qt::YAxis)

transform.rotate(60, Qt::XAxis)

Rotating Effect

21

rotating pixmaps

Rotating Effect: The Code

22

QTransform transform;transform.translate(width() / 2, height() / 2);transform.rotate(angle, Qt::XAxis);

QPainter p(this);p.setTransform(transform);p.drawPixmap(-width() / 2, -height() / 2, pixmap);p.end();

Flipping Effect

23

rotating and interleaving

two pixmaps

A Trick with QBasicTimer

24

QBasicTimer ticker;ticker.start(1000, this);

void timerEvent(QTimerEvent*){ // update the clock}

No need for QTimer, a slot, and

periodic triggering of signal/slot !

QTimeLine for Frame-based Animation

25

QTimeLine animator;animator.setFrameRange(0, 100);animator.setDuration(600);animator.setCurveShape(QTimeLine::EaseInOutCurve);

int progress = animator.currentFrame();

EaseInOutLinear

acceleration

deacceleration

Sacrifice Quality for Speed

26

Beauty is in the eye of the beholder.

Aliasing during Animation

27

QPainter p(this);p.setRenderHint(QPainter::SmoothPixmapTransform, false);p.setRenderHint(QPainter::Antialiasing, false);

Example #2

Weather Info

Weather Info

29

Screen Orientation

30

requires different layout strategy

Lock the Orientation

31

#include <eikenv.h>#include <eikappui.h>#include <aknenv.h>#include <aknappui.h>

CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi());appUi->SetOrientationL (CAknAppUi::EAppUiOrientationPortrait);

S60-specific, usually you do NOT need to do this!

Animation with Graphics View

32

item movement &

opacity

Using Web Service

33

<weather><forecast_information> <city data="Oslo, Oslo"/> <postal_code data="Oslo"/> <latitude_e6 data=""/><longitude_e6 data=""/> <forecast_date data="2009-09-15"/> <current_date_time data="2009-09-15 13:40:00 +0000"/> <unit_system data="US"/></forecast_information><current_conditions> <condition data="Clear"/> <temp_f data="61"/><temp_c data="16"/> <humidity data="Humidity: 55%"/> <icon data="/ig/images/weather/sunny.gif"/> <wind_condition data="Wind: S at 12 mph"/></current_conditions><forecast_conditions>...

Create the Network Request

34

http://www.google.com/ig/api?hl=en&weather=oslo

QUrl url("http://www.google.com/ig/api");url.addEncodedQueryItem("hl", "en");url.addEncodedQueryItem("weather", QUrl::toPercentEncoding(location));

QNetworkAccessManager *manager;manager = new QNetworkAccessManager(this);connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(handleNetworkData(QNetworkReply*)));

manager->get(QNetworkRequest(url));

Handle the Network Reply

35

http://www.google.com/ig/api?hl=en&weather=oslo

QUrl url = networkReply->url();data = QString::fromUtf8(networkReply->readAll());networkReply->deleteLater();networkReply->manager()->deleteLater();

XML Stream Reader for Parsing

36

QXmlStreamReader xml(data);while (!xml.atEnd()) { xml.readNext(); if (xml.tokenType() == QXmlStreamReader::StartElement) if (xml.name() == "city") city = xml.attributes().value("data").toString()}

faster and requires less memory than

using QDom!

Scalable Icons with SVG

37

bitmap vs vector

Optimize Your SVG

38

Because one element in a group often

does not make sense!

<g> <ellipse cx="10" cy="10" rx=2" ry="2"/></g>

<ellipse cx="10" cy="10" rx=2" ry="2"/>

SVG Loading Time Comparison

39

Use tools like:

codedread.com/scour

svgmin.googlecode.com

Example #3

Flight Tracking

Flight Tracking

41

No Web Service?

42

Use “mobile” version of the web site.

Web Scraping

• Grab the HTML contents

• Scrap it– remove unnecessary clutters– parse and extract the interesting bits

• Legal aspect– some sites explicitly prohibit the use other than

in a web browser

43

Parsing HTML with XML Stream Reader

• HTML != XML

• Potentially provoke the parser (→ errors)– Solution: “scrub it”, i.e. clean up the raw HTML

44

// remove all inline frameswhile (true) { i = data.indexOf("<iframe"); if (i < 0) break; data.remove(i, data.indexOf("</iframe>") - i + 8);}

The Usual Tricks

• Use network request and reply

• Contents– Construct the request– Get the HTML data– Clean it up and then parse it

• Flight map– Construct the request– Get data and feed it to a QPixmap– Display the pixmap, e.g. with QLabel

45

Beware of Different Font Metrics

46

Example #4

Magnifying Glass

Image Zoom

48

Shadow with Radial Gradient

49

magnifier

Shadow with Radial Gradient

50

QRadialGradient g;g.setCenter(radius, radius);g.setFocalPoint(radius, radius);g.setRadius(radius);g.setColorAt(1.0, QColor(255, 255, 255, 0));g.setColorAt(0.5, QColor(128, 128, 128, 255));

Prepare the gradient brush

p.setCompositionMode (QPainter::CompositionMode_Source);p.setBrush(g);p.drawRect(maskPixmap.rect());

p.setBrush(QColor(Qt::transparent));p.drawEllipse(g.center(), radius-15, radius-15);

Draw the shadow

Carve the “hole”

Panning with Mouse/Finger/Stylus

51

void mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::LeftButton) return; pressed = true; pressPos = dragPos = event->pos();}

Record the tap position

void mouseMoveEvent(QMouseEvent *event) { if (!event->buttons()) return; QPoint delta = event->pos() - pressPos; pressPos = event->pos(); pan(delta);}

Pan the map based on the movement

Avoid Accidental Panning

52

panning is not started past the threshold

Turbo Downscaling (We're Cheating!)

53

Fast, no filtering

With filtering

Up to 200x faster,

see http://bit.ly/cheatscale for details!

Example #5

Maps

Maps (with OpenStreetMap)

55

OpenStreetMap vs [Google,Yahoo]Maps

• Free content– Creative Commons Attribution-ShareAlike 2.0

• API does not require the license key

• Available in– rendered images– vector data

More info at www.openstreetmap.org !

56

Getting the Rendered Tiles

• Each tile is 256 x 256 pixels

• Zoom level of 0 → the whole world

• Zoom level of 17 → most detailed

57

QPointF tileForCoordinate(qreal lat, qreal lng, int zoom){ qreal zn = static_cast<qreal>(1 << zoom); qreal tx = (lng + 180.0) / 360.0; qreal ty = (1.0 - log(tan(lat * M_PI / 180.0) + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0; return QPointF(tx * zn, ty * zn);}

Rendering and Caching Strategy

58

application windowcached tiles

Avoid Accidental Panning

59

panning is not started past the threshold

Night Mode

60

Night Mode: The Code

61

QPainter p(this);p.setCompositionMode (QPainter::CompositionMode_Difference);p.fillRect(event->rect(), Qt::white);p.end();

Color channel inversion

red = 255 – red

green = 255 – green

blue = 255 - blue

Example #6

Kinetic Scrolling

Kinetic Scrolling

63

State Machine for Scrolling

64

Steady

Pressed

Manual Scroll

Auto Scroll

Stop

Mouse press

Mouse release

Mouse move

Mouse release

Mouse release Mouse press

Mousemove

Timer tick

Example #7

Parallax Sliding

Parallax Sliding

66

Slow-moving Background

67

1 542

3

Example #8

Web Technologies

Web Browser

• QtWebKit:– Standard compliant, fast rendering engine– Used in Apple Safari, Google Chrome, …– S60 Browser, Apple iPhone, Google Android,

Palm WebOS, …

• Use QWebView and you are done!

• Add flick support for kinetic scrolling

69

Google Chat Client

70

We Cheat (Again)!

71

• Use QWebView from QtWebKit

• Show the “mobile” version

• Add custom login page

Example #9

Unfinished Mini-game

Ray Casting

73

Made Popular in (DOS) Wolfenstein 3-D

• A single ray is traced for every column

• Grid-based world, uniform height → fast

74

Shading Trick

75

Direct Screen Blit

76

setAttribute(Qt::WA_OpaquePaintEvent, true);

Don't bother “clearing” the widget!

Faster direct screen access using

CDirectScreenBitmap or

Anti-Tearing API

Bypass Alpha-Blending

77

QPainter p(this);p.setCompositionMode(QPainter::Composition_Source)p.drawImage(0, 0, buffer);

Since we handle each and every pixel, ...

Storing Pixels in Image

78

Memory Access Optimization

79

Minimize location (in memory) betweentwo vertically separated pixels

Jump several hundreds bytes

Jump fewbytes only

Inner Loop Approach

80

while (y1 >= 0 && y2 < bufh && p1 >= 0) { *pixel1 = tex[p1 >> 12]; *pixel2 = tex[p2 >> 12]; p1 -= dy; p2 += dy; --y1; ++y2; pixel1 -= stride; pixel2 += stride;}

Use only simple, 12-bits fixed-point arithmetics

Conclusion

81

Mobile application developmentwith Qt is FUN

That's all, folks...

82

Thank You!

Bleeding-Edge

83

labs.qt.nokia.com

bit.ly/graphicsdojo

top related