• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Copy Your Favourite Nokia App with Qt
 

Copy Your Favourite Nokia App with Qt

on

  • 3,701 views

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! ...

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

Statistics

Views

Total Views
3,701
Views on SlideShare
3,666
Embed Views
35

Actions

Likes
0
Downloads
75
Comments
0

1 Embed 35

http://www.slideshare.net 35

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Copy Your Favourite Nokia App with Qt Copy Your Favourite Nokia App with Qt Presentation Transcript

    • Copy Your Favorite Nokia Apps 09/25/09 Ariya Hidayat
    • 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 All examples are available from... labs.qt.nokia.com bit.ly/graphicsdojo 3
    • 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 plain digits with frame gradient 15
    • Gradient is Expensive, so... 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; Cache to a p.begin(&pixmap); pixmap p.setFont(font); QPen pen; pen.setBrush(QBrush(gr)); p.setPen(pen); p.drawText(pixmap.rect(), Qt::AlignCenter, str); p.end(); 16
    • Sliding Effect translating both pixmaps 17
    • Sliding Effect: The Code QPainter p(this); int y = height() * currentFrame / 100; p.drawPixmap(0, y, m_lastPixmap); p.drawPixmap(0, y - height(), m_pixmap); p.end(); 18
    • Rotation transform.rotate(30, Qt::ZAxis) 19
    • Perspective Transformation transform.rotate (60, Qt::XAxis) transform.rotate(60, Qt::YAxis) 20
    • Rotating Effect rotating pixmaps 21
    • Rotating Effect: The Code 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(); 22
    • Flipping Effect rotating and interleaving two pixmaps 23
    • A Trick with QBasicTimer QBasicTimer ticker; ticker.start(1000, this); void timerEvent(QTimerEvent*) { // update the clock } No need for QTimer, a slot, and periodic triggering of signal/slot ! 24
    • QTimeLine for Frame-based Animation QTimeLine animator; animator.setFrameRange(0, 100); animator.setDuration(600); animator.setCurveShape(QTimeLine::EaseInOutCurve); int progress = animator.currentFrame(); Linear EaseInOut deacceleration acceleration 25
    • Sacrifice Quality for Speed Beauty is in the eye of the beholder. 26
    • Aliasing during Animation QPainter p(this); p.setRenderHint(QPainter::SmoothPixmapTransform, false); p.setRenderHint(QPainter::Antialiasing, false); 27
    • Example #2 Weather Info
    • Weather Info 29
    • Screen Orientation requires different layout strategy 30
    • Lock the Orientation S60-specific, usually you do NOT need to do this! #include <eikenv.h> #include <eikappui.h> #include <aknenv.h> #include <aknappui.h> CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi()); appUi->SetOrientationL (CAknAppUi::EAppUiOrientationPortrait); 31
    • Animation with Graphics View item movement & opacity 32
    • Using Web Service <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> ... 33
    • Create the Network Request 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)); 34
    • Handle the Network Reply http://www.google.com/ig/api?hl=en&weather=oslo QUrl url = networkReply->url(); data = QString::fromUtf8(networkReply->readAll()); networkReply->deleteLater(); networkReply->manager()->deleteLater(); 35
    • XML Stream Reader for Parsing 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! 36
    • Scalable Icons with SVG bitmap vs vector 37
    • Optimize Your SVG <g> <ellipse cx="10" cy="10" rx=2" ry="2"/> </g> <ellipse cx="10" cy="10" rx=2" ry="2"/> Because one element in a group often does not make sense! 38
    • SVG Loading Time Comparison Use tools like: codedread.com/scour svgmin.googlecode.com 39
    • Example #3 Flight Tracking
    • Flight Tracking 41
    • No Web Service? Use “mobile” version of the web site. 42
    • 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 // remove all inline frames while (true) { i = data.indexOf("<iframe"); if (i < 0) break; data.remove(i, data.indexOf("</iframe>") - i + 8); } 44
    • 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 magnifier 49
    • Shadow with Radial Gradient Prepare the gradient brush 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)); Draw the shadow p.setCompositionMode (QPainter::CompositionMode_Source); p.setBrush(g); p.drawRect(maskPixmap.rect()); Carve the “hole” p.setBrush(QColor(Qt::transparent)); p.drawEllipse(g.center(), radius-15, radius-15); 50
    • Panning with Mouse/Finger/Stylus Record the tap position void mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::LeftButton) return; pressed = true; pressPos = dragPos = event->pos(); } Pan the map based on the movement void mouseMoveEvent(QMouseEvent *event) { if (!event->buttons()) return; QPoint delta = event->pos() - pressPos; pressPos = event->pos(); pan(delta); } 51
    • Avoid Accidental Panning panning is not started past the threshold 52
    • Turbo Downscaling (We're Cheating!) With filtering Fast, no filtering Up to 200x faster, see http://bit.ly/cheatscale for details! 53
    • 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 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); } 57
    • Rendering and Caching Strategy cached tiles application window 58
    • Avoid Accidental Panning panning is not started past the threshold 59
    • Night Mode 60
    • Night Mode: The Code Color channel inversion QPainter p(this); p.setCompositionMode (QPainter::CompositionMode_Difference); p.fillRect(event->rect(), Qt::white); p.end(); red = 255 – red green = 255 – green blue = 255 - blue 61
    • Example #6 Kinetic Scrolling
    • Kinetic Scrolling 63
    • State Machine for Scrolling Mouse move Mouse press Pressed Manual Scroll Mouse release Steady Mouse release Mouse move Auto Scroll Mouse release Mouse press Stop Timer tick 64
    • Example #7 Parallax Sliding
    • Parallax Sliding 66
    • Slow-moving Background 1 5 2 4 3 67
    • 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)! • Use QWebView from QtWebKit • Show the “mobile” version • Add custom login page 71
    • 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 Don't bother “clearing” the widget! setAttribute(Qt::WA_OpaquePaintEvent, true); Faster direct screen access using CDirectScreenBitmap or Anti-Tearing API 76
    • Bypass Alpha-Blending Since we handle each and every pixel, ... QPainter p(this); p.setCompositionMode(QPainter::Composition_Source) p.drawImage(0, 0, buffer); 77
    • Storing Pixels in Image 78
    • Memory Access Optimization Minimize location (in memory) between two vertically separated pixels Jump several Jump few hundreds bytes bytes only 79
    • Inner Loop Approach Use only simple, 12-bits fixed-point arithmetics 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; } 80
    • Conclusion Mobile application development with Qt is FUN 81
    • That's all, folks... Thank You! 82
    • Bleeding-Edge labs.qt.nokia.com bit.ly/graphicsdojo 83