Initial commit.
authoreshe <jessehakanen@gmail.com>
Tue, 13 Jul 2010 19:44:15 +0000 (20:44 +0100)
committereshe <jessehakanen@gmail.com>
Tue, 13 Jul 2010 19:44:15 +0000 (20:44 +0100)
73 files changed:
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/rules [new file with mode: 0644]
jspeed.pro [new file with mode: 0644]
src/abstractscreen.cpp [new file with mode: 0644]
src/abstractscreen.h [new file with mode: 0644]
src/buttonselector.cpp [new file with mode: 0644]
src/buttonselector.h [new file with mode: 0644]
src/data/26x26/jspeed.png [new file with mode: 0644]
src/data/48x48/jspeed.png [new file with mode: 0644]
src/data/64x64/jspeed.png [new file with mode: 0644]
src/data/jspeed.desktop [new file with mode: 0644]
src/detailscreen.cpp [new file with mode: 0644]
src/detailscreen.h [new file with mode: 0644]
src/detailwidget.cpp [new file with mode: 0644]
src/detailwidget.h [new file with mode: 0644]
src/filereader.cpp [new file with mode: 0644]
src/filereader.h [new file with mode: 0644]
src/graphicselement.cpp [new file with mode: 0644]
src/graphicselement.h [new file with mode: 0644]
src/graphicsscene.cpp [new file with mode: 0644]
src/graphicsscene.h [new file with mode: 0644]
src/graphicsscreen.cpp [new file with mode: 0644]
src/graphicsscreen.h [new file with mode: 0644]
src/imageelement.cpp [new file with mode: 0644]
src/imageelement.h [new file with mode: 0644]
src/imageitem.cpp [new file with mode: 0644]
src/imageitem.h [new file with mode: 0644]
src/location.cpp [new file with mode: 0644]
src/location.h [new file with mode: 0644]
src/main.cpp [new file with mode: 0644]
src/mainmenu.cpp [new file with mode: 0644]
src/mainmenu.h [new file with mode: 0644]
src/mainwindow.cpp [new file with mode: 0644]
src/mainwindow.h [new file with mode: 0644]
src/mainwindowstack.cpp [new file with mode: 0644]
src/mainwindowstack.h [new file with mode: 0644]
src/odometer.cpp [new file with mode: 0644]
src/odometer.h [new file with mode: 0644]
src/pointer.cpp [new file with mode: 0644]
src/pointer.h [new file with mode: 0644]
src/reader.cpp [new file with mode: 0644]
src/reader.h [new file with mode: 0644]
src/rectangle.cpp [new file with mode: 0644]
src/rectangle.h [new file with mode: 0644]
src/resources.qrc [new file with mode: 0644]
src/resources/appicon.png [new file with mode: 0644]
src/resources/close.png [new file with mode: 0644]
src/resources/minimize.png [new file with mode: 0644]
src/resources/settings.png [new file with mode: 0644]
src/resources/themes/default/background.png [new file with mode: 0755]
src/resources/themes/default/digital7.ttf [new file with mode: 0755]
src/resources/themes/default/theme.xml [new file with mode: 0755]
src/settings.cpp [new file with mode: 0644]
src/settings.h [new file with mode: 0644]
src/textelement.cpp [new file with mode: 0644]
src/textelement.h [new file with mode: 0644]
src/theme.cpp [new file with mode: 0644]
src/theme.h [new file with mode: 0644]
src/themescreen.cpp [new file with mode: 0644]
src/themescreen.h [new file with mode: 0644]
src/themeselector.cpp [new file with mode: 0644]
src/themeselector.h [new file with mode: 0644]
src/unitselector.cpp [new file with mode: 0644]
src/unitselector.h [new file with mode: 0644]
src/widgetscreen.cpp [new file with mode: 0644]
src/widgetscreen.h [new file with mode: 0644]
src/zipreader.cpp [new file with mode: 0644]
src/zipreader.h [new file with mode: 0644]
welcome [deleted file]

diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..999b76d
--- /dev/null
@@ -0,0 +1,5 @@
+jspeed (0.1-1) unstable; urgency=low
+
+  * Initial release.
+
+ -- Jesse Hakanen <jessehakanen@gmail.com>  Tue, 13 Jul 2010 13:17:36 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..f522be9
--- /dev/null
@@ -0,0 +1,136 @@
+Source: jspeed
+Section: user/utilities
+Priority: optional
+Maintainer: Jesse Hakanen <jessehakanen@gmail.com>
+Build-Depends: debhelper (>= 5), libqt4-dev, libzip-dev, liblocation-dev, libgconf2-dev
+Standards-Version: 3.7.2
+Homepage: http://jspeed.garage.maemo.org
+
+Package: jspeed
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Highly customizable speedometer application.
+XSBC-Bugtracker: https://garage.maemo.org/tracker/?atid=6134&group_id=1756
+XB-Maemo-Display-Name: jSpeed
+XB-Maemo-Icon-26: 
+ iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0
+ d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAFORJREFUeNqkWQmUFNW5/qp6
+ 756Znn0BhmVgWEUBIRE1EvdjlIgGQU9CJLi9RI2JmBgTjca8xMRgkqMh5hnU
+ GEVRMe9A1CSgIrIjCDjIvgwwzM4sPdMz00vVfd9/q7pnJCQnyZs591R11a1b
+ //r933/LUErhSG0bzvRnGAZM08NhwjANuQLTMPnbyN5XynDnocDn80wO+IxR
+ Xh+qvF4M4axcmaeAWCqF4+k0jiST9oFUyt5lK8SUsvks71MGPTjX5jXIOSfY
+ ts1h6Xtn+qsaXggv/t0//ULnlEIXRyLe63LCxmz+nMJRHOuKo6W1E+1t7ejt
+ 69PzwuEQCgoKUFiQj/xoSJ5s4hpbu3vsV3t60m/yvBP/4d+/rYBYxuczx0Sj
+ /u/4fZjV25coWrt2O1avXo2tmzfh2InjaI/F0EvLWTS5QelMnx9hmrqwsBAj
+ KofivAsvLLv8sstnnjt10szciL8xkVSvdXQmn0il7eP/tj3/1RASy/O8oDAa
+ eDAUMu9sbGoNLH15GV5+8Y+oOXYUts+H8Khq+CuHIJJKQ5WVwWtZMPsSSObm
+ QLW2oreLisU60bdrF7wMxcnVYzD/1tswd86X6KFod3fcWtQRSyyiTHFx878S
+ Qv+SAiJ9KOy7orQo+Pt4vHfoU4v/B4ufeRrN3d0oOOccRD57HkK9vfCJkMOG
+ wejoQGT7R4hPngST3ggdOoz2K69AsLkZZiKBRHk50qda0b5/H7o2bkTl4Erc
+ v/A+LLjlZvi83r1Nrb0LEn3pzZI9/28FaHcU5Ifuz4/6H9uy9SPjnoULsfPg
+ fhTNug7FBUXwNTfBCgTRF81D/jvvIllSwky04Wlvh/L7oegFgxmcKi3R3vB1
+ daF11heRu3sPEAmjr6ICHfRIy9o1+PyUaXhq8W8wflx14lR73zdjscQzXOw/
+ V0CeKy3JeTI3x3/3M8/8AQ/84ucIMI4LLr8cYSZpx5hqlCz/ExTDxxZEorBg
+ 3NsULD1sOEDBVTAAxXDxf/KJvgePBxp6eC73Ts28BnlUJpETQeM7qxCMdePJ
+ RU8wrK5De2ffw21tPY8aBv6hAp5HHnkE7R29f3fTZrJq4XMDdz/04KN46LdP
+ YfDUaTBv/iryN2yC//hx5Bw+or3kpcVNGVREINYI56D70kvgM73o/NJ1sAYN
+ QrDuJLydHTCJr2YyCYOKmJaN8L798LY0A3l58MyeDbOxES89/xwiniAuufj8
+ i0WWnt7UWuMMWjAyHBSy+PJPC2+juDDnkTwK/30K/8QrL2Lk+RfCTyuF/rYK
+ ab7cYKikRlYxwmjRYBCKkBn5cButzbzhee7evUgOHYrcj3ZCpVPwd3ZCefg6
+ Ktk76RwETtYjOWQILP4O7NwBi+7OffNtJMeNRyVD8ru/eEzLcu+9dz2STKWb
+ O2N9T2fqz9/BqJW2PmX5SCTwhaLC8A8X/+45PPn8EgxlvPecdRZyXnsdJsNC
+ UMkm2vRMmgQPX9w9fhzCTNTI/v3wiKB8T+TjGoRrdhN2bQ2lOsR8DmonqquR
+ OncqYtPOReBoLYyeHkQ2bUSK6/p64ojdOBeDaaQf/PTHGFJZiTk3XPtET09y
+ RyKR2ny6J3QO7NnXkI15j8eoGDu6fMuaDzZVzpk7B6HLLkOOxDZdH2hphS/e
+ TaN74WFxskZUwcovgEkPgCgU2bVTC6xrr1vxdALqiu2cGzRQ7+hqVnYP+oYM
+ gs1jYNMmoKmRaZFGgvCbpiKp4mL01B6FsWcP3lm1ChPGj6vZd6DhAi7clRF+
+ /NgKR4GaPSfghJLC0CHFS4IBzy2XXHQx9g6vRP7osYi8v4bo0Q0PBfVIDBNd
+ PKIEn/UwQT3iWm1hn0svlINgmh44ymQU0F6W5KaikvQSvhanSgiJAhbzI02o
+ TUajiBN6O1euwMWFJfjLqrfQ1Bx7rLGp4/umx/HCxPGVxEj+pblQkg8H/N7z
+ C/PDt/xq0a+xw1SIBkKwCXtWTi5SI0bAqh6N1NhxMLyOoOIV+GX49fDQ7aKY
+ 1x0ezvN4fM5vrzP0HEl2gVgaxODRFCdpuE3rIzhS9IR57BiiE87CqoP78NyS
+ F1BWmvdNCj86RVlF5mwIbdtxiM/YqB415I+98a555195JbqHDEaQk4KMUW8k
+ gt4HHgAY976GRkSXL0eAR+0JuluE0oTPcMgejEwNEcvb2aPkl1OcbPTwvVXM
+ lxZeb2biyl+KsJpmSFkN9VA1H2shExMmIM4COIw1ZOv6deiKJ544fqL5Po/H
+ xNTJoxwPiEZer1lN639pyXPPo6GtBfbnPofU4MFZ9xq0hnfPXhiMVdAryLDI
+ bMFzjsJa9dFlraKYHjrUnHOLQg4iUl3U1ICYzCXJ67niCsRvugl9M69GatpU
+ nY+KQqZGjYJn+nTsY/Fc+vIrqCjL/wofKUu5wKNhIZlM8Ubh3Hg8EX79jTdg
+ XkIMf/NNGBKPIpCVhn/pUiIgw4FDipFFgubR1Nfsj3k4w1HAgNFf0p0ccfMh
+ wee+dvIE3gmFkAwSy+nlEC1sUhFJYHvfPqm/RC4T3vffhyoqAmZchJdeeAF3
+ 3L6gLDcvck1zc/uzWQVsuqqivHjWmnffxd7ONuT09sEi6fLEumDTrZZtOYK5
+ YSLyeIRo8cQ2nOQUHm8oU4eIAzwGVD8eIUMGunh9VnMjivt6sa6cBU6KMkPE
+ W3dCLKlhOimJLRVbKjepikFPhFkzth/bjV07d2NY1cjZDfXNWgEdQl6vURXw
+ mxPWb9xCQRRSEycizYQVxexMY6FsV1BHQJUVz4VHHfhn4lP9xxRDp4IE8A5W
+ 3teiBTDoAb0YvayY4DbrhPAnxpqzLv/FaNaUyVAjR6I30YdNW7YiPy80ldYq
+ ySoQDgfP4yG48cMtbEsmw/P6cmDzZh37FvFdDwkngT3L4fka8jK/9TXLVZiK
+ 2u5RlLaVhkxRvI/W/XbdcTRR0A25uQhIYlvusJ0kF4jVI5GE4hBw8az4M8yd
+ OwFW8PfeWyMiFwf8vonZEMrNCY9rb+vCIWa/p6IMKjdC/t7CaaUwxoyBCocB
+ chlJYKU82XBQWZx3PaKQLVw64pWRtX4X4/nq+lpcRCs+lJOHNKHZL6HidnkO
+ JDKnSLXFIw5U87TtFNTJkyyehF8qdoQySmQFAv5RfOQ9rUAoFKw61daGDsIa
+ pkxCivHmI8kymTjpOXNhMg6xfgO8bx5nPHqzjYbEuZxnuJRlWFkIFbU0pPIs
+ wWMl6fVCGqC+uARrQ2EEXc5lK9v1llifXiXHSk/7DBKTzta0XLFfUK+8gjT7
+ Ds+RI2gkc21rjyEnkjM064GcSHhQHWGyh52TeaoNnvfedQgaebrBlxmMT4M8
+ xxZYVP3uNgy7P2REcFuaf14XT1gpHWaSHTaf//rRwwhF8/Ein+sMRxCRsMuE
+ mM4rBxSMenr6+DGCBGl5IOB4ng2Sf+nLsC+7FDHOa2HSFxSVFGUVCAb90a54
+ D+zuLg2Naji5PBNNHTzIcUhTX8hiwu0z4ePEix62y3HIqRnPCvGeXgxmozKc
+ bLSTCp6z/gNcTA90lZTiTan40j+kktkQVC4w6OTlPM9f/0oDpJ1csx0eZg8b
+ qru7ZG+P3iwo9QZysgooN1iVYHAZ416CjLycoK8fVl6PpsmSbKZpa1j1WKwF
+ Ei9CAYguvItkymkB71gwH1+eO5sNV9jBKcYwFv8OK5ctQ+2QSkQ0ADjrWG7i
+ awBwE1o8I2Fpu+xYpLNoVFv35maWNWdRqDve1xWhW72ENbO5Bd4NG5ywyVRV
+ J7BdTHR/D7BcBnXi8Tju+fp/4favfVULn8lPkxUdpMaHb7wRNoumKGl/KnxU
+ PywbA4sfnP0oYQpr1ugw8/nZPzAa4r10RUYBJnBDGclTSGKWTNAeNy5LgXWS
+ 6Zc5G05O0mbg00lmsVYP1xtVNQJzrp/1d7VAqn4iBVw//1ZEmFtJgWTxgp12
+ odmFZFlb3s/7NtHKZnWW31L106NZlxqbkOsPoLioBC0tLW3ZEGpr6zw6rnoU
+ 8plkJwWBSN6MEyccYkAhDRifosRKZXbTxPKGfnkf4/KciWeRlPqygi+4ZQHK
+ K4bh1tvuQSthWdhoRcUgHCCvkfNs6AysAfSWTaTTHhHG2dEO1d7BBqoSKb6j
+ nB4sIOX4cMfHdcAYR4HGpub90z97DqrYsJ84dAhmPRsc2VWj5sYXvwjFnlZo
+ NciPNI+XZLXFebI12A+nKeZAZwxM4jgf78XuTw6gvrENm7ay26JVvcypPhZF
+ 7VnbysKx5R5t8QobpNTN86BYse3yCqj166F++QRw4ACpRgJV7E+kM21rbzuc
+ 9UB9Q8MW6ScunH6Bd+2ypQyhscyFZhgtLbCuugpmhPC6d4/evDJEMU2bBevN
+ DBBplrltx3as27iB9aQDLa3NuOa6OVrwXbt26PsJhsXJhpNOWKUdBQYms6CO
+ Vc5CevQYQ7kPqqMTNmE1fe65pAsRYHcNPn/rDHR1W1306O6sAsyBA/UNHQcu
+ mDptvPH6K7DHOgpwJsyf/AQG3aqki2LvKhuiykUJ080ilgMIPz985DBe+9My
+ FsYQw/KUy0ydtJeeoZb43kvPeIha2eKV9QQH0Q5r3gPeWe0ke5q1hO/F2WfD
+ Yhvq2/0xzvvMdNQeO7Yj1hWryyrARdM7a2r+POPCGeNH0z8HpTkn5soCiizR
+ 5IsFKtNMQFP1I4fD+Qm90tC4FHr9xnVMsmKESJMNdxdBlI2xynd2dcrOG62f
+ 0tdkDQdGHdIofCpND2euSYur2IMLsKS3fYhpDOWx4ybijRUr/1d6mCwKyd/u
+ T3a/Fgj6rDmzb4BNBTB1KuyLL3H6WoaO1IJM2bfcF6qM5bJ47mBzE+lyXX2d
+ HifI+0+QwHXEOpxmRkImK3SmkvczXpeLOAWThrFvuAGQfuDoUcz7ys3Mr0TX
+ 4aOHVmQ4mOnsONtM5IaPtm6vefu2ry5AKUOgTxZhJc6yT/eYEmskpPHu052c
+ WDNFDpOSo7jcSuul5TzJeZIDyuHfnJdy56V1DjhNfIJzErqRl2Fp71iaFylW
+ a2P/ASTJXkcWFOCmG+dhw6YNr3d2dhy13Y7MbSmdhzZsWv90xeAyfP3aWbB2
+ 7oA9aiQUH7QIq3phKqHIFqVDskjK0q4gGsddgUQhh2qnneQUj6UdBftpuEMT
+ 9OA6spOt1y0rh80CqOG0uIisOA8WAQUffIB7v3EXKU3A2r5j22IxiKyXVUAS
+ RQjYkaOH//Lu+1tWLFz4PZxN5EkQhdJf+bKDx4IaYk0muLr/ftjz5/MlxbpP
+ cIrQgN4gU5gyfMb9nR7YP8ighW0pUFfPBObNg/Hte2FccqkkJQzmkLr9dlhk
+ BZ+fMgXzv3YH3v7bX59vaW35SCJGJ3fWA7KNIdZl/L296i8PsPPvfPzhR+Ft
+ bIC15n3YeXlO+0hXWoMHwSJzFeKXJiqJcDo0UinX+hlPOCNlpQd4JuWGnBtu
+ 8gwtLxxH8yC+T2+LSezn5SL91luIMD8ef/QxHDxce2LD5vUPS6+Qkbd/a9FK
+ Z6tne3vr3j+89MeF993zjSU/u/UO3PeHZ6HIItWsa+F58SXYy151qLP0wNI1
+ ccEEFdG12v2WJkdl9W+L699uwcheo0F8wnBXrtD7q7J/KjBtV1XBvvtu2OvX
+ EQHr8Nsf/gjDR43Dol//8q6+vp56H4uhBevTe6Mp1x1S3kPk/3v2ffLssuUr
+ z/vWdxfeWkts/82GdfBu20Z+zn5V6oPHhU9BFVbfKy6/AkFylHZCZSZ8ipkn
+ gv0ibxspcpDCChJVMM71RhpDb+26D2iEvuxevjBe2aIUFLSO1eLRBbdj9k3z
+ 8PTvn/3Jyfq6lWHmYnYPdKACK15fqlEixAmVw0ZgcOUwrF6z6s68vLySRYt/
+ e626804sXvU2TFJhT20tLeZ3KrCm1ybKywZB2Gysey8izB2xblFRqbZ2NC+K
+ 9o4dyC8oROWQYciLRnGERikoLZJooLJK1xDtFQkN8n6bBvvRXd/Cwu88gKWv
+ Ln9u58cfPZgkUtUdr0UjoTnO8NXbOE/+Amf8+iH7n4OGDMX5My6NvLTszyvS
+ 7Fh++rNFyu/1SfVSvlBY+cI5yhfJUd5IrsorLVf5FYNVsLBYhYpKVPmIkapk
+ 6AiVU1KmIsWlKsTrcu6PFvBYqudGywcpX25U+XPzOKJ6MJRUXl5U/W7JC6o3
+ odSvFz///PQZl3orh1eRJAbO8AFG4R9+vhmgjP97P/jv3ydSSq1+9wNVPWac
+ Ju5supVXKxJRXg4Phwjko0AerRhHTq5W0MejR8/jtVBEmYGQ8gZDjhF43fQF
+ 9JpTPjtdbd1Wo1rbkmrBbXc9LrnzT7+Y/hMFxKfydc/nHo0vXHP9t/cdbIif
+ au9V9z/wkMovLMoqIoL4KbA/Jy87AnIU4eW6CCrKaoXDVMJRwPB49Rqlg4eo
+ nz7+K9XZZakNm3efmn7BjPkZ+7nDxBl2nc6kgOnmhWwayFf2Yo7B8jmKY2hp
+ WcXcny9a/GFre1odOtKoHnz4x2pE9WilO3noXShl+Py0cJAChp1Ba3v429Dh
+ Z/bvhjEUx06YqB6j4Mfq2jhi6jvf+9GavGj+lbxfIe/jKOPIl60r15ifUkTz
+ sf59TX1DhJdgk8/pOa4See4i+e71/PFnTbroG3fde/7Ma64tDAZ82Lp1E956
+ eyVqanah7mQdm5dW9LInEDqgvy8TjQQgSlh1KyuHYvLkc/GFq2Zi8pTPELY7
+ 1PI3Xm1a8sxT79UeObSB68eEX3J0cHS6v+WjhrSQAlmpjBFOVyATMhFX8AKO
+ IncUu8cS91yUKq4YNGTQVVfPKpo58/rgxIlnG1EiTJKw2MpeoKm5SXdp8q5Q
+ MIxyFqwislSmFFpPncKOHdvtlSve6Fm96q3GtlMt8oWl1RW49bTR5g651+0q
+ YZ1JAfM0BfIHKFE84JgZha6XxL3BsvJB/vETzvZXjaz2VlWN8paVVRhs7OXz
+ GLriXaqhvt4+cuRg+vChA6m9e2qSFDrB5+KuULHThD414CjCt7tz4v9MgUzi
+ +t0cCJ8WRlFXqeiAkMpzFQ64I5P03oFU3XW5vDTtjqR863PDotu1bseAsOlw
+ BY659+NuWCXc588YQtldkAFC+FyF/ANyI+gew+55cMAc32nIMVAB21Ui5Y6M
+ Er2njT53JNw5SVdoy13DHpjE/yfAAFGSmo2CjwzbAAAAAElFTkSuQmCC
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..8e8e2e4
--- /dev/null
@@ -0,0 +1,14 @@
+Copyright (c) 2010 Jesse Hakanen <jessehakanen@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..80507f1
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/share/applications/hildon
diff --git a/debian/rules b/debian/rules
new file mode 100644 (file)
index 0000000..64396e2
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/make -f
+APPNAME := jspeed
+builddir:
+       mkdir -p builddir
+
+builddir/Makefile: builddir
+       cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro
+
+build: build-stamp
+
+build-stamp: builddir/Makefile
+       dh_testdir
+       # Add here commands to compile the package.
+       cd builddir && $(MAKE)
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp
+       # Add here commands to clean up after the build process.
+       rm -rf builddir
+       dh_clean
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+# Add here commands to install the package into debian/your_appname
+       cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installdocs
+       dh_installexamples
+       dh_installman
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/jspeed.pro b/jspeed.pro
new file mode 100644 (file)
index 0000000..b770792
--- /dev/null
@@ -0,0 +1,89 @@
+QT += maemo5 xml
+TARGET = jspeed
+TEMPLATE = app
+SOURCES += src/main.cpp \ 
+           src/mainwindow.cpp \
+           src/mainwindowstack.cpp \
+           src/location.cpp \
+           src/graphicsscreen.cpp \
+           src/abstractscreen.cpp \
+           src/widgetscreen.cpp \
+           src/imageitem.cpp \
+           src/reader.cpp \
+           src/zipreader.cpp \
+           src/filereader.cpp \
+           src/graphicselement.cpp \
+           src/textelement.cpp \
+           src/imageelement.cpp \
+           src/rectangle.cpp \
+           src/pointer.cpp \
+           src/odometer.cpp \
+           src/theme.cpp \
+           src/themescreen.cpp \
+           src/settings.cpp \
+           src/detailwidget.cpp \
+           src/detailscreen.cpp \
+           src/graphicsscene.cpp \
+           src/mainmenu.cpp \
+           src/buttonselector.cpp \
+           src/themeselector.cpp \
+           src/unitselector.cpp
+HEADERS += src/mainwindow.h \
+           src/mainwindowstack.h \
+           src/location.h \
+           src/graphicsscreen.h \
+           src/abstractscreen.h \
+           src/widgetscreen.h \
+           src/imageitem.h \
+           src/reader.h \
+           src/zipreader.h \
+           src/filereader.h \
+           src/graphicselement.h \
+           src/textelement.h \
+           src/imageelement.h \
+           src/rectangle.h \
+           src/pointer.h \
+           src/odometer.h \
+           src/theme.h \
+           src/themescreen.h \
+           src/settings.h \
+           src/detailwidget.h \
+           src/detailscreen.h \
+           src/graphicsscene.h \
+           src/mainmenu.h \
+           src/buttonselector.h \
+           src/themeselector.h \
+           src/unitselector.h
+RESOURCES = src/resources.qrc
+CONFIG += link_pkgconfig
+PKGCONFIG += liblocation libzip
+
+unix {
+  #VARIABLES
+  isEmpty(PREFIX) {
+    PREFIX = /usr
+  }
+
+  BINDIR = $$PREFIX/bin
+  DATADIR =$$PREFIX/share
+
+  DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\"
+
+  #MAKE INSTALL
+
+  INSTALLS += target desktop icon26 icon48 icon64
+
+  target.path =$$BINDIR
+
+  desktop.path = $$DATADIR/applications/hildon
+  desktop.files += src/data/$${TARGET}.desktop
+
+  icon26.path = $$DATADIR/icons/hicolor/26x26/apps
+  icon26.files += src/data/26x26/$${TARGET}.png
+
+  icon48.path = $$DATADIR/icons/hicolor/48x48/apps
+  icon48.files += src/data/48x48/$${TARGET}.png
+
+  icon64.path = $$DATADIR/icons/hicolor/64x64/apps
+  icon64.files += src/data/64x64/$${TARGET}.png
+}
diff --git a/src/abstractscreen.cpp b/src/abstractscreen.cpp
new file mode 100644 (file)
index 0000000..4c9097e
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "abstractscreen.h"
+
+AbstractScreen::AbstractScreen(){}
diff --git a/src/abstractscreen.h b/src/abstractscreen.h
new file mode 100644 (file)
index 0000000..fe22f04
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ABSTRACTSCREEN_H
+#define ABSTRACTSCREEN_H
+
+class AbstractScreen
+{
+public:
+    AbstractScreen();
+    virtual void reArrange() = 0;
+    virtual void flip() = 0;
+};
+
+#endif
diff --git a/src/buttonselector.cpp b/src/buttonselector.cpp
new file mode 100644 (file)
index 0000000..c1adde3
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QDebug>
+#include "buttonselector.h"
+
+ButtonSelector::ButtonSelector(QString const& text, QWidget* parent):
+QMaemo5ValueButton(text, parent), selector_(0), model_(0)
+{
+    setValueLayout(QMaemo5ValueButton::ValueBesideText);
+    selector_ = new QMaemo5ListPickSelector(this);
+    connect(selector_, SIGNAL(selected(QString const&)), this, SLOT(onSelected(QString const&)));
+    model_ = new QStandardItemModel(0, 1);
+    selector_->setModel(model_);
+    setPickSelector(selector_);
+}
+
+void ButtonSelector::addItem(QString const& text)
+{
+    addItem(text, QVariant(text));
+}
+
+void ButtonSelector::addItem(QString const& text, QVariant const& value)
+{
+    QStandardItem* item = new QStandardItem(text);
+    item->setData(value, Qt::UserRole);
+    item->setTextAlignment(Qt::AlignCenter);
+    item->setEditable(false);
+    model_->appendRow(item);
+
+    if(selector_->currentIndex() < 0)
+    {
+        selector_->setCurrentIndex(0);
+    }
+
+}
+
+void ButtonSelector::clear()
+{
+    model_->clear();
+}
+
+void ButtonSelector::setCurrentIndex(unsigned int index)
+{
+    selector_->setCurrentIndex(index);
+}
+
+int ButtonSelector::indexOfValue(QVariant const& value) const
+{
+    for(int i = 0; i < model_->rowCount(); i++)
+    {
+        QStandardItem* item = model_->item(i);
+
+        if(item && item->data(Qt::UserRole) == value)
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+bool ButtonSelector::selectByValue(QVariant const& value)
+{
+    int index = indexOfValue(value);
+
+    if(index < 0)
+    {
+        return false;
+    }
+
+    setCurrentIndex(index);
+
+    return true;
+}
+
+int ButtonSelector::currentIndex() const
+{
+    return selector_->currentIndex();
+}
+
+QString ButtonSelector::text() const
+{
+    return selector_->currentValueText();
+}
+
+QVariant ButtonSelector::value() const
+{
+    int currentIndex = selector_->currentIndex();
+
+    if(currentIndex < 0)
+    {
+        return QVariant("");
+    }
+
+    QStandardItem* item = model_->item(currentIndex);
+
+    return item->data(Qt::UserRole);
+}
+
+bool ButtonSelector::changeItem(unsigned int index,
+                                QString const& text)
+{
+    return changeItem(index, text, QVariant(text));
+}
+
+bool ButtonSelector::changeItem(unsigned int index,
+                                QString const& text,
+                                QVariant const& value)
+{
+    QStandardItem* item = model_->item(index);
+
+    if(!item)
+    {
+        return false;
+    }
+
+    item->setText(text);
+    item->setData(value, Qt::UserRole);
+
+    return true;
+}
+
+bool ButtonSelector::removeItem(unsigned int index)
+{
+    return model_->removeRow(index);
+}
+
+void ButtonSelector::onSelected(QString const& text)
+{
+    emit selected(currentIndex(), text, value());
+}
diff --git a/src/buttonselector.h b/src/buttonselector.h
new file mode 100644 (file)
index 0000000..e36c159
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BUTTONSELECTOR_H
+#define BUTTONSELECTOR_H
+
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+#include <QtGui/QStandardItemModel>
+#include <QMaemo5ValueButton>
+#include <QMaemo5ListPickSelector>
+
+class ButtonSelector : public QMaemo5ValueButton
+{
+
+Q_OBJECT
+
+public:
+    ButtonSelector(QString const& text, QWidget* parent = 0);
+    void addItem(QString const& text);
+    void addItem(QString const& text, QVariant const& value);
+    void clear();
+    void setCurrentIndex(unsigned int index);
+    int indexOfValue(QVariant const& value) const;
+    bool selectByValue(QVariant const& value);
+    int currentIndex() const;
+    bool changeItem(unsigned int index, QString const& text);
+    bool changeItem(unsigned int index, QString const& text, QVariant const& value);
+    bool removeItem(unsigned int index);
+    bool setValue(unsigned int index);
+    QString text() const;
+    QVariant value() const;
+
+signals:
+    void selected(unsigned int index, QString const& text, QVariant const& value);
+
+private slots:
+    void onSelected(QString const& text);
+
+private:
+    QMaemo5ListPickSelector* selector_;
+    QStandardItemModel* model_;
+
+};
+
+#endif
diff --git a/src/data/26x26/jspeed.png b/src/data/26x26/jspeed.png
new file mode 100644 (file)
index 0000000..ab74e4b
Binary files /dev/null and b/src/data/26x26/jspeed.png differ
diff --git a/src/data/48x48/jspeed.png b/src/data/48x48/jspeed.png
new file mode 100644 (file)
index 0000000..0ffdd33
Binary files /dev/null and b/src/data/48x48/jspeed.png differ
diff --git a/src/data/64x64/jspeed.png b/src/data/64x64/jspeed.png
new file mode 100644 (file)
index 0000000..b431a07
Binary files /dev/null and b/src/data/64x64/jspeed.png differ
diff --git a/src/data/jspeed.desktop b/src/data/jspeed.desktop
new file mode 100644 (file)
index 0000000..e22e0e2
--- /dev/null
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Name=jSpeed
+Exec=/usr/bin/jspeed
+Icon=jspeed
+X-Window-Icon=jspeed
+X-Window-Icon-Dimmed=jspeed
diff --git a/src/detailscreen.cpp b/src/detailscreen.cpp
new file mode 100644 (file)
index 0000000..1c3cd10
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QGraphicsTextItem>
+#include <QtGui/QGraphicsLineItem>
+#include <QtGui/QGraphicsView>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <math.h>
+#include "detailscreen.h"
+#include "odometer.h"
+#include "graphicsscene.h"
+
+namespace
+{
+    QString const FONT = "Tahoma";
+    QString const BACKGROUND = ":/resources/themes/default/background.png";
+    int const FONT_SIZE = 20;
+    int const PADDING_LEFT = 40;
+    int const START_HEIGHT = 80;
+    int const ITEM_WIDTH = 130;
+}
+
+DetailScreen::DetailScreen(QWidget* parent): GraphicsScreen(parent)
+{
+    QString unit = Odometer::getUnit();
+    QString speedUnit = Odometer::getSpeedUnit();
+
+    QGraphicsPixmapItem* background = new QGraphicsPixmapItem(QPixmap(BACKGROUND));
+    getScene()->addItem(background);
+
+    tripLabel_ = createItem(tr("Trip"));
+    trip_ = createItem(roundDouble(Odometer::instance().getTrip()));
+    tripUnit_ = createItem(unit);
+
+    totalLabel_ = createItem(tr("Total"));
+    total_ = createItem(roundDouble(Odometer::instance().getTotal()));
+    totalUnit_ = createItem(unit);
+
+    speedLabel_ = createItem(tr("Speed"));
+    speed_ = createItem(roundDouble(0.0));
+    speedUnit_ = createItem(speedUnit);
+
+    avgSpeedLabel_ = createItem(tr("Average speed"));
+    avgSpeed_ = createItem(roundDouble(Odometer::instance().getAverageSpeed()));
+    avgSpeedUnit_ = createItem(speedUnit);
+
+    maxSpeedLabel_ = createItem(tr("Max speed"));
+    maxSpeed_ = createItem(roundDouble(Odometer::instance().getMaxSpeed()));
+    maxSpeedUnit_ = createItem(speedUnit);
+
+    tripTimeLabel_ = createItem(tr("Trip time"));
+    tripTime_ = createItem(formatTime(Odometer::instance().getTripTime()));
+
+    totalTimeLabel_ = createItem(tr("Total time"));
+    totalTime_ = createItem(formatTime(Odometer::instance().getTotalTime()));
+
+    line1_ = createLine();
+    line2_ = createLine();
+
+    connect(&(Odometer::instance()), SIGNAL(timeUpdated()), this, SLOT(updateTime()));
+    connect(&(Odometer::instance()), SIGNAL(unitChanged()), this, SLOT(updateUnits()));
+
+    reArrange();
+}
+
+void DetailScreen::update()
+{
+    speed_->setPlainText(roundDouble(Odometer::instance().getLatestFix().speed));
+    trip_->setPlainText(roundDouble(Odometer::instance().getTrip()));
+    total_->setPlainText(roundDouble(Odometer::instance().getTotal()));
+    avgSpeed_->setPlainText(roundDouble(Odometer::instance().getAverageSpeed()));
+    maxSpeed_->setPlainText(roundDouble(Odometer::instance().getMaxSpeed()));
+}
+
+void DetailScreen::updateTime()
+{
+    tripTime_->setPlainText(formatTime(Odometer::instance().getTripTime()));
+    totalTime_->setPlainText(formatTime(Odometer::instance().getTotalTime()));
+}
+
+void DetailScreen::updateUnits()
+{
+    QString unit = Odometer::getUnit();
+    QString speedUnit = Odometer::getSpeedUnit();
+
+    tripUnit_->setPlainText(unit);
+    totalUnit_->setPlainText(unit);
+    speedUnit_->setPlainText(speedUnit);
+    avgSpeedUnit_->setPlainText(speedUnit);
+    maxSpeedUnit_->setPlainText(speedUnit);
+
+    update();
+}
+
+void DetailScreen::reArrange()
+{
+    GraphicsScreen::reArrange();
+
+    int lineHeight = getScene()->height() / 9;
+
+    int area1 = (getScene()->width() / 3) + ITEM_WIDTH / 2 + 20;
+    int area2 = area1 + ITEM_WIDTH;
+
+    tripLabel_->setPos(PADDING_LEFT, START_HEIGHT);
+    trip_->setPos(area1, START_HEIGHT);
+    tripUnit_->setPos(area2, START_HEIGHT);
+
+    totalLabel_->setPos(PADDING_LEFT, START_HEIGHT + lineHeight);
+    total_->setPos(area1, START_HEIGHT + lineHeight);
+    totalUnit_->setPos(area2, START_HEIGHT + lineHeight);
+
+    speedLabel_->setPos(PADDING_LEFT, START_HEIGHT + 2 * lineHeight);
+    speed_->setPos(area1, START_HEIGHT + 2 * lineHeight);
+    speedUnit_->setPos(area2, START_HEIGHT + 2 * lineHeight);
+
+    avgSpeedLabel_->setPos(PADDING_LEFT, START_HEIGHT + 3 * lineHeight);
+    avgSpeed_->setPos(area1, START_HEIGHT + 3 * lineHeight);
+    avgSpeedUnit_->setPos(area2, START_HEIGHT + 3 * lineHeight);
+
+    maxSpeedLabel_->setPos(PADDING_LEFT, START_HEIGHT + 4 * lineHeight);
+    maxSpeed_->setPos(area1, START_HEIGHT + 4 * lineHeight);
+    maxSpeedUnit_->setPos(area2, START_HEIGHT + 4 * lineHeight);
+
+    tripTimeLabel_->setPos(PADDING_LEFT, START_HEIGHT + 5 * lineHeight);
+    tripTime_->setPos(area1, START_HEIGHT + 5 * lineHeight);
+
+    totalTimeLabel_->setPos(PADDING_LEFT, START_HEIGHT + 6 * lineHeight);
+    totalTime_->setPos(area1, START_HEIGHT + 6 * lineHeight);
+
+    int y1 = START_HEIGHT + 2 * lineHeight - lineHeight / 2 + FONT_SIZE + 2;
+    int y2 = START_HEIGHT + 5 * lineHeight - lineHeight / 2 + FONT_SIZE + 2;
+    int x = getScene()->width() - PADDING_LEFT;
+    line1_->setLine(PADDING_LEFT + 2, y1, x, y1);
+    line2_->setLine(PADDING_LEFT + 2, y2, x, y2);
+}
+
+QGraphicsTextItem* DetailScreen::createItem(QString const& text)
+{
+    QGraphicsTextItem* item = new QGraphicsTextItem(text);
+    QFont font(FONT, FONT_SIZE);
+    font.setBold(true);
+    item->setFont(font);
+    item->setDefaultTextColor(QColor("#fff"));
+    getScene()->addItem(item);
+    return item;
+}
+
+QGraphicsLineItem* DetailScreen::createLine()
+{
+    QGraphicsLineItem* item = new QGraphicsLineItem;
+    QPen pen(QColor("#ddd"));
+    pen.setWidth(1);
+    item->setPen(pen);
+    getScene()->addItem(item);
+    return item;
+}
+
+QString DetailScreen::roundDouble(double number)
+{
+    QString result;
+    result.sprintf("%.2lf", number);
+    return result;
+}
+
+QString DetailScreen::formatTime(qulonglong time)
+{
+    qulonglong secs = time % 60;
+    qulonglong mins_tmp = time / 60;
+    qulonglong mins = mins_tmp % 60;
+    qulonglong hours = mins_tmp / 60;
+
+    static char format[] = "%02d";
+
+    return QString().sprintf(format, hours) + ":" +
+           QString().sprintf(format, mins) + ":" +
+           QString().sprintf(format, secs);
+}
diff --git a/src/detailscreen.h b/src/detailscreen.h
new file mode 100644 (file)
index 0000000..4c30e75
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DETAILSCREEN_H
+#define DETAILSCREEN_H
+
+#include "location.h"
+#include "graphicsscreen.h"
+
+class QGraphicsTextItem;
+class QGraphicsLineItem;
+class QGraphicsView;
+class GraphicsScene;
+
+class DetailScreen : public GraphicsScreen
+{
+    Q_OBJECT
+
+public:
+    DetailScreen(QWidget* parent = 0);
+
+public slots:
+    virtual void update();
+    void reArrange();
+
+private slots:
+    void updateTime();
+    void updateUnits();
+
+private:
+    QString formatTime(qulonglong time);
+    QGraphicsTextItem* createItem(QString const& text);
+    QGraphicsLineItem* createLine();
+    QString roundDouble(double number);
+    QGraphicsTextItem* tripLabel_;
+    QGraphicsTextItem* trip_;
+    QGraphicsTextItem* tripUnit_;
+    QGraphicsTextItem* totalLabel_;
+    QGraphicsTextItem* total_;
+    QGraphicsTextItem* totalUnit_;
+    QGraphicsTextItem* speedLabel_;
+    QGraphicsTextItem* speed_;
+    QGraphicsTextItem* speedUnit_;
+    QGraphicsTextItem* avgSpeedLabel_;
+    QGraphicsTextItem* avgSpeed_;
+    QGraphicsTextItem* avgSpeedUnit_;
+    QGraphicsTextItem* maxSpeedLabel_;
+    QGraphicsTextItem* maxSpeed_;
+    QGraphicsTextItem* maxSpeedUnit_;
+    QGraphicsTextItem* tripTimeLabel_;
+    QGraphicsTextItem* tripTime_;
+    QGraphicsTextItem* totalTimeLabel_;
+    QGraphicsTextItem* totalTime_;
+    QGraphicsLineItem* line1_;
+    QGraphicsLineItem* line2_;
+};
+
+#endif
diff --git a/src/detailwidget.cpp b/src/detailwidget.cpp
new file mode 100644 (file)
index 0000000..4a6f523
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "detailwidget.h"
+#include "detailscreen.h"
+
+DetailWidget::DetailWidget(QWidget* parent): WidgetScreen(parent)
+{
+    screen_ = new DetailScreen;
+    connect(screen_, SIGNAL(minimizePressed()), this, SIGNAL(minimizePressed()));
+    connect(screen_, SIGNAL(settingsPressed()), this, SIGNAL(settingsPressed()));
+    connect(screen_, SIGNAL(closePressed()), this, SIGNAL(closePressed()));
+    connect(screen_, SIGNAL(clicked()), this, SIGNAL(clicked()));
+    addWidget(screen_);
+}
+
+void DetailWidget::update()
+{
+    screen_->update();
+}
+
+void DetailWidget::reArrange()
+{
+    screen_->reArrange();
+}
+
+void DetailWidget::flip()
+{
+    screen_->flip();
+}
diff --git a/src/detailwidget.h b/src/detailwidget.h
new file mode 100644 (file)
index 0000000..037c60d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DETAILWIDGET_H
+#define DETAILWIDGET_H
+
+#include "widgetscreen.h"
+
+class DetailScreen;
+
+class DetailWidget : public WidgetScreen
+{
+    Q_OBJECT
+
+public:
+    DetailWidget(QWidget* parent = 0);
+
+public slots:
+    virtual void update();
+    void reArrange();
+    void flip();
+
+private:
+    DetailScreen* screen_;
+};
+
+#endif
diff --git a/src/filereader.cpp b/src/filereader.cpp
new file mode 100644 (file)
index 0000000..0cd9054
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include "filereader.h"
+
+FileReader::FileReader(QString const& dirname): Reader(), dirname_(dirname)
+{
+}
+
+bool FileReader::open()
+{
+    return true;
+}
+
+bool FileReader::readFile(QString const& filename, QByteArray& data)
+{
+    QFile file(dirname_ + QDir::separator() + filename);
+
+    if(!file.exists())
+    {
+        error_ = "No such file: " + filename;
+        return false;
+    }
+
+    if(file.open(QIODevice::ReadOnly))
+    {
+        data = file.readAll();
+    }
+    else
+    {
+        error_ = "Unable to open file: " + filename;
+        return false;
+    }
+
+    file.close();
+    return true;
+}
+
+bool FileReader::fileExists(QString const& filename) const
+{
+    return QFile::exists(dirname_ + QDir::separator() + filename);
+}
+
+bool FileReader::close()
+{
+    return true;
+}
+
+QString const& FileReader::errorString() const
+{
+    return error_;
+}
diff --git a/src/filereader.h b/src/filereader.h
new file mode 100644 (file)
index 0000000..dc118d4
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FILEREADER_H
+#define FILEREADER_H
+
+class QString;
+class QByteArray;
+
+#include "reader.h"
+
+class FileReader : public Reader
+{
+public:
+    FileReader(QString const& dirname);
+    bool open();
+    bool readFile(QString const& filename, QByteArray& data);
+    bool fileExists(QString const& filename) const;
+    bool close();
+    QString const& errorString() const;
+
+private:
+    QString dirname_;
+    QString error_;
+};
+
+#endif
diff --git a/src/graphicselement.cpp b/src/graphicselement.cpp
new file mode 100644 (file)
index 0000000..b290d87
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QMap>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+#include "graphicselement.h"
+#include "reader.h"
+#include "textelement.h"
+#include "imageelement.h"
+#include "rectangle.h"
+#include "pointer.h"
+#include "settings.h"
+
+GraphicsElement::GraphicsElement(Reader* reader): reader_(reader), error_("")
+{
+}
+
+GraphicsElement* GraphicsElement::getElement(QString const& name, Reader* reader)
+{
+    if(name == "image")
+    {
+        return new ImageElement(reader);
+    }
+
+    if(name == "text")
+    {
+        return new TextElement(reader);
+    }
+
+    if(name == "rectangle")
+    {
+        return new Rectangle(reader);
+    }
+
+    if(name == "pointer")
+    {
+        bool animate = Settings::instance().value("animate_pointer", true).toBool();
+        return new Pointer(reader, animate);
+    }
+
+    qDebug() << "Element not found: " << name;
+    return 0;
+}
+
+QString const& GraphicsElement::getError() const
+{
+    return error_;
+}
+
+void GraphicsElement::setError(QString const& error)
+{
+    error_ = error;
+}
+
+bool GraphicsElement::readFile(QString const& filename, QByteArray& data)
+{
+
+    if(!reader_->readFile(filename, data))
+    {
+        setError(reader_->errorString());
+        return false;
+    }
+
+    return true;
+}
+
+bool GraphicsElement::getFont(QString const& name, QFont& font)
+{
+    QByteArray data;
+
+    QMap<QString, QString>::const_iterator it = loadedFonts_.find(name);
+
+    if(it != loadedFonts_.end())
+    {
+        font = QFont(it.value());
+        return true;
+    }
+
+    if(!reader_->fileExists(name))
+    {
+        font = QFont(name);
+        return true;
+    }
+
+    if(!readFile(name, data))
+    {
+        return false;
+    }
+
+    int id = QFontDatabase::addApplicationFontFromData(data);
+
+    if(id == -1)
+    {
+        setError("Unable to load font: " + name);
+        loadedFonts_[name] = "";
+        return false;
+    }
+
+    QStringList families = QFontDatabase::applicationFontFamilies(id);
+
+    if(families.size() == 0)
+    {
+        setError("No fonts found in " + name);
+        return false;
+    }
+
+    loadedFonts_[name] = families.at(0);
+    font = QFont(families.at(0));
+
+    return true;
+}
+
+int GraphicsElement::getAttribute(QString const& name,
+                                  QString const& value,
+                                  const GraphicsElement::AttributeDetails details[],
+                                  int count,
+                                  int& intValue)
+{
+    QString lower = name.toLower();
+
+    for(int i = 0; i < count; i++)
+    {
+        if(details[i].name == lower)
+        {
+            if(!details[i].isInt)
+            {
+                return i;
+            }
+            else
+            {
+                bool ok = true;
+                int tmp = value.toInt(&ok);
+
+                if(ok)
+                {
+                    intValue = tmp;
+                    return i;
+                }
+                else
+                {
+                    setError("Value for " + name + " is not integer ("+value+")");
+                    return -1;
+                }
+            }
+        }
+    }
+
+    setError("Unknown attribute: " + name);
+    return -1;
+}
diff --git a/src/graphicselement.h b/src/graphicselement.h
new file mode 100644 (file)
index 0000000..fbd7858
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GRAPHICSELEMENT_H
+#define GRAPHICSELEMENT_H
+
+#include <QtCore/QMap>
+#include "location.h"
+
+class QString;
+class QByteArray;
+class GraphicsScene;
+class Reader;
+class QFont;
+
+class GraphicsElement
+{
+public:
+
+    struct AttributeDetails
+    {
+        QString name;
+        bool isInt;
+    };
+
+    GraphicsElement(Reader* reader);
+    static GraphicsElement* getElement(QString const& name, Reader* reader);
+    virtual bool setAttribute(QString const& name, QString const& value) = 0;
+    virtual void addToScene(GraphicsScene* scene) = 0;
+    virtual void update() = 0;
+    QString const& getError() const;
+
+protected:
+    int getAttribute(QString const& name, QString const& value, const AttributeDetails details[], int count, int& intValue);
+    void setError(QString const& error);
+    bool readFile(QString const& name, QByteArray& data);
+    bool getFont(QString const& name, QFont& font);
+
+private:
+    Reader* reader_;
+    QString error_;
+    QMap<QString, QString> loadedFonts_;
+};
+
+#endif
diff --git a/src/graphicsscene.cpp b/src/graphicsscene.cpp
new file mode 100644 (file)
index 0000000..d512944
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QGraphicsSceneMouseEvent>
+#include "graphicsscene.h"
+
+GraphicsScene::GraphicsScene(QRectF const& rect): QGraphicsScene(rect)
+{
+}
+
+void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    QGraphicsScene::mousePressEvent(event);
+
+    QPointF pos = event->screenPos();
+
+    if(pos.x() > CLICK_MARGIN && pos.x() < (width() - CLICK_MARGIN) &&
+       pos.y() > CLICK_MARGIN && pos.y() < (height() - CLICK_MARGIN))
+    {
+        emit clicked();
+    }
+}
diff --git a/src/graphicsscene.h b/src/graphicsscene.h
new file mode 100644 (file)
index 0000000..d5ac6d7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GRAPHICSSCENE_H
+#define GRAPHICSSCENE_H
+
+#include <QtGui/QGraphicsScene>
+
+class QGraphicsSceneMouseEvent;
+
+class GraphicsScene : public QGraphicsScene
+{
+    Q_OBJECT
+
+public:
+    GraphicsScene(QRectF const& rect);
+    static int const CLICK_MARGIN = 45;
+
+signals:
+    void clicked();
+
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
+
+};
+
+#endif
diff --git a/src/graphicsscreen.cpp b/src/graphicsscreen.cpp
new file mode 100644 (file)
index 0000000..19dfb36
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QApplication>
+#include "graphicsscreen.h"
+#include "imageitem.h"
+#include "graphicsscene.h"
+#include "odometer.h"
+
+namespace
+{
+    int const PADDING = 8;
+}
+
+GraphicsScreen::GraphicsScreen(QWidget* parent): QGraphicsView(parent),
+AbstractScreen(), scene_(0)
+{
+    QRect rect = QApplication::desktop()->availableGeometry();
+
+    scene_ = new GraphicsScene(QRect(QPoint(0, 0), rect.size()));
+    setScene(scene_);
+
+    connect(scene_, SIGNAL(clicked()), this, SIGNAL(clicked()));
+
+    minimizeButton_ = new ImageItem(":/resources/minimize.png");
+    minimizeButton_->setZValue(9999);
+    scene_->addItem(minimizeButton_);
+    connect(minimizeButton_, SIGNAL(clicked()), this, SIGNAL(minimizePressed()));
+
+    imageWidth_ = minimizeButton_->pixmap().width();
+
+    closeButton_ = new ImageItem(":/resources/close.png");
+    closeButton_->setZValue(9999);
+    scene_->addItem(closeButton_);
+    connect(closeButton_, SIGNAL(clicked()), this, SIGNAL(closePressed()));
+
+    settingsButton_ = new ImageItem(":/resources/settings.png");
+    settingsButton_->setZValue(9999);
+    scene_->addItem(settingsButton_);
+    connect(settingsButton_, SIGNAL(clicked()), this, SIGNAL(settingsPressed()));
+
+    reArrange();
+
+    connect(&(Odometer::instance()), SIGNAL(dataUpdated()), this, SLOT(update()));
+    connect(&(Odometer::instance()), SIGNAL(unitChanged()), this, SLOT(update()));
+}
+
+GraphicsScreen::~GraphicsScreen()
+{
+}
+
+void GraphicsScreen::reArrange()
+{
+    QRect rect = QApplication::desktop()->screenGeometry();
+    scene_->setSceneRect(rect);
+    minimizeButton_->setPos(PADDING, PADDING);
+    closeButton_->setPos(rect.width() - imageWidth_ - PADDING, PADDING);
+    settingsButton_->setPos((rect.width() / 2) - (imageWidth_ / 2) - (PADDING / 2), PADDING);
+}
+
+void GraphicsScreen::flip()
+{
+    if(isTransformed())
+    {
+        resetMatrix();
+        return;
+    }
+
+    setTransform(QTransform(1, 0, 0, 0, -1, 0, 0, 0, 1));
+}
+
+GraphicsScene* GraphicsScreen::getScene() const
+{
+    return scene_;
+}
diff --git a/src/graphicsscreen.h b/src/graphicsscreen.h
new file mode 100644 (file)
index 0000000..75947a7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GRAPHICSSCREEN_H
+#define GRAPHICSSCREEN_H
+
+#include <QtGui/QGraphicsView>
+#include "abstractscreen.h"
+#include "location.h"
+#include "imageitem.h"
+
+class QGraphicsScene;
+class GraphicsScene;
+
+class GraphicsScreen : public QGraphicsView, public AbstractScreen
+{
+    Q_OBJECT
+
+public:
+    enum Orientation {LANDSCAPE, PORTRAIT};
+    GraphicsScreen(QWidget* parent = 0);
+    virtual ~GraphicsScreen();
+
+signals:
+    void minimizePressed();
+    void settingsPressed();
+    void closePressed();
+    void clicked();
+
+public slots:
+    virtual void update() = 0;
+    virtual void reArrange();
+    void flip();
+
+protected:
+    GraphicsScene* getScene() const;
+
+private:
+    GraphicsScene* scene_;
+    ImageItem* minimizeButton_;
+    ImageItem* settingsButton_;
+    ImageItem* closeButton_;
+    int imageWidth_;
+};
+
+#endif
diff --git a/src/imageelement.cpp b/src/imageelement.cpp
new file mode 100644 (file)
index 0000000..2002666
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsPixmapItem>
+#include "imageelement.h"
+#include "reader.h"
+#include "graphicsscene.h"
+
+namespace
+{
+    const GraphicsElement::AttributeDetails ATTRIBUTES[ImageElement::ATTRIBUTE_COUNT] =
+    {
+     {"xpos", true},
+     {"ypos", true},
+     {"src", false}
+    };
+}
+
+ImageElement::ImageElement(Reader* reader): GraphicsElement(reader)
+{
+    element_ = new QGraphicsPixmapItem();
+}
+
+bool ImageElement::setAttribute(QString const& name,
+                                QString const& value)
+{
+    int intVal = 0;
+    int attrId = -1;
+
+    if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
+    {
+        Attribute attr = static_cast<Attribute>(attrId);
+
+        switch(attr)
+        {
+        case XPOS:
+            element_->setX(intVal);
+            break;
+        case YPOS:
+            element_->setY(intVal);
+            break;
+        case SRC:
+            return loadImage(value);
+            break;
+
+        default:
+            qDebug() << "Unknown attribute: " << attr;
+            return false;
+        }
+
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void ImageElement::addToScene(GraphicsScene* scene)
+{
+    scene->addItem(element_);
+}
+
+void ImageElement::update()
+{
+}
+
+bool ImageElement::loadImage(QString const& name)
+{
+    QPixmap pixmap;
+    QByteArray data;
+
+    if(!readFile(name, data))
+    {
+        return false;
+    }
+
+    if(!pixmap.loadFromData(data))
+    {
+        setError("Invalid image file: " + name);
+        return false;
+    }
+
+    element_->setPixmap(pixmap);
+
+    return true;
+}
diff --git a/src/imageelement.h b/src/imageelement.h
new file mode 100644 (file)
index 0000000..c21cba6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGELEMENT_H
+#define IMAGELEMENT_H
+
+#include "graphicselement.h"
+#include "location.h"
+
+class ZipReader;
+class GraphicsScene;
+class QString;
+class QGraphicsPixmapItem;
+
+class ImageElement : public GraphicsElement
+{
+public:
+    enum Attribute {XPOS, YPOS, SRC, ATTRIBUTE_COUNT};
+    ImageElement(Reader* reader);
+    virtual bool setAttribute(QString const& name, QString const& value);
+    virtual void addToScene(GraphicsScene* scene);
+    virtual void update();
+
+private:
+    bool loadImage(QString const& name);
+    QGraphicsPixmapItem* element_;
+};
+
+#endif
diff --git a/src/imageitem.cpp b/src/imageitem.cpp
new file mode 100644 (file)
index 0000000..046334c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "imageitem.h"
+
+ImageItem::ImageItem(QString const& filename, QGraphicsItem *parent):
+QGraphicsPixmapItem(QPixmap(filename), parent)
+{
+}
+
+void ImageItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_UNUSED(event);
+    emit clicked();
+}
+
diff --git a/src/imageitem.h b/src/imageitem.h
new file mode 100644 (file)
index 0000000..286d561
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGEITEM_H
+#define IMAGEITEM_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtGui/QGraphicsPixmapItem>
+
+class ImageItem: public QObject, public QGraphicsPixmapItem
+{
+    Q_OBJECT
+
+public:
+    ImageItem(QString const& filename, QGraphicsItem *parent = 0);
+
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
+signals:
+    void clicked();
+};
+
+
+#endif
diff --git a/src/location.cpp b/src/location.cpp
new file mode 100644 (file)
index 0000000..f22c7c8
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDebug>
+#include "location.h"
+
+namespace
+{
+    static const double KM_MULTIPLIER = 1.0;
+    static const double MILE_MULTIPLIER = 0.621371192;
+}
+
+Location::Unit Location::unit_ = Location::KM;
+
+Location::Location(QObject* parent): QObject(parent), started_(false),
+control_(0), device_(0)
+{
+    g_type_init();
+}
+
+Location::~Location()
+{
+    end();
+}
+
+void Location::start()
+{
+    control_ = location_gpsd_control_get_default();
+    device_ = (LocationGPSDevice*) g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
+
+    g_object_set(G_OBJECT(control_),
+                 "preferred-method", LOCATION_METHOD_USER_SELECTED,
+                 "preferred-interval", LOCATION_INTERVAL_DEFAULT,
+                 NULL);
+
+    g_signal_connect(control_, "error-verbose", G_CALLBACK(onError), this);
+    g_signal_connect(device_, "changed", G_CALLBACK(onChanged), this);
+
+    location_gpsd_control_start(control_);
+
+    started_ = true;
+}
+
+void Location::end()
+{
+    if(!started_)
+    {
+        return;
+    }
+
+    location_gpsd_control_stop(control_);
+
+    g_object_unref(device_);
+    device_ = 0;
+    g_object_unref(control_);
+    control_ = 0;
+
+    started_ = false;
+}
+
+void Location::setUnit(Location::Unit unit)
+{
+    unit_ = unit;
+}
+
+Location::Unit Location::getUnit()
+{
+    return unit_;
+}
+
+double Location::getUnitMultiplier()
+{
+    if(unit_ == MILE)
+    {
+        return MILE_MULTIPLIER;
+    }
+
+    return KM_MULTIPLIER;
+}
+
+void Location::onChanged(LocationGPSDevice *device, gpointer data)
+{
+    if(device && device->fix &&
+       !(device->fix->fields & LOCATION_GPS_DEVICE_NONE_SET))
+    {
+
+        Fix fix;
+        fix.unit = unit_;
+        fix.time = device->fix->time;
+        fix.ept = device->fix->ept;
+
+        if (device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET)
+        {
+            fix.latitude = device->fix->latitude;
+            fix.longitude = device->fix->longitude;
+            fix.eph = device->fix->eph;
+        }
+
+        if(device->fix->fields & LOCATION_GPS_DEVICE_ALTITUDE_SET)
+        {
+            fix.altitude = device->fix->altitude;
+            fix.epv = device->fix->epv;
+        }
+
+        if(device->fix->fields & LOCATION_GPS_DEVICE_SPEED_SET)
+        {
+            fix.kmSpeed = device->fix->speed;
+            fix.speed = device->fix->speed * getUnitMultiplier();
+            fix.eps = device->fix->eps;
+        }
+
+        if(device->fix->fields & LOCATION_GPS_DEVICE_TRACK_SET)
+        {
+            fix.track = device->fix->track;
+            fix.epd = device->fix->epd;
+        }
+
+        if(device->fix->fields & LOCATION_GPS_DEVICE_CLIMB_SET)
+        {
+            fix.climb = device->fix->climb;
+            fix.epc = device->fix->epc;
+        }
+
+        Location* meh = (Location*) data;
+        meh->emit locationChanged(fix);
+    }
+}
+
+void Location::onError(LocationGPSDControl *control, LocationGPSDControlError error, gpointer data)
+{
+    Q_UNUSED(control);
+
+    Error err = SYSTEM_ERROR;
+
+    switch(error)
+    {
+    case LOCATION_ERROR_USER_REJECTED_DIALOG:
+        err = USER_REJECTED_DIALOG;
+        break;
+    case LOCATION_ERROR_USER_REJECTED_SETTINGS:
+        err = USER_REJECTED_SETTINGS;
+        break;
+    case LOCATION_ERROR_BT_GPS_NOT_AVAILABLE:
+        err = GPS_NOT_AVAILABLE;
+        break;
+    case LOCATION_ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
+        err = NOT_ALLOWED_IN_OFFLINE_MODE;
+        break;
+    case LOCATION_ERROR_SYSTEM:
+        err = SYSTEM_ERROR;
+        break;
+    }
+
+    Location* meh = (Location*) data;
+    meh->emit locationError(err);
+}
+
+Location::Fix::Fix()
+{
+    unit = KM;
+    kmSpeed = 0.0;
+    time = 0.0;
+    ept = 0.0;
+    latitude = 0.0;
+    longitude = 0.0;
+    eph = 0.0;
+    altitude = 0.0;
+    epv = 0.0;
+    track = 0.0;
+    epd = 0.0;
+    speed = 0.0;
+    eps = 0.0;
+    climb = 0.0;
+    epc = 0.0;
+}
diff --git a/src/location.h b/src/location.h
new file mode 100644 (file)
index 0000000..656be1c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LOCATION_H
+#define LOCATION_H
+
+#include <QtCore/QObject>
+#include <location/location-gps-device.h>
+#include <location/location-gpsd-control.h>
+
+class Location : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    enum Unit {KM, MILE};
+
+    struct Fix
+    {
+        Unit unit;
+        double kmSpeed;
+        double time;
+        double ept;
+        double latitude;
+        double longitude;
+        double eph;
+        double altitude;
+        double epv;
+        double track;
+        double epd;
+        double speed;
+        double eps;
+        double climb;
+        double epc;
+        Fix();
+    };
+
+    enum Error {USER_REJECTED_DIALOG,
+        USER_REJECTED_SETTINGS,
+        GPS_NOT_AVAILABLE,
+        NOT_ALLOWED_IN_OFFLINE_MODE,
+        SYSTEM_ERROR};
+
+    Location(QObject* parent = 0);
+    ~Location();
+    void start();
+    void end();
+    static void setUnit(Unit unit);
+    static Unit getUnit();
+    static double getUnitMultiplier();
+
+signals:
+    void locationChanged(Location::Fix const& fix);
+    void locationError(Location::Error error);
+
+private:
+    static void onChanged(LocationGPSDevice *device, gpointer data);
+    static void onError(LocationGPSDControl *control, LocationGPSDControlError error, gpointer data);
+    bool started_;
+    LocationGPSDControl* control_;
+    LocationGPSDevice* device_;
+    static Unit unit_;
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644 (file)
index 0000000..cee1700
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QObject>
+#include <QtGui/QApplication>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication app(argc, argv);
+
+    MainWindow window;
+
+    QObject::connect(&window, SIGNAL(quit()), &app, SLOT(quit()));
+
+    window.show();
+
+    return app.exec();
+}
diff --git a/src/mainmenu.cpp b/src/mainmenu.cpp
new file mode 100644 (file)
index 0000000..e9bb4f8
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QPushButton>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QMessageBox>
+#include <QtGui/QLabel>
+#include <QtGui/QPixmap>
+#include "mainmenu.h"
+#include "themeselector.h"
+#include "unitselector.h"
+
+MainMenu::MainMenu(QWidget* parent): QDialog(parent), itemCount_(0),
+currentRow_(0), themeSelector_(0), unitSelector_(0), aboutDialog_(0)
+{
+    layout_ = new QVBoxLayout;
+    setLayout(layout_);
+
+    setWindowTitle(tr("Menu"));
+    addAction(tr("Reset trip"), this, SIGNAL(resetTrip()));
+    addAction(tr("Reset all"), this, SLOT(confirmReset()));
+    addAction(tr("Select theme"), this, SLOT(selectTheme()));
+    addAction(tr("Set unit"), this, SLOT(selectUnit()));
+    addAction(tr("Flip screen"), this, SIGNAL(flip()));
+    addAction(tr("About"), this, SLOT(showAbout()));
+}
+
+void MainMenu::selectTheme()
+{
+    if(!themeSelector_)
+    {
+        themeSelector_ = new ThemeSelector(this);
+        connect(themeSelector_, SIGNAL(themeChanged()), this, SIGNAL(themeChanged()));
+    }
+
+    themeSelector_->show();
+}
+
+void MainMenu::selectUnit()
+{
+    if(!unitSelector_)
+    {
+        unitSelector_ = new UnitSelector(this);
+        connect(unitSelector_, SIGNAL(unitChanged()), this, SIGNAL(unitChanged()));
+    }
+
+    unitSelector_->show();
+}
+
+void MainMenu::showAbout()
+{
+    if(!aboutDialog_)
+    {
+        aboutDialog_ = new QDialog(this);
+        aboutDialog_->setWindowTitle(tr("About"));
+
+        QHBoxLayout* mainLayout = new QHBoxLayout;
+        QPixmap pixmap(":/resources/appicon.png");
+        QLabel* image = new QLabel;
+        image->setPixmap(pixmap);
+        mainLayout->addWidget(image, 0, Qt::AlignLeft);
+        mainLayout->addSpacing(15);
+        QLabel* text = new QLabel(QString::fromUtf8("<font size='4'><b>jSpeed</b></font><br>(c) 2010 Jesse Hakanen<br><a href='http://jspeed.garage.maemo.org' style='color:#ffffff'>http://jspeed.garage.maemo.org</a>"));
+        text->setOpenExternalLinks(true);
+        mainLayout->addWidget(text, 10, Qt::AlignLeft);
+
+        aboutDialog_->setLayout(mainLayout);
+    }
+
+    aboutDialog_->show();
+}
+
+void MainMenu::confirmReset()
+{
+    QMessageBox::StandardButton result =  QMessageBox::question(this, tr("Reset all"),
+             tr("Are you sure? All recorded data will be lost."),
+             QMessageBox::Yes | QMessageBox::No);
+
+    if(result == QMessageBox::Yes)
+    {
+        emit resetAll();
+    }
+}
+
+void MainMenu::addAction(const QString& text,
+                         const QObject* receiver,
+                         const char* member)
+{
+    if(itemCount_ % 2 == 0 || !currentRow_)
+    {
+        currentRow_ = new QHBoxLayout;
+        layout_->addLayout(currentRow_);
+    }
+
+    QPushButton* button = new QPushButton(text);
+    connect(button, SIGNAL(clicked(bool)), receiver, member);
+    connect(button, SIGNAL(clicked(bool)), this, SLOT(hide()));
+    currentRow_->addWidget(button);
+    itemCount_++;
+}
diff --git a/src/mainmenu.h b/src/mainmenu.h
new file mode 100644 (file)
index 0000000..44e8b0c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MAINMENU_H
+#define MAINMENU_H
+
+#include <QtGui/QDialog>
+
+class QVBoxLayout;
+class QHBoxLayout;
+class ThemeSelector;
+class UnitSelector;
+
+class MainMenu : public QDialog
+{
+    Q_OBJECT
+
+public:
+    MainMenu(QWidget* parent = 0);
+    void addAction(const QString& text, const QObject* receiver, const char* member);
+
+signals:
+    void resetTrip();
+    void resetAll();
+    void flip();
+    void themeChanged();
+    void unitChanged();
+
+private slots:
+    void selectTheme();
+    void selectUnit();
+    void showAbout();
+    void confirmReset();
+
+private:
+    QVBoxLayout* layout_;
+    int itemCount_;
+    QHBoxLayout* currentRow_;
+    ThemeSelector* themeSelector_;
+    UnitSelector* unitSelector_;
+    QDialog* aboutDialog_;
+};
+
+#endif
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
new file mode 100644 (file)
index 0000000..e0280d3
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusMessage>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+#include <QMaemo5InformationBox>
+#include "mainwindow.h"
+#include "mainwindowstack.h"
+#include "theme.h"
+#include "detailwidget.h"
+#include "mainmenu.h"
+#include "odometer.h"
+
+MainWindow::MainWindow(): QMainWindow(0), menu_(0), theme_(0)
+{
+    setWindowTitle(tr("jSpeed"));
+    showFullScreen();
+    Odometer::instance().start();
+    addScreens();
+    startBacklight();
+}
+
+MainWindow::~MainWindow()
+{
+}
+
+void MainWindow::addScreens()
+{
+    stack_ = new MainWindowStack(this);
+
+    connect(stack_, SIGNAL(minimizePressed()), this, SLOT(minimize()));
+    connect(stack_, SIGNAL(settingsPressed()), this, SLOT(openMenu()));
+    connect(stack_, SIGNAL(closePressed()), this, SIGNAL(quit()));
+
+    theme_ = new Theme;
+
+    if(!loadTheme())
+    {
+        return;
+    }
+
+    stack_->addScreen(theme_);
+    stack_->addScreen(new DetailWidget(this));
+
+    connect(QApplication::desktop(), SIGNAL(resized(int)), stack_, SLOT(reArrange()));
+
+    setCentralWidget(stack_);
+}
+
+bool MainWindow::loadTheme()
+{
+    if(!theme_->load())
+    {
+        QMaemo5InformationBox::information(this, tr("Unable to load theme: %1").arg(theme_->error()));
+        close();
+        return false;
+    }
+
+    if(theme_->landscapeEnabled() && theme_->portraitEnabled())
+    {
+        setAttribute(Qt::WA_Maemo5AutoOrientation, true);
+    }
+    else if(theme_->portraitEnabled())
+    {
+        setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
+    }
+
+    return true;
+}
+
+void MainWindow::minimize()
+{
+    QDBusConnection connection = QDBusConnection::sessionBus();
+    QDBusMessage msg = QDBusMessage::createSignal("/",
+                                                  "com.nokia.hildon_desktop",
+                                                  "exit_app_view");
+    connection.send(msg);
+}
+
+void MainWindow::openMenu()
+{
+    if(!menu_)
+    {
+        menu_ = new MainMenu(this);
+        connect(menu_, SIGNAL(resetTrip()), &(Odometer::instance()), SLOT(resetTrip()));
+        connect(menu_, SIGNAL(resetAll()), &(Odometer::instance()), SLOT(resetAll()));
+        connect(menu_, SIGNAL(flip()), stack_, SLOT(flip()));
+        connect(menu_, SIGNAL(themeChanged()), this, SLOT(loadTheme()));
+        connect(menu_, SIGNAL(unitChanged()), &(Odometer::instance()), SLOT(updateUnit()));
+    }
+
+    menu_->show();
+}
+
+void MainWindow::startBacklight()
+{
+    QTimer* timer = new QTimer(this);
+    timer->setInterval(25000);
+    connect(timer, SIGNAL(timeout()), this, SLOT(keepBacklightOn()));
+    timer->start();
+}
+
+void MainWindow::keepBacklightOn()
+{
+    QDBusConnection connection = QDBusConnection::systemBus();
+    QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.mce",
+                                                      "/com/nokia/mce/request",
+                                                      "com.nokia.mce.request",
+                                                      "req_display_blanking_pause");
+
+    connection.call(msg);
+}
diff --git a/src/mainwindow.h b/src/mainwindow.h
new file mode 100644 (file)
index 0000000..373fe2d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+class MainScreen;
+class MainWindowStack;
+class MainMenu;
+class Theme;
+
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    MainWindow();
+    ~MainWindow();
+
+signals:
+    void quit();
+
+private slots:
+    void minimize();
+    void openMenu();
+    void keepBacklightOn();
+    bool loadTheme();
+
+private:
+    void addScreens();
+    void startGps();
+    void startBacklight();
+    MainWindowStack* stack_;
+    MainMenu* menu_;
+    Theme* theme_;
+
+};
+
+#endif
diff --git a/src/mainwindowstack.cpp b/src/mainwindowstack.cpp
new file mode 100644 (file)
index 0000000..ca9b501
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "widgetscreen.h"
+#include "mainwindowstack.h"
+
+MainWindowStack::MainWindowStack(QWidget* parent): WidgetScreen(parent),
+currentScreen_(-1)
+{
+}
+
+void MainWindowStack::addScreen(WidgetScreen* screen)
+{
+    screens_.push_back(screen);
+    connect(screen, SIGNAL(minimizePressed()), this, SIGNAL(minimizePressed()));
+    connect(screen, SIGNAL(settingsPressed()), this, SIGNAL(settingsPressed()));
+    connect(screen, SIGNAL(closePressed()), this, SIGNAL(closePressed()));
+    connect(screen, SIGNAL(clicked()), this, SLOT(toggleScreen()));
+    addWidget(screen);
+
+    if(currentScreen_ == -1)
+    {
+        toggleScreen();
+    }
+}
+
+void MainWindowStack::reArrange()
+{
+    for(int i = 0; i < screens_.size(); i++)
+    {
+        screens_.at(i)->reArrange();
+    }
+}
+
+void MainWindowStack::flip()
+{
+    for(int i = 0; i < screens_.size(); i++)
+    {
+        screens_.at(i)->flip();
+    }
+}
+
+void MainWindowStack::toggleScreen()
+{
+    if(currentScreen_ < 0)
+    {
+        currentScreen_ = 0;
+    }
+    else
+    {
+        currentScreen_++;
+
+        if(currentScreen_ >= screens_.size())
+        {
+            currentScreen_ = 0;
+        }
+    }
+
+    setCurrentIndex(currentScreen_);
+}
diff --git a/src/mainwindowstack.h b/src/mainwindowstack.h
new file mode 100644 (file)
index 0000000..9325044
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MAINWINDOWSTACK_H
+#define MAINWINDOWSTACK_H
+
+#include <QtGui/QStackedWidget>
+#include "abstractscreen.h"
+#include "widgetscreen.h"
+
+class MainWindowStack : public WidgetScreen
+{
+    Q_OBJECT
+
+public:
+    MainWindowStack(QWidget* parent = 0);
+    void addScreen(WidgetScreen* screen);
+
+signals:
+    void minimizePressed();
+    void settingsPressed();
+    void closePressed();
+
+public slots:
+    virtual void reArrange();
+    virtual void flip();
+
+private slots:
+    void toggleScreen();
+
+private:
+    QList<WidgetScreen*> screens_;
+    int currentScreen_;
+};
+
+#endif
diff --git a/src/odometer.cpp b/src/odometer.cpp
new file mode 100644 (file)
index 0000000..bb28ec8
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QTime>
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+#include "odometer.h"
+#include "settings.h"
+
+namespace
+{
+    QString const TOTAL_FIELD = "odometer_total";
+    QString const TOTALTIME_FIELD = "odometer_totaltime";
+    QString const TRIP_FIELD = "odometer_trip";
+    QString const TRIPTIME_FIELD = "odometer_triptime";
+    QString const MAXSPEED_FIELD = "odometer_maxspeed";
+    QString const KM_UNIT = "km";
+    QString const MILE_UNIT = "mi";
+    QString const KM_SPEEDUNIT = "km/h";
+    QString const MILE_SPEEDUNIT = "mph";
+    double const SPEED_TRESHOLD = 0.8;
+    double const SPEED_IGNORE_LEVEL = 0.2;
+}
+
+Odometer::Odometer(): QObject(0), trip_(0), total_(0),
+maxSpeed_(0), totalTime_(0), tripTime_(0), fixTimer_(0),
+mainTimer_(0), emitUpdate_(true), location_(0), signalTimer_(0)
+{
+    total_ = Settings::instance().value(TOTAL_FIELD, 0).toDouble();
+    totalTime_ = Settings::instance().value(TOTALTIME_FIELD, 0).toULongLong();
+    maxSpeed_ = Settings::instance().value(MAXSPEED_FIELD, 0).toDouble();
+    trip_ = Settings::instance().value(TRIP_FIELD, 0).toDouble();
+    tripTime_ = Settings::instance().value(TRIPTIME_FIELD, 0).toULongLong();
+    signalTimer_ = new QTimer(this);
+    signalTimer_->setSingleShot(false);
+    signalTimer_->setInterval(1000);
+    connect(signalTimer_, SIGNAL(timeout()), this, SIGNAL(timeUpdated()));
+    updateUnit();
+}
+
+Odometer::~Odometer()
+{
+    store();
+    delete fixTimer_;
+    delete mainTimer_;
+    end();
+}
+
+Odometer& Odometer::instance()
+{
+    static Odometer instance;
+    return instance;
+}
+
+void Odometer::start()
+{
+    location_ = new Location;
+    connect(location_, SIGNAL(locationChanged(Location::Fix const&)),
+            this, SLOT(update(Location::Fix const&)));
+    location_->start();
+}
+
+void Odometer::end()
+{
+    delete location_;
+    location_ = 0;
+}
+
+void Odometer::update(Location::Fix const& fix)
+{
+    if(fix.kmSpeed > maxSpeed_)
+    {
+        maxSpeed_ = fix.kmSpeed;
+    }
+
+    if(!fixTimer_)
+    {
+        fixTimer_ = new QTime();
+        fixTimer_->start();
+    }
+
+    int elapsed = fixTimer_->elapsed();
+
+    fixTimer_->restart();
+
+    if(elapsed > 200 && fix.kmSpeed > SPEED_IGNORE_LEVEL && elapsed < 10000)
+    {
+        if(fix.kmSpeed > SPEED_TRESHOLD)
+        {
+            double km = fix.kmSpeed * (static_cast<double>(elapsed) / (1000 * 3600));
+            trip_ += km;
+            total_ += km;
+
+            if(!mainTimer_)
+            {
+                startTiming();
+            }
+        }
+        else
+        {
+            endTiming();
+        }
+
+        latestFix_ = fix;
+        emit dataUpdated();
+    }
+    else
+    {
+        if(latestFix_.kmSpeed > 0.49)
+        {
+            latestFix_ = fix;
+            latestFix_.speed = 0.0;
+            latestFix_.kmSpeed = 0.0;
+            emit dataUpdated();
+        }
+
+        endTiming();
+    }
+}
+
+double Odometer::getTrip() const
+{
+    return trip_ * Location::getUnitMultiplier();
+}
+
+double Odometer::getAverageSpeed() const
+{
+    int elapsed = getTripTime();
+
+    if(elapsed == 0)
+    {
+        return 0.0;
+    }
+
+    return (static_cast<double>(trip_) * Location::getUnitMultiplier()) / (static_cast<double>(elapsed) / 60.0);
+}
+
+double Odometer::getTotal() const
+{
+    return total_ * Location::getUnitMultiplier();
+}
+
+double Odometer::getMaxSpeed() const
+{
+    return maxSpeed_ * Location::getUnitMultiplier();
+}
+
+qulonglong Odometer::getTotalTime() const
+{
+    return totalTime_ + timeAddition();
+}
+
+qulonglong Odometer::getTripTime() const
+{
+    return tripTime_ + timeAddition();
+}
+
+void Odometer::resetTrip()
+{
+    resetTiming();
+    trip_ = 0;
+    tripTime_ = 0;
+    maxSpeed_ = 0;
+
+    if(emitUpdate_)
+    {
+        emit timeUpdated();
+        emit dataUpdated();
+    }
+}
+
+void Odometer::resetTotal()
+{
+    resetTiming();
+    total_ = 0;
+    totalTime_ = 0;
+
+    if(emitUpdate_)
+    {
+        emit timeUpdated();
+        emit dataUpdated();
+    }
+}
+
+void Odometer::resetAll()
+{
+    emitUpdate_ = false;
+    resetTrip();
+    resetTotal();
+    emitUpdate_ = true;
+    emit timeUpdated();
+    emit dataUpdated();
+}
+
+void Odometer::store()
+{
+    Settings::instance().setValue(TOTAL_FIELD, total_);
+    Settings::instance().setValue(TOTALTIME_FIELD, getTotalTime());
+    Settings::instance().setValue(TRIP_FIELD, trip_);
+    Settings::instance().setValue(TRIPTIME_FIELD, getTripTime());
+    Settings::instance().setValue(MAXSPEED_FIELD, maxSpeed_);
+    Settings::instance().sync();
+}
+
+Location::Fix const& Odometer::getLatestFix() const
+{
+    return latestFix_;
+}
+
+QString const& Odometer::getUnit()
+{
+    if(Location::getUnit() == Location::KM)
+    {
+        return KM_UNIT;
+    }
+    else
+    {
+        return MILE_UNIT;
+    }
+}
+
+QString const& Odometer::getSpeedUnit()
+{
+    if(Location::getUnit() == Location::KM)
+    {
+        return KM_SPEEDUNIT;
+    }
+    else
+    {
+        return MILE_SPEEDUNIT;
+    }
+}
+
+void Odometer::updateUnit()
+{
+    QString unit = Settings::instance().value("unit", "km").toString();
+
+    if(unit == "km")
+    {
+        Location::setUnit(Location::KM);
+    }
+    else if(unit == "mile")
+    {
+        Location::setUnit(Location::MILE);
+    }
+    else
+    {
+        return;
+    }
+
+    emit unitChanged();
+}
+
+void Odometer::startTiming()
+{
+    signalTimer_->start();
+
+    if(mainTimer_)
+    {
+        mainTimer_->restart();
+        return;
+    }
+
+    mainTimer_ = new QTime();
+    mainTimer_->start();
+    signalTimer_->start();
+}
+
+void Odometer::endTiming()
+{
+    signalTimer_->stop();
+
+    if(!mainTimer_)
+    {
+        return;
+    }
+
+    int elapsed = mainTimer_->elapsed() / 1000;
+    totalTime_ += elapsed;
+    tripTime_ += elapsed;
+    delete mainTimer_;
+    mainTimer_ = 0;
+}
+
+void Odometer::resetTiming()
+{
+    if(!mainTimer_)
+    {
+        return;
+    }
+
+    endTiming();
+    startTiming();
+}
+
+int Odometer::timeAddition() const
+{
+    if(mainTimer_)
+    {
+        return mainTimer_->elapsed() / 1000;
+    }
+
+    return 0;
+}
diff --git a/src/odometer.h b/src/odometer.h
new file mode 100644 (file)
index 0000000..93b91d8
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ODOMETER_H
+#define ODOMETER_H
+
+#include <QtCore/QObject>
+#include "location.h"
+
+class QTime;
+class QTimer;
+
+class Odometer : public QObject
+{
+    Q_OBJECT
+
+public:
+    virtual ~Odometer();
+    static Odometer& instance();
+    void start();
+    void end();
+    double getTrip() const;
+    double getAverageSpeed() const;
+    double getTotal() const;
+    double getMaxSpeed() const;
+    qulonglong getTotalTime() const;
+    qulonglong getTripTime() const;
+    Location::Fix const& getLatestFix() const;
+    static QString const& getUnit();
+    static QString const& getSpeedUnit();
+
+public slots:
+    void update(Location::Fix const& fix);
+    void updateUnit();
+
+signals:
+    void dataUpdated();
+    void timeUpdated();
+    void unitChanged();
+
+public slots:
+    void resetTrip();
+    void resetTotal();
+    void resetAll();
+    void store();
+
+private:
+    Q_DISABLE_COPY(Odometer);
+    Odometer();
+    void startTiming();
+    void endTiming();
+    void resetTiming();
+    int timeAddition() const;
+    Location::Fix latestFix_;
+    double trip_;
+    double total_;
+    double maxSpeed_;
+    qulonglong totalTime_;
+    qulonglong tripTime_;
+    QTime* fixTimer_;
+    QTime* mainTimer_;
+    bool emitUpdate_;
+    Location* location_;
+    QTimer* signalTimer_;
+};
+
+#endif
diff --git a/src/pointer.cpp b/src/pointer.cpp
new file mode 100644 (file)
index 0000000..2431844
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDebug>
+#include <QtCore/QTimeLine>
+#include <QtGui/QGraphicsItemAnimation>
+#include <QtGui/QGraphicsPixmapItem>
+#include <math.h>
+#include "pointer.h"
+#include "reader.h"
+#include "graphicsscene.h"
+#include "odometer.h"
+
+namespace
+{
+    const GraphicsElement::AttributeDetails ATTRIBUTES[Pointer::ATTRIBUTE_COUNT] =
+    {
+     {"xpos", true},
+     {"ypos", true},
+     {"src", false},
+     {"zeroangle", true},
+     {"fullangle", true},
+     {"zerospeed", true},
+     {"fullspeed", true},
+     {"xrotationpoint", true},
+     {"yrotationpoint", true}
+    };
+
+    int const ANIMATION_TIME = 500;
+    int const ANIMATION_FRAMES = 50;
+    int const ANIMATION_UPDATEINTERVAL = 20;
+}
+
+Pointer::Pointer(Reader* reader, bool animate): QObject(0), GraphicsElement(reader),
+xRotationPoint_(0), yRotationPoint_(0), x_(0), y_(0), zeroAngle_(0),
+fullAngle_(180), zeroSpeed_(0), fullSpeed_(220), targetAngle_(0),
+startAngle_(0), angle_(-1), imageSet_(false), animate_(animate), timer_(0)
+{
+    element_ = new QGraphicsPixmapItem();
+
+    if(animate_)
+    {
+        timer_ = new QTimeLine(ANIMATION_TIME);
+        timer_->setFrameRange(0, ANIMATION_FRAMES);
+        timer_->setUpdateInterval(ANIMATION_UPDATEINTERVAL);
+        connect(timer_, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
+    }
+
+}
+
+Pointer::~Pointer()
+{
+    delete timer_;
+}
+
+bool Pointer::setAttribute(QString const& name, QString const& value)
+{
+    int intVal = 0;
+    int attrId = -1;
+
+    if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
+    {
+        Attribute attr = static_cast<Attribute>(attrId);
+
+        switch(attr)
+        {
+        case XPOS:
+            x_ = intVal;
+            break;
+        case YPOS:
+            y_ = intVal;
+            break;
+        case SRC:
+            return loadImage(value);
+            break;
+        case ZEROANGLE:
+            zeroAngle_ = intVal;
+            break;
+        case FULLANGLE:
+            fullAngle_ = intVal;
+            break;
+        case ZEROSPEED:
+            zeroSpeed_ = intVal;
+            break;
+        case FULLSPEED:
+            fullSpeed_ = intVal;
+            break;
+        case XROTATIONPOINT:
+            xRotationPoint_ = intVal;
+            break;
+        case YROTATIONPOINT:
+            yRotationPoint_ = intVal;
+            break;
+        default:
+            qDebug() << "Unknown attribute: " << attr;
+            return false;
+        }
+
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void Pointer::addToScene(GraphicsScene* scene)
+{
+    if(!imageSet_)
+    {
+        return;
+    }
+
+    element_->setTransformOriginPoint(xRotationPoint_, yRotationPoint_);
+    element_->setX(x_ - xRotationPoint_);
+    element_->setY(y_ - yRotationPoint_);
+
+    bool animateVal = animate_;
+    animate_ = false;
+    update();
+    animate_ = animateVal;
+
+    scene->addItem(element_);
+}
+
+void Pointer::update()
+{
+    double speed = Odometer::instance().getLatestFix().kmSpeed;
+
+    if(speed < zeroSpeed_)
+    {
+        speed = static_cast<double>(zeroSpeed_);
+    }
+    else if(speed > fullSpeed_)
+    {
+        speed = static_cast<double>(fullSpeed_);
+    }
+
+    double multiplier = static_cast<double>(speed - zeroSpeed_) / (fullSpeed_ - zeroSpeed_);
+    double angle = static_cast<double>(zeroAngle_) + ((fullAngle_ - zeroAngle_) * multiplier);
+
+    int rounded = static_cast<int>(round(angle));
+
+    if(rounded == angle_)
+    {
+        return;
+    }
+
+    angle_ = rounded;
+
+    if(!animate_)
+    {
+        element_->setRotation(rounded);
+    }
+    else
+    {
+        targetAngle_ = rounded;
+        startAngle_ = element_->rotation();
+
+        if(timer_->state() == QTimeLine::Running)
+        {
+            timer_->stop();
+        }
+
+        timer_->start();
+    }
+}
+
+void Pointer::setFrame(int frame)
+{
+    element_->setRotation(startAngle_ + ((static_cast<double>(frame) / ANIMATION_FRAMES) * (targetAngle_ - startAngle_)));
+}
+
+bool Pointer::loadImage(QString const& name)
+{
+    QPixmap pixmap;
+    QByteArray data;
+
+    if(!readFile(name, data))
+    {
+        return false;
+    }
+
+    if(!pixmap.loadFromData(data))
+    {
+        setError("Invalid image file: " + name);
+        return false;
+    }
+
+    element_->setPixmap(pixmap);
+    imageSet_ = true;
+
+    return true;
+}
diff --git a/src/pointer.h b/src/pointer.h
new file mode 100644 (file)
index 0000000..4ae1818
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef POINTER_H
+#define POINTER_H
+
+#include <QtCore/QObject>
+#include "graphicselement.h"
+#include "location.h"
+
+class Reader;
+class QGraphicsPixmapItem;
+class GraphicsScene;
+class QTimeLine;
+
+class Pointer : public QObject, public GraphicsElement
+{
+    Q_OBJECT
+
+public:
+    enum Attribute {XPOS, YPOS, SRC, ZEROANGLE, FULLANGLE, ZEROSPEED, FULLSPEED, XROTATIONPOINT, YROTATIONPOINT, ATTRIBUTE_COUNT};
+    Pointer(Reader* reader, bool animate);
+    ~Pointer();
+    virtual bool setAttribute(QString const& name, QString const& value);
+    virtual void addToScene(GraphicsScene* scene);
+    virtual void update();
+
+private slots:
+    void setFrame(int frame);
+
+private:
+    bool loadImage(QString const& name);
+    QGraphicsPixmapItem* element_;
+    int xRotationPoint_;
+    int yRotationPoint_;
+    int x_;
+    int y_;
+    int zeroAngle_;
+    int fullAngle_;
+    int zeroSpeed_;
+    int fullSpeed_;
+    int targetAngle_;
+    int startAngle_;
+    int angle_;
+    bool imageSet_;
+    bool animate_;
+    QTimeLine* timer_;
+};
+
+#endif
diff --git a/src/reader.cpp b/src/reader.cpp
new file mode 100644 (file)
index 0000000..0831361
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "reader.h"
+
+Reader::Reader(){}
diff --git a/src/reader.h b/src/reader.h
new file mode 100644 (file)
index 0000000..7b9b04b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef READER_H
+#define READER_H
+
+class QString;
+class QByteArray;
+
+class Reader
+{
+public:
+    Reader();
+    virtual bool open() = 0;
+    virtual bool readFile(QString const& filename, QByteArray& data) = 0;
+    virtual bool fileExists(QString const& filename) const = 0;
+    virtual bool close() = 0;
+    virtual QString const& errorString() const = 0;
+};
+
+#endif
diff --git a/src/rectangle.cpp b/src/rectangle.cpp
new file mode 100644 (file)
index 0000000..5448748
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QGraphicsRectItem>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include "rectangle.h"
+#include "reader.h"
+#include "graphicsscene.h"
+
+namespace
+{
+    const GraphicsElement::AttributeDetails ATTRIBUTES[Rectangle::ATTRIBUTE_COUNT] =
+    {
+     {"xpos", true},
+     {"ypos", true},
+     {"width", true},
+     {"height", true},
+     {"color", false}
+    };
+}
+
+Rectangle::Rectangle(Reader* reader): GraphicsElement(reader),
+x_(0), y_(0), width_(0), height_(0)
+{
+    element_ = new QGraphicsRectItem();
+}
+
+bool Rectangle::setAttribute(QString const& name, QString const& value)
+{
+    int intVal = 0;
+    int attrId = -1;
+
+    if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
+    {
+        Attribute attr = static_cast<Attribute>(attrId);
+
+        switch(attr)
+        {
+        case XPOS:
+            x_ = intVal;
+            break;
+        case YPOS:
+            y_ = intVal;
+            break;
+        case WIDTH:
+            width_ = intVal;
+            break;
+        case HEIGHT:
+            height_ = intVal;
+            break;
+        case COLOR:
+            element_->setBrush(QBrush(QColor(value)));
+            break;
+
+        default:
+            qDebug() << "Unknown attribute: " << attr;
+            return false;
+        }
+
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void Rectangle::addToScene(GraphicsScene* scene)
+{
+    int width = width_;
+
+    int maxSize = scene->width();
+
+    if(scene->height() > maxSize)
+    {
+        maxSize = scene->height();
+    }
+
+    if(width <= 0)
+    {
+        width = maxSize;
+    }
+
+    int height = height_;
+
+    if(height <= 0)
+    {
+        height = maxSize;
+    }
+
+    element_->setRect(x_, y_, width, height);
+    scene->addItem(element_);
+}
+
+void Rectangle::update()
+{
+}
diff --git a/src/rectangle.h b/src/rectangle.h
new file mode 100644 (file)
index 0000000..72912a0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef RECTANGLE_H
+#define RECTANGLE_H
+
+#include "graphicselement.h"
+#include "location.h"
+
+class GraphicsScene;
+class QString;
+class Reader;
+class QGraphicsRectItem;
+
+class Rectangle : public GraphicsElement
+{
+public:
+    enum Attribute {XPOS, YPOS, WIDTH, HEIGHT, COLOR, ATTRIBUTE_COUNT};
+    Rectangle(Reader* reader);
+    virtual bool setAttribute(QString const& name, QString const& value);
+    virtual void addToScene(GraphicsScene* scene);
+    virtual void update();
+
+private:
+    QGraphicsRectItem* element_;
+    int x_;
+    int y_;
+    int width_;
+    int height_;
+};
+
+#endif
diff --git a/src/resources.qrc b/src/resources.qrc
new file mode 100644 (file)
index 0000000..7b6a999
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+    <file>resources/minimize.png</file>
+    <file>resources/close.png</file>
+    <file>resources/settings.png</file>
+    <file>resources/appicon.png</file>
+    <file>resources/themes/default/theme.xml</file>
+    <file>resources/themes/default/digital7.ttf</file>
+    <file>resources/themes/default/background.png</file>
+</qresource>
+</RCC>
diff --git a/src/resources/appicon.png b/src/resources/appicon.png
new file mode 100644 (file)
index 0000000..5c3d9f1
Binary files /dev/null and b/src/resources/appicon.png differ
diff --git a/src/resources/close.png b/src/resources/close.png
new file mode 100644 (file)
index 0000000..c7942ad
Binary files /dev/null and b/src/resources/close.png differ
diff --git a/src/resources/minimize.png b/src/resources/minimize.png
new file mode 100644 (file)
index 0000000..d4c6bcd
Binary files /dev/null and b/src/resources/minimize.png differ
diff --git a/src/resources/settings.png b/src/resources/settings.png
new file mode 100644 (file)
index 0000000..39ae7ca
Binary files /dev/null and b/src/resources/settings.png differ
diff --git a/src/resources/themes/default/background.png b/src/resources/themes/default/background.png
new file mode 100755 (executable)
index 0000000..d4f20b1
Binary files /dev/null and b/src/resources/themes/default/background.png differ
diff --git a/src/resources/themes/default/digital7.ttf b/src/resources/themes/default/digital7.ttf
new file mode 100755 (executable)
index 0000000..e94f8e3
Binary files /dev/null and b/src/resources/themes/default/digital7.ttf differ
diff --git a/src/resources/themes/default/theme.xml b/src/resources/themes/default/theme.xml
new file mode 100755 (executable)
index 0000000..a05dafe
--- /dev/null
@@ -0,0 +1,58 @@
+<theme>
+<orientation name="landscape">
+       <image>
+               <xpos>0</xpos>
+               <ypos>0</ypos>
+               <src>background.png</src>
+       </image>
+       <text>
+               <data>000</data>
+               <font>digital7.ttf</font>
+               <size>320</size>
+               <xpos>100</xpos>
+               <ypos>75</ypos>
+               <color>#17202b</color>
+               <align>right</align>
+               <width>600</width>
+       </text>
+       <text>
+               <data>{SPEED}</data>
+               <font>digital7.ttf</font>
+               <size>320</size>
+               <xpos>100</xpos>
+               <ypos>75</ypos>
+               <color>#fff</color>
+               <align>right</align>
+               <width>600</width>
+               <format>%.0f</format>
+       </text>
+</orientation>
+<orientation name="portrait">
+       <image>
+               <xpos>0</xpos>
+               <ypos>0</ypos>
+               <src>background.png</src>
+       </image>
+       <text>
+               <data>000</data>
+               <font>digital7.ttf</font>
+               <size>230</size>
+               <xpos>0</xpos>
+               <ypos>260</ypos>
+               <color>#17202b</color>
+               <align>right</align>
+               <width>450</width>
+       </text>
+       <text>
+               <data>{SPEED}</data>
+               <font>digital7.ttf</font>
+               <size>230</size>
+               <xpos>0</xpos>
+               <ypos>260</ypos>
+               <color>#fff</color>
+               <align>right</align>
+               <width>450</width>
+               <format>%.0f</format>
+       </text>
+</orientation>
+</theme>
diff --git a/src/settings.cpp b/src/settings.cpp
new file mode 100644 (file)
index 0000000..12f7234
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include "settings.h"
+
+QString Settings::dir_ = initDir();
+
+Settings::Settings(): QSettings("jspeed")
+{
+}
+
+Settings& Settings::instance()
+{
+    static Settings instance;
+    return instance;
+}
+
+QString const& Settings::getDir()
+{
+    return dir_;
+}
+
+QString Settings::initDir()
+{
+    return QDir::home().path() + QDir::separator() + ".jspeed" + QDir::separator();
+}
diff --git a/src/settings.h b/src/settings.h
new file mode 100644 (file)
index 0000000..d1e0056
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include <QtCore/QSettings>
+
+class Settings : public QSettings
+{
+public:
+    static Settings& instance();
+    static QString const& getDir();
+    static void close();
+
+private:
+    Settings();
+    static QString initDir();
+    static QString dir_;
+
+};
+
+#endif
diff --git a/src/textelement.cpp b/src/textelement.cpp
new file mode 100644 (file)
index 0000000..92bf7fa
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsTextItem>
+#include "reader.h"
+#include "textelement.h"
+#include "odometer.h"
+#include "graphicsscene.h"
+#include "location.h"
+
+namespace
+{
+    const GraphicsElement::AttributeDetails ATTRIBUTES[TextElement::ATTRIBUTE_COUNT] =
+    {
+     {"xpos", true},
+     {"ypos", true},
+     {"data", false},
+     {"format", false},
+     {"width", true},
+     {"align", false},
+     {"color", false},
+     {"size", true},
+     {"font", false}
+    };
+}
+
+TextElement::TextElement(Reader* reader): GraphicsElement(reader),
+data_(""), format_(""), align_("left"), fontSize_(16), hasSpecialField_(false)
+{
+    element_ = new QGraphicsTextItem();
+}
+
+bool TextElement::setAttribute(QString const& name, QString const& value)
+{
+    int intVal = 0;
+    int attrId = -1;
+
+    if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
+    {
+        Attribute attr = static_cast<Attribute>(attrId);
+
+        bool fontChanged = false;
+
+        switch(attr)
+        {
+        case XPOS:
+            element_->setX(intVal);
+            break;
+        case YPOS:
+            element_->setY(intVal);
+            break;
+        case DATA:
+            data_ = value;
+            break;
+        case FORMAT:
+            format_ = value;
+            break;
+        case WIDTH:
+            element_->setTextWidth(intVal);
+            break;
+        case ALIGN:
+            align_ = value;
+            break;
+        case COLOR:
+            element_->setDefaultTextColor(QColor(value));
+            break;
+        case SIZE:
+            fontSize_ = intVal;
+            fontChanged = true;
+            break;
+        case FONT:
+            fontFile_ = value;
+            fontChanged = true;
+            break;
+        default:
+            qDebug() << "Unknown attribute: " << attr;
+            return false;
+        }
+
+        if(fontChanged)
+        {
+            if(!fontFile_.isEmpty())
+            {
+                QFont font;
+
+                if(getFont(fontFile_, font))
+                {
+                    font.setPointSize(fontSize_);
+                    element_->setFont(font);
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                element_->setFont(QFont("Default", fontSize_));
+            }
+        }
+
+        return true;
+
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void TextElement::addToScene(GraphicsScene* scene)
+{
+    Location::Fix fix;
+
+    QString replaced = data_;
+
+    hasSpecialField_ = replaceSpecialField(replaced);
+
+    updateHtml(replaced);
+
+    scene->addItem(element_);
+}
+
+void TextElement::update()
+{
+    if(!hasSpecialField_)
+    {
+        return;
+    }
+
+    QString replaced = data_;
+    replaceSpecialField(replaced);
+
+    updateHtml(replaced);
+}
+
+void TextElement::updateHtml(QString const& data)
+{
+    element_->setHtml("<div align='"+align_+"'>"+data+"</div>");
+}
+
+bool TextElement::replaceSpecialField(QString& value)
+{
+    bool found = false;
+
+    if(value.indexOf("{TRIP}") != -1)
+    {
+        value = value.replace("{TRIP}", formatString(Odometer::instance().getTrip()));
+        found = true;
+    }
+
+    if(value.indexOf("{TOTAL}") != -1)
+    {
+        value = value.replace("{TOTAL}", formatString(Odometer::instance().getTotal()));
+        found = true;
+    }
+
+    if(value.indexOf("{SPEED}") != -1)
+    {
+        value = value.replace("{SPEED}", formatString(Odometer::instance().getLatestFix().speed));
+        found = true;
+    }
+
+    if(value.indexOf("{SPEED_UNIT}") != -1)
+    {
+        value = value.replace("{SPEED_UNIT}", Odometer::getSpeedUnit());
+        found = true;
+    }
+
+    if(value.indexOf("{UNIT}") != -1)
+    {
+        value = value.replace("{UNIT}", Odometer::getUnit());
+        found = true;
+    }
+
+    return found;
+
+}
+
+QString TextElement::formatString(double val)
+{
+    QString format = format_;
+
+    if(format.isEmpty())
+    {
+        format = "%.1lf";
+    }
+
+    QString result;
+    result.sprintf(format.toLatin1().data(), val);
+
+    return result;
+}
diff --git a/src/textelement.h b/src/textelement.h
new file mode 100644 (file)
index 0000000..02e34f8
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TEXTELEMENT_H
+#define TEXTELEMENT_H
+
+#include "graphicselement.h"
+
+class Reader;
+class QString;
+class GraphicsScene;
+class QGraphicsTextItem;
+
+class TextElement : public GraphicsElement
+{
+public:
+    enum Attribute {XPOS, YPOS, DATA, FORMAT, WIDTH, ALIGN, COLOR, SIZE, FONT, ATTRIBUTE_COUNT};
+    TextElement(Reader* reader);
+    virtual bool setAttribute(QString const& name, QString const& value);
+    virtual void addToScene(GraphicsScene* scene);
+    virtual void update();
+
+private:
+    void updateHtml(QString const& data);
+    bool replaceSpecialField(QString& value);
+    QString formatString(double val);
+    QGraphicsTextItem* element_;
+    QString data_;
+    QString format_;
+    QString align_;
+    int fontSize_;
+    QString fontFile_;
+    bool hasSpecialField_;
+};
+
+#endif
diff --git a/src/theme.cpp b/src/theme.cpp
new file mode 100644 (file)
index 0000000..09baddf
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDir>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QStackedWidget>
+#include <QtXml/QDomNode>
+#include <QtXml/QDomDocument>
+#include <QtXml/QDomAttr>
+#include <QMaemo5InformationBox>
+#include "theme.h"
+#include "reader.h"
+#include "zipreader.h"
+#include "filereader.h"
+#include "themescreen.h"
+#include "settings.h"
+
+namespace
+{
+    QString const RESOURCE_DIR = ":/resources/themes/";
+    QString const THEME_SUFFIX = ".jspeed";
+}
+
+Theme::Theme(QWidget* parent): WidgetScreen(parent),
+portraitId_(-1), landscapeId_(-1), reader_(0),
+portrait_(0), landscape_(0), portraitMode_(false)
+{
+}
+
+Theme::~Theme()
+{
+}
+
+bool Theme::load()
+{
+    if(landscape_)
+    {
+        removeWidget(landscape_);
+        delete landscape_;
+        landscape_ = 0;
+        landscapeId_ = -1;
+    }
+
+    if(portrait_)
+    {
+        removeWidget(portrait_);
+        delete portrait_;
+        portrait_ = 0;
+        portraitId_ = -1;
+    }
+
+    QString theme = Settings::instance().value("theme", "default").toString();
+
+    QString themeDir = getThemeDir();
+
+    if(QFile::exists(themeDir + theme + THEME_SUFFIX))
+    {
+        reader_ = new ZipReader(themeDir + theme + THEME_SUFFIX);
+
+        if(read())
+        {
+            qDebug() << "Ladattiin " << theme;
+            return true;
+        }
+        else
+        {
+            QMaemo5InformationBox::information(this,
+                                               tr("Unable to load theme: %1.").arg(error_),
+                                               QMaemo5InformationBox::NoTimeout);
+        }
+    }
+
+    theme = "default";
+    Settings::instance().setValue("theme", theme);
+
+    if(QFile::exists(RESOURCE_DIR + theme))
+    {
+        if(reader_)
+        {
+            delete reader_;
+        }
+
+        reader_ = new FileReader(RESOURCE_DIR + theme);
+        return read();
+    }
+
+    error_ = "No themes found";
+
+    return false;
+}
+
+bool Theme::read()
+{
+    Q_ASSERT(reader_ != 0);
+
+    if(!reader_->open())
+    {
+        error_ = reader_->errorString();
+        return false;
+    }
+
+    QByteArray xmlData;
+
+    if(!reader_->readFile("theme.xml", xmlData))
+    {
+        error_ = "Unable to find <b>theme.xml</b> from theme file";
+        return false;
+    }
+
+    QDomDocument doc;
+    int line = 0;
+    int column = 0;
+    QString msg;
+
+    if(!doc.setContent(xmlData, false, &msg, &line, &column))
+    {
+        error_ = "Invalid xml file, " + msg + " (line "+line+", column "+column+")";
+        return false;
+    }
+
+    QDomNodeList orientations = doc.elementsByTagName("orientation");
+
+    if(orientations.isEmpty())
+    {
+        error_ = "No <orientation> tags found";
+        return false;
+    }
+
+    bool ok = true;
+
+    for(int i = 0; i < orientations.size(); i++)
+    {
+        QDomNode data = orientations.at(i);
+        QString type = data.attributes().namedItem("name").toAttr().value();
+
+        if(type == "landscape")
+        {
+            if(landscape_)
+            {
+                error_ = "More than one <orientation name=\"landscape\"> specified";
+                ok = false;
+            }
+
+            landscape_ = new ThemeScreen();
+            ok = ok && landscape_->load(data, reader_);
+
+        }
+        else if(type == "portrait")
+        {
+            if(portrait_)
+            {
+                error_ = "More than one <orientation name=\"portrait\"> specified";
+                ok = false;
+            }
+
+            portrait_ = new ThemeScreen();
+            ok = ok && portrait_->load(data, reader_);
+        }
+        else
+        {
+            error_ = "Invalid orientation: " + type;
+            ok = false;
+        }
+    }
+
+    reader_->close();
+    delete reader_;
+    reader_ = 0;
+
+    if(!portrait_ && !landscape_)
+    {
+        error_ = "No valid orientation tags found";
+        ok = false;
+    }
+
+    if(ok)
+    {
+        if(landscape_)
+        {
+            landscapeId_ = addWidget(landscape_);
+            connectSignals(landscape_);
+        }
+
+        if(portrait_)
+        {
+            portraitId_ = addWidget(portrait_);
+            connectSignals(portrait_);
+        }
+    }
+    else
+    {
+        delete portrait_;
+        portrait_ = 0;
+        delete landscape_;
+        landscape_ = 0;
+    }
+
+    return ok;
+}
+
+QString Theme::getThemeDir()
+{
+    return Settings::getDir() + "themes" + QDir::separator();
+}
+
+QString const& Theme::getThemeSuffix()
+{
+    return THEME_SUFFIX;
+}
+
+QString const& Theme::error() const
+{
+    return error_;
+}
+
+bool Theme::portraitEnabled() const
+{
+    return portraitId_ != -1;
+}
+
+bool Theme::landscapeEnabled() const
+{
+    return landscapeId_ != -1;
+}
+
+void Theme::reArrange()
+{
+    QRect rect = QApplication::desktop()->screenGeometry();
+
+    bool portrait = rect.height() > rect.width();
+
+    if(portrait != portraitMode_)
+    {
+        if((portrait && portraitId_ == -1) ||
+           (!portrait && landscapeId_ == -1))
+        {
+            return;
+        }
+
+        portraitMode_ = portrait;
+
+        if(portrait)
+        {
+            setCurrentIndex(portraitId_);
+            portrait_->reArrange();
+        }
+        else
+        {
+            setCurrentIndex(landscapeId_);
+            landscape_->reArrange();
+        }
+    }
+}
+
+void Theme::flip()
+{
+    if(portrait_)
+    {
+        portrait_->flip();
+    }
+
+    if(landscape_)
+    {
+        landscape_->flip();
+    }
+}
+
+void Theme::connectSignals(ThemeScreen* screen)
+{
+    connect(screen, SIGNAL(minimizePressed()), this, SIGNAL(minimizePressed()));
+    connect(screen, SIGNAL(settingsPressed()), this, SIGNAL(settingsPressed()));
+    connect(screen, SIGNAL(closePressed()), this, SIGNAL(closePressed()));
+    connect(screen, SIGNAL(clicked()), this, SIGNAL(clicked()));
+}
+
diff --git a/src/theme.h b/src/theme.h
new file mode 100644 (file)
index 0000000..79682d5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEME_H
+#define THEME_H
+
+#include "widgetscreen.h"
+
+class QString;
+class Reader;
+class ThemeScreen;
+
+class Theme : public WidgetScreen
+{
+    Q_OBJECT
+
+public:
+    Theme(QWidget* parent = 0);
+    ~Theme();
+    bool load();
+    bool portraitEnabled() const;
+    bool landscapeEnabled() const;
+    QString const& error() const;
+    static QString getThemeDir();
+    static QString const& getThemeSuffix();
+
+public slots:
+    virtual void reArrange();
+    virtual void flip();
+
+private:
+    bool read();
+    void connectSignals(ThemeScreen* screen);
+    int portraitId_;
+    int landscapeId_;
+    Reader* reader_;
+    QString error_;
+    ThemeScreen* portrait_;
+    ThemeScreen* landscape_;
+    bool portraitMode_;
+
+};
+
+#endif
diff --git a/src/themescreen.cpp b/src/themescreen.cpp
new file mode 100644 (file)
index 0000000..d4dcaa0
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QWidget>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtXml/QDomNode>
+#include <QtXml/QDomNodeList>
+#include "themescreen.h"
+#include "graphicselement.h"
+#include "reader.h"
+
+ThemeScreen::ThemeScreen(QWidget* parent): GraphicsScreen(parent)
+{
+}
+
+bool ThemeScreen::load(QDomNode const& data, Reader* reader)
+{
+    QDomNodeList childNodes = data.childNodes();
+
+    if(childNodes.size() == 0)
+    {
+        error_ = "No elements specified for " + data.nodeName();
+        return false;
+    }
+
+    for(int i = 0; i < childNodes.size(); i++)
+    {
+        GraphicsElement* element = GraphicsElement::getElement(childNodes.at(i).nodeName(), reader);
+
+        if(element == 0)
+        {
+            qDebug() << "Warning: invalid element: " << childNodes.at(i).nodeName();
+            continue;
+        }
+
+        elements_.push_back(element);
+
+        QDomNodeList options = childNodes.at(i).childNodes();
+
+        for(int i = 0; i < options.size(); i++)
+        {
+            if(!element->setAttribute(options.at(i).nodeName(), options.at(i).toElement().text()))
+            {
+                qDebug() << "Warning: invalid option: " << options.at(i).nodeName();
+            }
+        }
+
+        element->addToScene(getScene());
+
+    }
+
+    return true;
+}
+
+void ThemeScreen::update()
+{
+    for(int i = 0; i < elements_.size(); i++)
+    {
+        elements_.at(i)->update();
+    }
+}
diff --git a/src/themescreen.h b/src/themescreen.h
new file mode 100644 (file)
index 0000000..3e1da8b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEMESCREEN_H
+#define THEMESCREEN_H
+
+#include "graphicsscreen.h"
+#include "location.h"
+
+class QString;
+class QWidget;
+class GraphicsElement;
+class QDomNode;
+class Reader;
+
+class ThemeScreen : public GraphicsScreen
+{
+public:
+    ThemeScreen(QWidget* parent = 0);
+    bool load(QDomNode const& data, Reader* reader);
+    virtual void update();
+
+private:
+    QList<GraphicsElement*> elements_;
+    QString error_;
+};
+
+#endif
diff --git a/src/themeselector.cpp b/src/themeselector.cpp
new file mode 100644 (file)
index 0000000..7f22a09
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtGui/QFileDialog>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QMessageBox>
+#include "themeselector.h"
+#include "buttonselector.h"
+#include "theme.h"
+#include "settings.h"
+
+ThemeSelector::ThemeSelector(QWidget* parent): QDialog(parent)
+{
+    setWindowTitle(tr("Select theme"));
+
+    QHBoxLayout* layout = new QHBoxLayout;
+    QHBoxLayout* left = new QHBoxLayout;
+
+    QPushButton* saveButton = new QPushButton(tr("Save"));
+    connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(saveTheme()));
+    QDialogButtonBox* buttons = new QDialogButtonBox;
+    buttons->setCenterButtons(false);
+    buttons->addButton(saveButton, QDialogButtonBox::AcceptRole);
+
+    selector_ = new ButtonSelector(tr("Theme"), this);
+    theme_ = Settings::instance().value("theme", "default").toString();
+
+    QPushButton* loadButton = new QPushButton(tr("Import"));
+    connect(loadButton, SIGNAL(clicked(bool)), this, SLOT(loadFromFile()));
+
+    left->addWidget(selector_, Qt::AlignLeft);
+    left->addWidget(loadButton);
+
+    layout->addLayout(left, Qt::AlignLeft);
+    layout->addWidget(buttons);
+
+    setLayout(layout);
+
+}
+
+void ThemeSelector::saveTheme()
+{
+    QString theme = selector_->value().toString();
+
+    if(theme == theme_)
+    {
+        hide();
+        return;
+    }
+
+    Settings::instance().setValue("theme", theme);
+    hide();
+    theme_ = theme;
+    emit themeChanged();
+}
+
+void ThemeSelector::loadFromFile()
+{
+    QString filename = QFileDialog::getOpenFileName(this, tr("Open file"),
+                                                    QDir::home().path(),
+                                                    tr("Theme files") + "(*" + Theme::getThemeSuffix() + ")");
+
+    if(filename.isEmpty())
+    {
+        return;
+    }
+
+    qDebug() << filename;
+
+    QString basename;
+    int i = filename.lastIndexOf(QDir::separator());
+
+    if(i == -1)
+    {
+        basename = filename;
+    }
+    else
+    {
+        basename = filename.mid(i + 1);
+    }
+
+    QString targetFile = Theme::getThemeDir() + basename;
+
+    qDebug() << targetFile;
+
+    bool ok = true;
+
+    if(QFile::exists(targetFile))
+    {
+        ok = confirmCopy(basename);
+
+        if(ok)
+        {
+            QFile::remove(targetFile);
+        }
+    }
+
+    if(ok)
+    {
+        QFile::copy(filename, targetFile);
+        QString name;
+        QString id;
+        getThemeDetails(basename, name, id);
+        theme_ = id;
+        loadThemes();
+    }
+}
+
+void ThemeSelector::loadThemes()
+{
+    selector_->clear();
+    selector_->addItem(tr("Default"), "default");
+    QDir themeDir(Theme::getThemeDir());
+
+    if(!themeDir.exists() || !themeDir.isReadable())
+    {
+        qDebug() << "Warning: theme dir (" + Theme::getThemeDir() + ") doesn't exist or is read protected";
+        return;
+    }
+
+    QStringList filters;
+    filters << "*" + Theme::getThemeSuffix();
+    themeDir.setNameFilters(filters);
+    themeDir.setFilter(QDir::Files);
+    QStringList files = themeDir.entryList();
+
+    for(int i = 0; i < files.size(); i++)
+    {
+        QString name;
+        QString id;
+        getThemeDetails(files.at(i), name, id);
+        selector_->addItem(name, id);
+
+        if(id == theme_)
+        {
+            selector_->setCurrentIndex(i + 1);
+        }
+    }
+
+}
+
+void ThemeSelector::getThemeDetails(QString filename,
+                                    QString& name,
+                                    QString& id)
+{
+    static QRegExp cleaner(QRegExp::escape(Theme::getThemeSuffix()) + "$");
+    filename = filename.replace(cleaner, "");
+
+    id = filename;
+    name = filename.at(0).toUpper() + filename.mid(1);
+}
+
+bool ThemeSelector::confirmCopy(QString const& filename)
+{
+    QMessageBox::StandardButton result =  QMessageBox::question(this, tr("File exists"),
+             tr("Theme file %1 already exists in theme directory, overwrite?").arg(filename),
+             QMessageBox::Yes | QMessageBox::No);
+
+    return (result == QMessageBox::Yes);
+}
+
+void ThemeSelector::setVisible(bool visible)
+{
+    if(visible)
+    {
+        loadThemes();
+    }
+
+    QDialog::setVisible(visible);
+}
diff --git a/src/themeselector.h b/src/themeselector.h
new file mode 100644 (file)
index 0000000..4543657
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEMESELECTOR_H
+#define THEMESELECTOR_H
+
+#include <QtGui/QDialog>
+
+class ButtonSelector;
+class QString;
+
+class ThemeSelector : public QDialog
+{
+    Q_OBJECT
+
+public:
+    ThemeSelector(QWidget* parent = 0);
+
+signals:
+    void themeChanged();
+
+private slots:
+    void saveTheme();
+    void loadFromFile();
+
+protected:
+    virtual void setVisible(bool visible);
+
+private:
+    void loadThemes();
+    void getThemeDetails(QString filename, QString& name, QString& id);
+    bool confirmCopy(QString const& name);
+    ButtonSelector* selector_;
+    QString theme_;
+};
+
+
+#endif
diff --git a/src/unitselector.cpp b/src/unitselector.cpp
new file mode 100644 (file)
index 0000000..90cadfa
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include "unitselector.h"
+#include "buttonselector.h"
+#include "settings.h"
+
+UnitSelector::UnitSelector(QWidget* parent): QDialog(parent)
+{
+    setWindowTitle(tr("Set unit"));
+
+    unit_ = Settings::instance().value("unit", "km").toString();
+
+    QHBoxLayout* layout = new QHBoxLayout;
+
+    selector_ = new ButtonSelector(tr("Unit"));
+
+    selector_->addItem(tr("Kilometers"), "km");
+    selector_->addItem(tr("Miles"), "mile");
+
+    if(unit_ == "mile")
+    {
+        selector_->setCurrentIndex(1);
+    }
+
+    layout->addWidget(selector_, Qt::AlignLeft);
+
+    QPushButton* button = new QPushButton(tr("Save"));
+    connect(button, SIGNAL(clicked(bool)), this, SLOT(saveUnit()));
+    QDialogButtonBox* buttons = new QDialogButtonBox;
+    buttons->setCenterButtons(false);
+    buttons->addButton(button, QDialogButtonBox::AcceptRole);
+
+    layout->addWidget(buttons);
+
+    setLayout(layout);
+}
+
+void UnitSelector::saveUnit()
+{
+    QString value = selector_->value().toString();
+
+    if(value == unit_)
+    {
+        hide();
+        return;
+    }
+
+    Settings::instance().setValue("unit", value);
+    unit_ = value;
+    hide();
+    emit unitChanged();
+}
diff --git a/src/unitselector.h b/src/unitselector.h
new file mode 100644 (file)
index 0000000..793682b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef UNITSELECTOR_H
+#define UNITSELECTOR_H
+
+#include <QtGui/QDialog>
+
+class ButtonSelector;
+class QString;
+
+class UnitSelector : public QDialog
+{
+    Q_OBJECT
+
+public:
+    UnitSelector(QWidget* parent = 0);
+
+signals:
+    void unitChanged();
+
+private slots:
+    void saveUnit();
+
+private:
+    ButtonSelector* selector_;
+    QString unit_;
+};
+
+#endif
diff --git a/src/widgetscreen.cpp b/src/widgetscreen.cpp
new file mode 100644 (file)
index 0000000..fd00a06
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "widgetscreen.h"
+
+WidgetScreen::WidgetScreen(QWidget* parent): QStackedWidget(parent), AbstractScreen(){}
diff --git a/src/widgetscreen.h b/src/widgetscreen.h
new file mode 100644 (file)
index 0000000..83c83f5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef WIDGETSCREEN_H
+#define WIDGETSCREEN_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QStackedWidget>
+#include "abstractscreen.h"
+
+class WidgetScreen : public QStackedWidget, public AbstractScreen
+{
+    Q_OBJECT
+
+public:
+    WidgetScreen(QWidget* parent = 0);
+
+signals:
+    void minimizePressed();
+    void settingsPressed();
+    void closePressed();
+    void clicked();
+
+};
+
+#endif
diff --git a/src/zipreader.cpp b/src/zipreader.cpp
new file mode 100644 (file)
index 0000000..7cafef4
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include "zipreader.h"
+
+namespace
+{
+    int const BUFFER_SIZE = 16384;
+}
+
+ZipReader::ZipReader(QString const& filename): Reader(),
+filename_(filename), zip_(0), error_("")
+{
+}
+
+bool ZipReader::open()
+{
+    int error = 0;
+
+    zip_ = zip_open(filename_.toLatin1().data(), 0, &error);
+
+    if(error)
+    {
+        error_ = "Not a valid zip file";
+        zip_ = 0;
+        return false;
+    }
+
+    return true;
+}
+
+bool ZipReader::readFile(QString const& filename, QByteArray& data)
+{
+    zip_file* file = 0;
+
+    file = zip_fopen(zip_, filename.toLatin1().data(), 0);
+
+    if(!file)
+    {
+        error_ = QString(zip_strerror(zip_));
+        return false;
+    }
+
+    char buffer[BUFFER_SIZE];
+
+    int read = 0;
+
+    data.clear();
+
+    while((read = zip_fread(file, buffer, BUFFER_SIZE)) > 0)
+    {
+        data.append(buffer, read);
+    }
+
+    return true;
+}
+
+bool ZipReader::fileExists(QString const& filename) const
+{
+    return zip_name_locate(zip_, filename.toLatin1().data(), 0) != -1;
+}
+
+bool ZipReader::close()
+{
+    if(zip_close(zip_) == 0)
+    {
+        zip_ = 0;
+        return true;
+    }
+
+    return false;
+}
+
+QString const& ZipReader::errorString() const
+{
+    return error_;
+}
diff --git a/src/zipreader.h b/src/zipreader.h
new file mode 100644 (file)
index 0000000..c510b7f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ZIPREADER_H
+#define ZIPREADER_H
+
+#include "reader.h"
+#include "zip.h"
+
+class QString;
+class QByteArray;
+
+class ZipReader : public Reader
+{
+public:
+    ZipReader(QString const& filename);
+    bool open();
+    bool readFile(QString const& filename, QByteArray& data);
+    bool fileExists(QString const& filename) const;
+    bool close();
+    QString const& errorString() const;
+
+private:
+    QString filename_;
+    zip* zip_;
+    QString error_;
+};
+
+#endif
diff --git a/welcome b/welcome
deleted file mode 100644 (file)
index e69de29..0000000