summaryrefslogtreecommitdiffstats
path: root/src/shared/deviceskin
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/deviceskin')
-rw-r--r--src/shared/deviceskin/deviceskin.cpp857
-rw-r--r--src/shared/deviceskin/deviceskin.h174
-rw-r--r--src/shared/deviceskin/deviceskin.pri12
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.qrc5
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin30
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.pngbin0 -> 68200 bytes
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.pngbin0 -> 113907 bytes
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.pngbin0 -> 113450 bytes
-rw-r--r--src/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf78
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.qrc5
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin14
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf23
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.pngbin0 -> 6183 bytes
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.pngbin0 -> 6182 bytes
-rw-r--r--src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcfbin0 -> 41592 bytes
-rw-r--r--src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc5
-rw-r--r--src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.pngbin0 -> 161184 bytes
-rw-r--r--src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.pngbin0 -> 156789 bytes
-rw-r--r--src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin15
-rw-r--r--src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf78
-rw-r--r--src/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc5
-rw-r--r--src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.pngbin0 -> 241501 bytes
-rw-r--r--src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.pngbin0 -> 240615 bytes
-rw-r--r--src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin10
-rw-r--r--src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf53
-rw-r--r--src/shared/deviceskin/skins/SmartPhone.qrc5
-rw-r--r--src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.pngbin0 -> 111515 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.pngbin0 -> 101750 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin28
-rw-r--r--src/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf78
-rw-r--r--src/shared/deviceskin/skins/SmartPhone2.qrc5
-rw-r--r--src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.pngbin0 -> 134749 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.pngbin0 -> 121915 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin25
-rw-r--r--src/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf52
-rw-r--r--src/shared/deviceskin/skins/SmartPhoneWithButtons.qrc5
-rw-r--r--src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.pngbin0 -> 103838 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.pngbin0 -> 88470 bytes
-rw-r--r--src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin31
-rw-r--r--src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf103
-rw-r--r--src/shared/deviceskin/skins/TouchscreenPhone.qrc5
-rw-r--r--src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.pngbin0 -> 88599 bytes
-rw-r--r--src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.pngbin0 -> 61809 bytes
-rw-r--r--src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin16
-rw-r--r--src/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf45
45 files changed, 1762 insertions, 0 deletions
diff --git a/src/shared/deviceskin/deviceskin.cpp b/src/shared/deviceskin/deviceskin.cpp
new file mode 100644
index 000000000..1e3748fe8
--- /dev/null
+++ b/src/shared/deviceskin/deviceskin.cpp
@@ -0,0 +1,857 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceskin.h"
+
+#include <QtCore/qnamespace.h>
+#include <QtGui/QApplication>
+#include <QtGui/QBitmap>
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+#include <QtCore/QTextStream>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtGui/QImage>
+#include <QtCore/QTimer>
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QDebug>
+
+#ifdef TEST_SKIN
+# include <QtGui/QMainWindow>
+# include <QtGui/QDialog>
+# include <QtGui/QDialogButtonBox>
+# include <QtGui/QHBoxLayout>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { joydistance = 10, key_repeat_period = 50, key_repeat_delay = 500 };
+ enum { debugDeviceSkin = 0 };
+}
+
+static void parseRect(const QString &value, QRect *rect) {
+ const QStringList l = value.split(QLatin1Char(' '));
+ rect->setRect(l[0].toInt(), l[1].toInt(), l[2].toInt(), l[3].toInt());
+}
+
+static QString msgImageNotLoaded(const QString &f) {
+ return DeviceSkin::tr("The image file '%1' could not be loaded.").arg(f);
+}
+
+// ------------ DeviceSkinButtonArea
+DeviceSkinButtonArea::DeviceSkinButtonArea() :
+ keyCode(0),
+ activeWhenClosed(0)
+{
+}
+
+QDebug &operator<<(QDebug &str, const DeviceSkinButtonArea &a)
+{
+
+ str << "Area: " << a.name << " keyCode=" << a.keyCode << " area=" << a.area
+ << " text=" << a.text << " activeWhenClosed=" << a.activeWhenClosed;
+ return str;
+}
+
+// ------------ DeviceSkinParameters
+
+QDebug operator<<(QDebug str, const DeviceSkinParameters &p)
+{
+ str << "Images " << p.skinImageUpFileName << ','
+ << p.skinImageDownFileName<< ',' << p.skinImageClosedFileName
+ << ',' << p.skinCursorFileName <<"\nScreen: " << p.screenRect
+ << " back: " << p.backScreenRect << " closed: " << p.closedScreenRect
+ << " cursor: " << p.cursorHot << " Prefix: " << p.prefix
+ << " Joystick: " << p.joystick << " MouseHover" << p.hasMouseHover;
+ const int numAreas = p.buttonAreas.size();
+ for (int i = 0; i < numAreas; i++)
+ str << p.buttonAreas[i];
+ return str;
+}
+
+QSize DeviceSkinParameters::secondaryScreenSize() const
+{
+ return backScreenRect.isNull() ? closedScreenRect .size(): backScreenRect.size();
+}
+
+bool DeviceSkinParameters::hasSecondaryScreen() const
+{
+ return secondaryScreenSize() != QSize(0, 0);
+}
+
+bool DeviceSkinParameters::read(const QString &skinDirectory, ReadMode rm, QString *errorMessage)
+{
+ // Figure out the name. remove ending '/' if present
+ QString skinFile = skinDirectory;
+ if (skinFile.endsWith(QLatin1Char('/')))
+ skinFile.truncate(skinFile.length() - 1);
+
+ QFileInfo fi(skinFile);
+ QString fn;
+ if ( fi.isDir() ) {
+ prefix = skinFile;
+ prefix += QLatin1Char('/');
+ fn = prefix;
+ fn += fi.baseName();
+ fn += QLatin1String(".skin");
+ } else if (fi.isFile()){
+ fn = skinFile;
+ prefix = fi.path();
+ prefix += QLatin1Char('/');
+ } else {
+ *errorMessage = DeviceSkin::tr("The skin directory '%1' does not contain a configuration file.").arg(skinDirectory);
+ return false;
+ }
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly )) {
+ *errorMessage = DeviceSkin::tr("The skin configuration file '%1' could not be opened.").arg(fn);
+ return false;
+ }
+ QTextStream ts(&f);
+ const bool rc = read(ts, rm, errorMessage);
+ if (!rc)
+ *errorMessage = DeviceSkin::tr("The skin configuration file '%1' could not be read: %2").arg(fn).arg(*errorMessage);
+ return rc;
+}
+bool DeviceSkinParameters::read(QTextStream &ts, ReadMode rm, QString *errorMessage)
+{
+ QStringList closedAreas;
+ QStringList toggleAreas;
+ QStringList toggleActiveAreas;
+ int nareas = 0;
+ screenDepth = 0;
+ QString mark;
+ ts >> mark;
+ hasMouseHover = true; // historical default
+ if ( mark == QLatin1String("[SkinFile]") ) {
+ const QString UpKey = QLatin1String("Up");
+ const QString DownKey = QLatin1String("Down");
+ const QString ClosedKey = QLatin1String("Closed");
+ const QString ClosedAreasKey = QLatin1String("ClosedAreas");
+ const QString ScreenKey = QLatin1String("Screen");
+ const QString ScreenDepthKey = QLatin1String("ScreenDepth");
+ const QString BackScreenKey = QLatin1String("BackScreen");
+ const QString ClosedScreenKey = QLatin1String("ClosedScreen");
+ const QString CursorKey = QLatin1String("Cursor");
+ const QString AreasKey = QLatin1String("Areas");
+ const QString ToggleAreasKey = QLatin1String("ToggleAreas");
+ const QString ToggleActiveAreasKey = QLatin1String("ToggleActiveAreas");
+ const QString HasMouseHoverKey = QLatin1String("HasMouseHover");
+ // New
+ while (!nareas) {
+ QString line = ts.readLine();
+ if ( line.isNull() )
+ break;
+ if ( line[0] != QLatin1Char('#') && !line.isEmpty() ) {
+ int eq = line.indexOf(QLatin1Char('='));
+ if ( eq >= 0 ) {
+ const QString key = line.left(eq);
+ eq++;
+ while (eq<line.length()-1 && line[eq].isSpace())
+ eq++;
+ const QString value = line.mid(eq);
+ if ( key == UpKey ) {
+ skinImageUpFileName = value;
+ } else if ( key == DownKey ) {
+ skinImageDownFileName = value;
+ } else if ( key == ClosedKey ) {
+ skinImageClosedFileName = value;
+ } else if ( key == ClosedAreasKey ) {
+ closedAreas = value.split(QLatin1Char(' '));
+ } else if ( key == ScreenKey ) {
+ parseRect( value, &screenRect);
+ } else if ( key == ScreenDepthKey ) {
+ screenDepth = value.toInt();
+ } else if ( key == BackScreenKey ) {
+ parseRect(value, &backScreenRect);
+ } else if ( key == ClosedScreenKey ) {
+ parseRect( value, &closedScreenRect );
+ } else if ( key == CursorKey ) {
+ QStringList l = value.split(QLatin1Char(' '));
+ skinCursorFileName = l[0];
+ cursorHot = QPoint(l[1].toInt(),l[2].toInt());
+ } else if ( key == AreasKey ) {
+ nareas = value.toInt();
+ } else if ( key == ToggleAreasKey ) {
+ toggleAreas = value.split(QLatin1Char(' '));
+ } else if ( key == ToggleActiveAreasKey ) {
+ toggleActiveAreas = value.split(QLatin1Char(' '));
+ } else if ( key == HasMouseHoverKey ) {
+ hasMouseHover = value == QLatin1String("true") || value == QLatin1String("1");
+ }
+ } else {
+ *errorMessage = DeviceSkin::tr("Syntax error: %1").arg(line);
+ return false;
+ }
+ }
+ }
+ } else {
+ // Old
+ skinImageUpFileName = mark;
+ QString s;
+ int x,y,w,h,na;
+ ts >> s >> x >> y >> w >> h >> na;
+ skinImageDownFileName = s;
+ screenRect.setRect(x, y, w, h);
+ nareas = na;
+ }
+ // Done for short mode
+ if (rm == ReadSizeOnly)
+ return true;
+ // verify skin files exist
+ skinImageUpFileName.insert(0, prefix);
+ if (!QFile(skinImageUpFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"up\" image file '%1' does not exist.").arg(skinImageUpFileName);
+ return false;
+ }
+ if (!skinImageUp.load(skinImageUpFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageUpFileName);
+ return false;
+ }
+
+ skinImageDownFileName.insert(0, prefix);
+ if (!QFile(skinImageDownFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"down\" image file '%1' does not exist.").arg(skinImageDownFileName);
+ return false;
+ }
+ if (!skinImageDown.load(skinImageDownFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageDownFileName);
+ return false;
+ }
+
+ if (!skinImageClosedFileName.isEmpty()) {
+ skinImageClosedFileName.insert(0, prefix);
+ if (!QFile(skinImageClosedFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"closed\" image file '%1' does not exist.").arg(skinImageClosedFileName);
+ return false;
+ }
+ if (!skinImageClosed.load(skinImageClosedFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageClosedFileName);
+ return false;
+ }
+ }
+
+ if (!skinCursorFileName.isEmpty()) {
+ skinCursorFileName.insert(0, prefix);
+ if (!QFile(skinCursorFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin cursor image file '%1' does not exist.").arg(skinCursorFileName);
+ return false;
+ }
+ if (!skinCursor.load(skinCursorFileName)) {
+ *errorMessage = msgImageNotLoaded(skinCursorFileName);
+ return false;
+ }
+ }
+
+ // read areas
+ if (!nareas)
+ return true;
+ buttonAreas.reserve(nareas);
+
+ int i = 0;
+ ts.readLine(); // eol
+ joystick = -1;
+ const QString Joystick = QLatin1String("Joystick");
+ while (i < nareas && !ts.atEnd() ) {
+ buttonAreas.push_back(DeviceSkinButtonArea());
+ DeviceSkinButtonArea &area = buttonAreas.back();
+ const QString line = ts.readLine();
+ if ( !line.isEmpty() && line[0] != QLatin1Char('#') ) {
+ const QStringList tok = line.split(QRegExp(QLatin1String("[ \t][ \t]*")));
+ if ( tok.count()<6 ) {
+ *errorMessage = DeviceSkin::tr("Syntax error in area definition: %1").arg(line);
+ return false;
+ } else {
+ area.name = tok[0];
+ QString k = tok[1];
+ if ( k.left(2).toLower() == QLatin1String("0x")) {
+ area.keyCode = k.mid(2).toInt(0,16);
+ } else {
+ area.keyCode = k.toInt();
+ }
+
+ int p=0;
+ for (int j=2; j < tok.count() - 1; ) {
+ const int x = tok[j++].toInt();
+ const int y = tok[j++].toInt();
+ area.area.putPoints(p++,1,x,y);
+ }
+
+ const QChar doubleQuote = QLatin1Char('"');
+ if ( area.name[0] == doubleQuote && area.name.endsWith(doubleQuote)) {
+ area.name.truncate(area.name.size() - 1);
+ area.name.remove(0, 1);
+ }
+ if ( area.name.length() == 1 )
+ area.text = area.name;
+ if ( area.name == Joystick)
+ joystick = i;
+ area.activeWhenClosed = closedAreas.contains(area.name)
+ || area.keyCode == Qt::Key_Flip; // must be to work
+ area.toggleArea = toggleAreas.contains(area.name);
+ area.toggleActiveArea = toggleActiveAreas.contains(area.name);
+ if ( area.toggleArea )
+ toggleAreaList += i;
+ i++;
+ }
+ }
+ }
+ if (i != nareas) {
+ qWarning() << DeviceSkin::tr("Mismatch in number of areas, expected %1, got %2.")
+ .arg(nareas).arg(i);
+ }
+ if (debugDeviceSkin)
+ qDebug() << *this;
+ return true;
+}
+
+// --------- CursorWindow declaration
+
+namespace qvfb_internal {
+
+class CursorWindow : public QWidget
+{
+public:
+ explicit CursorWindow(const QImage &cursor, QPoint hot, QWidget *sk);
+
+ void setView(QWidget*);
+ void setPos(QPoint);
+ bool handleMouseEvent(QEvent *ev);
+
+protected:
+ bool event( QEvent *);
+ bool eventFilter( QObject*, QEvent *);
+
+private:
+ QWidget *mouseRecipient;
+ QWidget *m_view;
+ QWidget *skin;
+ QPoint hotspot;
+};
+}
+
+// --------- Skin
+
+DeviceSkin::DeviceSkin(const DeviceSkinParameters &parameters, QWidget *p ) :
+ QWidget(p),
+ m_parameters(parameters),
+ buttonRegions(parameters.buttonAreas.size(), QRegion()),
+ parent(p),
+ m_view(0),
+ m_secondaryView(0),
+ buttonPressed(false),
+ buttonIndex(0),
+ cursorw(0),
+ joydown(0),
+ t_skinkey(new QTimer(this)),
+ t_parentmove(new QTimer(this)),
+ flipped_open(true)
+{
+ Q_ASSERT(p);
+ setMouseTracking(true);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ setZoom(1.0);
+ connect( t_skinkey, SIGNAL(timeout()), this, SLOT(skinKeyRepeat()) );
+ t_parentmove->setSingleShot( true );
+ connect( t_parentmove, SIGNAL(timeout()), this, SLOT(moveParent()) );
+}
+
+void DeviceSkin::skinKeyRepeat()
+{
+ if ( m_view ) {
+ const DeviceSkinButtonArea &area = m_parameters.buttonAreas[buttonIndex];
+ emit skinKeyReleaseEvent( area.keyCode,area.text, true );
+ emit skinKeyPressEvent( area.keyCode, area.text, true );
+ t_skinkey->start(key_repeat_period);
+ }
+}
+
+void DeviceSkin::calcRegions()
+{
+ const int numAreas = m_parameters.buttonAreas.size();
+ for (int i=0; i<numAreas; i++) {
+ QPolygon xa(m_parameters.buttonAreas[i].area.count());
+ int n = m_parameters.buttonAreas[i].area.count();
+ for (int p=0; p<n; p++) {
+ xa.setPoint(p,transform.map(m_parameters.buttonAreas[i].area[p]));
+ }
+ if ( n == 2 ) {
+ buttonRegions[i] = QRegion(xa.boundingRect());
+ } else {
+ buttonRegions[i] = QRegion(xa);
+ }
+ }
+}
+
+void DeviceSkin::loadImages()
+{
+ QImage iup = m_parameters.skinImageUp;
+ QImage idown = m_parameters.skinImageDown;
+
+ QImage iclosed;
+ const bool hasClosedImage = !m_parameters.skinImageClosed.isNull();
+
+ if (hasClosedImage)
+ iclosed = m_parameters.skinImageClosed;
+ QImage icurs;
+ const bool hasCursorImage = !m_parameters.skinCursor.isNull();
+ if (hasCursorImage)
+ icurs = m_parameters.skinCursor;
+
+ if (!transform.isIdentity()) {
+ iup = iup.transformed(transform, Qt::SmoothTransformation);
+ idown = idown.transformed(transform, Qt::SmoothTransformation);
+ if (hasClosedImage)
+ iclosed = iclosed.transformed(transform, Qt::SmoothTransformation);
+ if (hasCursorImage)
+ icurs = icurs.transformed(transform, Qt::SmoothTransformation);
+ }
+ const Qt::ImageConversionFlags conv = Qt::ThresholdAlphaDither|Qt::AvoidDither;
+ skinImageUp = QPixmap::fromImage(iup);
+ skinImageDown = QPixmap::fromImage(idown, conv);
+ if (hasClosedImage)
+ skinImageClosed = QPixmap::fromImage(iclosed, conv);
+ if (hasCursorImage)
+ skinCursor = QPixmap::fromImage(icurs, conv);
+
+ setFixedSize( skinImageUp.size() );
+ if (!skinImageUp.mask())
+ skinImageUp.setMask(skinImageUp.createHeuristicMask());
+ if (!skinImageClosed.mask())
+ skinImageClosed.setMask(skinImageClosed.createHeuristicMask());
+
+ QWidget* parent = parentWidget();
+ parent->setMask( skinImageUp.mask() );
+ parent->setFixedSize( skinImageUp.size() );
+
+ delete cursorw;
+ cursorw = 0;
+ if (hasCursorImage) {
+ cursorw = new qvfb_internal::CursorWindow(m_parameters.skinCursor, m_parameters.cursorHot, this);
+ if ( m_view )
+ cursorw->setView(m_view);
+ }
+}
+
+DeviceSkin::~DeviceSkin( )
+{
+ delete cursorw;
+}
+
+void DeviceSkin::setTransform( const QMatrix& wm )
+{
+ transform = QImage::trueMatrix(wm,m_parameters.skinImageUp.width(),m_parameters.skinImageUp.height());
+ calcRegions();
+ loadImages();
+ if ( m_view ) {
+ QPoint p = transform.map(QPolygon(m_parameters.screenRect)).boundingRect().topLeft();
+ m_view->move(p);
+ }
+ updateSecondaryScreen();
+}
+
+void DeviceSkin::setZoom( double z )
+{
+ setTransform(QMatrix().scale(z,z));
+}
+
+void DeviceSkin::updateSecondaryScreen()
+{
+ if (!m_secondaryView)
+ return;
+ if (flipped_open) {
+ if (m_parameters.backScreenRect.isNull()) {
+ m_secondaryView->hide();
+ } else {
+ m_secondaryView->move(transform.map(QPolygon(m_parameters.backScreenRect)).boundingRect().topLeft());
+ m_secondaryView->show();
+ }
+ } else {
+ if (m_parameters.closedScreenRect.isNull()) {
+ m_secondaryView->hide();
+ } else {
+ m_secondaryView->move(transform.map(QPolygon(m_parameters.closedScreenRect)).boundingRect().topLeft());
+ m_secondaryView->show();
+ }
+ }
+}
+
+void DeviceSkin::setView( QWidget *v )
+{
+ m_view = v;
+ m_view->setFocus();
+ m_view->move(transform.map(QPolygon(m_parameters.screenRect)).boundingRect().topLeft());
+ if ( cursorw )
+ cursorw->setView(v);
+}
+
+void DeviceSkin::setSecondaryView( QWidget *v )
+{
+ m_secondaryView = v;
+ updateSecondaryScreen();
+}
+
+void DeviceSkin::paintEvent( QPaintEvent *)
+{
+ QPainter p( this );
+ if ( flipped_open ) {
+ p.drawPixmap( 0, 0, skinImageUp );
+ } else {
+ p.drawPixmap( 0, 0, skinImageClosed );
+ }
+ QList<int> toDraw;
+ if ( buttonPressed == true ) {
+ toDraw += buttonIndex;
+ }
+ foreach (int toggle, m_parameters.toggleAreaList) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[toggle];
+ if ( flipped_open || ba.activeWhenClosed ) {
+ if ( ba.toggleArea && ba.toggleActiveArea )
+ toDraw += toggle;
+ }
+ }
+ foreach (int button, toDraw ) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[button];
+ const QRect r = buttonRegions[button].boundingRect();
+ if ( ba.area.count() > 2 )
+ p.setClipRegion(buttonRegions[button]);
+ p.drawPixmap( r.topLeft(), skinImageDown, r);
+ }
+}
+
+void DeviceSkin::mousePressEvent( QMouseEvent *e )
+{
+ if (e->button() == Qt::RightButton) {
+ emit popupMenu();
+ } else {
+ buttonPressed = false;
+
+ onjoyrelease = -1;
+ const int numAreas = m_parameters.buttonAreas.size();
+ for (int i = 0; i < numAreas ; i++) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[i];
+ if ( buttonRegions[i].contains( e->pos() ) ) {
+ if ( flipped_open || ba.activeWhenClosed ) {
+ if ( m_parameters.joystick == i ) {
+ joydown = true;
+ } else {
+ if ( joydown )
+ onjoyrelease = i;
+ else
+ startPress(i);
+ break;
+ if (debugDeviceSkin)// Debug message to be sure we are clicking the right areas
+ qDebug()<< m_parameters.buttonAreas[i].name << " clicked";
+ }
+ }
+ }
+ }
+ clickPos = e->pos();
+// This is handy for finding the areas to define rectangles for new skins
+ if (debugDeviceSkin)
+ qDebug()<< "Clicked in " << e->pos().x() << ',' << e->pos().y();
+ clickPos = e->pos();
+ }
+}
+
+void DeviceSkin::flip(bool open)
+{
+ if ( flipped_open == open )
+ return;
+ if ( open ) {
+ parent->setMask( skinImageUp.mask() );
+ emit skinKeyReleaseEvent( Qt::Key(Qt::Key_Flip), QString(), false);
+ } else {
+ parent->setMask( skinImageClosed.mask() );
+ emit skinKeyPressEvent( Qt::Key(Qt::Key_Flip), QString(), false);
+ }
+ flipped_open = open;
+ updateSecondaryScreen();
+ repaint();
+}
+
+void DeviceSkin::startPress(int i)
+{
+ buttonPressed = true;
+ buttonIndex = i;
+ if (m_view) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[buttonIndex];
+ if ( ba.keyCode == Qt::Key_Flip ) {
+ flip(!flipped_open);
+ } else if ( ba.toggleArea ) {
+ bool active = !ba.toggleActiveArea;
+ const_cast<DeviceSkinButtonArea &>(ba).toggleActiveArea = active;
+ if ( active )
+ emit skinKeyPressEvent( ba.keyCode, ba.text, false);
+ else
+ emit skinKeyReleaseEvent( ba.keyCode, ba.text, false);
+ } else {
+ emit skinKeyPressEvent( ba.keyCode, ba.text, false);
+ t_skinkey->start(key_repeat_delay);
+ }
+ repaint( buttonRegions[buttonIndex].boundingRect() );
+ }
+}
+
+void DeviceSkin::endPress()
+{
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[buttonIndex];
+ if (m_view && ba.keyCode != Qt::Key_Flip && !ba.toggleArea )
+ emit skinKeyReleaseEvent(ba.keyCode, ba.text, false );
+ t_skinkey->stop();
+ buttonPressed = false;
+ repaint( buttonRegions[buttonIndex].boundingRect() );
+}
+
+void DeviceSkin::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( e->buttons() & Qt::LeftButton ) {
+ const int joystick = m_parameters.joystick;
+ QPoint newpos = e->globalPos() - clickPos;
+ if ( joydown ) {
+ int k1=0, k2=0;
+ if ( newpos.x() < -joydistance ) {
+ k1 = joystick+1;
+ } else if ( newpos.x() > +joydistance ) {
+ k1 = joystick+3;
+ }
+ if ( newpos.y() < -joydistance ) {
+ k2 = joystick+2;
+ } else if ( newpos.y() > +joydistance ) {
+ k2 = joystick+4;
+ }
+ if ( k1 || k2 ) {
+ if ( !buttonPressed ) {
+ onjoyrelease = -1;
+ if ( k1 && k2 ) {
+ startPress(k2);
+ endPress();
+ }
+ startPress(k1 ? k1 : k2);
+ }
+ } else if ( buttonPressed ) {
+ endPress();
+ }
+ } else if ( buttonPressed == false ) {
+ parentpos = newpos;
+ if ( !t_parentmove->isActive() )
+ t_parentmove->start(50);
+ }
+ }
+ if ( cursorw )
+ cursorw->setPos(e->globalPos());
+}
+
+void DeviceSkin::moveParent()
+{
+ parent->move( parentpos );
+}
+
+void DeviceSkin::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( buttonPressed )
+ endPress();
+ if ( joydown ) {
+ joydown = false;
+ if ( onjoyrelease >= 0 ) {
+ startPress(onjoyrelease);
+ endPress();
+ }
+ }
+}
+
+bool DeviceSkin::hasCursor() const
+{
+ return !skinCursor.isNull();
+}
+
+// ------------------ CursorWindow implementation
+
+namespace qvfb_internal {
+
+bool CursorWindow::eventFilter( QObject *, QEvent *ev)
+{
+ handleMouseEvent(ev);
+ return false;
+}
+
+bool CursorWindow::event( QEvent *ev )
+{
+ if (handleMouseEvent(ev))
+ return true;
+ return QWidget::event(ev);
+}
+
+bool CursorWindow::handleMouseEvent(QEvent *ev)
+{
+ bool handledEvent = false;
+ static int inhere=0;
+ if ( !inhere ) {
+ inhere++;
+ if ( m_view ) {
+ if ( ev->type() >= QEvent::MouseButtonPress && ev->type() <= QEvent::MouseMove ) {
+ QMouseEvent *e = (QMouseEvent*)ev;
+ QPoint gp = e->globalPos();
+ QPoint vp = m_view->mapFromGlobal(gp);
+ QPoint sp = skin->mapFromGlobal(gp);
+ if ( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick ) {
+ if ( m_view->rect().contains(vp) )
+ mouseRecipient = m_view;
+ else if ( skin->parentWidget()->geometry().contains(gp) )
+ mouseRecipient = skin;
+ else
+ mouseRecipient = 0;
+ }
+ if ( mouseRecipient ) {
+ setPos(gp);
+ QMouseEvent me(e->type(),mouseRecipient==skin ? sp : vp,gp,e->button(),e->buttons(),e->modifiers());
+ QApplication::sendEvent(mouseRecipient, &me);
+ } else if ( !skin->parentWidget()->geometry().contains(gp) ) {
+ hide();
+ } else {
+ setPos(gp);
+ }
+ if ( e->type() == QEvent::MouseButtonRelease )
+ mouseRecipient = 0;
+ handledEvent = true;
+ }
+ }
+ inhere--;
+ }
+ return handledEvent;
+}
+
+void CursorWindow::setView(QWidget* v)
+{
+ if ( m_view ) {
+ m_view->removeEventFilter(this);
+ m_view->removeEventFilter(this);
+ }
+ m_view = v;
+ m_view->installEventFilter(this);
+ m_view->installEventFilter(this);
+ mouseRecipient = 0;
+}
+
+CursorWindow::CursorWindow(const QImage &img, QPoint hot, QWidget* sk)
+ :QWidget(0),
+ m_view(0), skin(sk),
+ hotspot(hot)
+{
+ setWindowFlags( Qt::FramelessWindowHint );
+ mouseRecipient = 0;
+ setMouseTracking(true);
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::BlankCursor);
+#endif
+ QPixmap p;
+ p = QPixmap::fromImage(img);
+ if (!p.mask()) {
+ if ( img.hasAlphaChannel() ) {
+ QBitmap bm;
+ bm = QPixmap::fromImage(img.createAlphaMask());
+ p.setMask( bm );
+ } else {
+ QBitmap bm;
+ bm = QPixmap::fromImage(img.createHeuristicMask());
+ p.setMask( bm );
+ }
+ }
+ QPalette palette;
+ palette.setBrush(backgroundRole(), QBrush(p));
+ setPalette(palette);
+ setFixedSize( p.size() );
+ if ( !p.mask().isNull() )
+ setMask( p.mask() );
+}
+
+void CursorWindow::setPos(QPoint p)
+{
+ move(p-hotspot);
+ show();
+ raise();
+}
+}
+
+#ifdef TEST_SKIN
+
+int main(int argc,char *argv[])
+{
+ if (argc < 1)
+ return 1;
+ const QString skinFile = QString::fromUtf8(argv[1]);
+ QApplication app(argc,argv);
+ QMainWindow mw;
+
+ DeviceSkinParameters params;
+ QString errorMessage;
+ if (!params.read(skinFile, DeviceSkinParameters::ReadAll, &errorMessage)) {
+ qWarning() << errorMessage;
+ return 1;
+ }
+ DeviceSkin ds(params, &mw);
+ // View Dialog
+ QDialog *dialog = new QDialog();
+ QHBoxLayout *dialogLayout = new QHBoxLayout();
+ dialog->setLayout(dialogLayout);
+ QDialogButtonBox *dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ QObject::connect(dialogButtonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
+ QObject::connect(dialogButtonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
+ dialogLayout->addWidget(dialogButtonBox);
+ dialog->setFixedSize(params.screenSize());
+ dialog->setParent(&ds, Qt::SubWindow);
+ dialog->setAutoFillBackground(true);
+ ds.setView(dialog);
+
+ QObject::connect(&ds, SIGNAL(popupMenu()), &mw, SLOT(close()));
+ QObject::connect(&ds, SIGNAL(skinKeyPressEvent(int,QString,bool)), &mw, SLOT(close()));
+ mw.show();
+ return app.exec();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
diff --git a/src/shared/deviceskin/deviceskin.h b/src/shared/deviceskin/deviceskin.h
new file mode 100644
index 000000000..8a53acffd
--- /dev/null
+++ b/src/shared/deviceskin/deviceskin.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SKIN_H
+#define SKIN_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QPolygon>
+#include <QtGui/QRegion>
+#include <QtGui/QPixmap>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace qvfb_internal {
+ class CursorWindow;
+}
+
+class QTextStream;
+
+// ------- Button Area
+struct DeviceSkinButtonArea {
+ DeviceSkinButtonArea();
+ QString name;
+ int keyCode;
+ QPolygon area;
+ QString text;
+ bool activeWhenClosed;
+ bool toggleArea;
+ bool toggleActiveArea;
+};
+
+// -------- Parameters
+struct DeviceSkinParameters {
+ enum ReadMode { ReadAll, ReadSizeOnly };
+ bool read(const QString &skinDirectory, ReadMode rm, QString *errorMessage);
+ bool read(QTextStream &ts, ReadMode rm, QString *errorMessage);
+
+ QSize screenSize() const { return screenRect.size(); }
+ QSize secondaryScreenSize() const;
+ bool hasSecondaryScreen() const;
+
+ QString skinImageUpFileName;
+ QString skinImageDownFileName;
+ QString skinImageClosedFileName;
+ QString skinCursorFileName;
+
+ QImage skinImageUp;
+ QImage skinImageDown;
+ QImage skinImageClosed;
+ QImage skinCursor;
+
+ QRect screenRect;
+ QRect backScreenRect;
+ QRect closedScreenRect;
+ int screenDepth;
+ QPoint cursorHot;
+ QVector<DeviceSkinButtonArea> buttonAreas;
+ QList<int> toggleAreaList;
+
+ int joystick;
+ QString prefix;
+ bool hasMouseHover;
+};
+
+// --------- Skin Widget
+class DeviceSkin : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit DeviceSkin(const DeviceSkinParameters &parameters, QWidget *p );
+ ~DeviceSkin( );
+
+ QWidget *view() const { return m_view; }
+ void setView( QWidget *v );
+
+ QWidget *secondaryView() const { return m_secondaryView; }
+ void setSecondaryView( QWidget *v );
+
+ void setZoom( double );
+ void setTransform( const QMatrix& );
+
+ bool hasCursor() const;
+
+ QString prefix() const {return m_parameters.prefix;}
+
+signals:
+ void popupMenu();
+ void skinKeyPressEvent(int code, const QString& text, bool autorep);
+ void skinKeyReleaseEvent(int code, const QString& text, bool autorep);
+
+protected slots:
+ void skinKeyRepeat();
+ void moveParent();
+
+protected:
+ virtual void paintEvent( QPaintEvent * );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+
+private:
+ void calcRegions();
+ void flip(bool open);
+ void updateSecondaryScreen();
+ void loadImages();
+ void startPress(int);
+ void endPress();
+
+ const DeviceSkinParameters m_parameters;
+ QVector<QRegion> buttonRegions;
+ QPixmap skinImageUp;
+ QPixmap skinImageDown;
+ QPixmap skinImageClosed;
+ QPixmap skinCursor;
+ QWidget *parent;
+ QWidget *m_view;
+ QWidget *m_secondaryView;
+ QPoint parentpos;
+ QPoint clickPos;
+ bool buttonPressed;
+ int buttonIndex;
+ QMatrix transform;
+ qvfb_internal::CursorWindow *cursorw;
+
+ bool joydown;
+ QTimer *t_skinkey;
+ QTimer *t_parentmove;
+ int onjoyrelease;
+
+ bool flipped_open;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/shared/deviceskin/deviceskin.pri b/src/shared/deviceskin/deviceskin.pri
new file mode 100644
index 000000000..3e9935abb
--- /dev/null
+++ b/src/shared/deviceskin/deviceskin.pri
@@ -0,0 +1,12 @@
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/deviceskin.h
+SOURCES += $$PWD/deviceskin.cpp
+RESOURCES += $$PWD/skins/ClamshellPhone.qrc \
+ $$PWD/skins/SmartPhone2.qrc \
+ $$PWD/skins/SmartPhone.qrc \
+ $$PWD/skins/SmartPhoneWithButtons.qrc \
+ $$PWD/skins/TouchscreenPhone.qrc \
+ $$PWD/skins/PortableMedia.qrc \
+ $$PWD/skins/S60-QVGA-Candybar.qrc \
+ $$PWD/skins/S60-nHD-Touchscreen.qrc
+
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.qrc b/src/shared/deviceskin/skins/ClamshellPhone.qrc
new file mode 100644
index 000000000..39cd42274
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>ClamshellPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin
new file mode 100644
index 000000000..cb24a8e14
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin
@@ -0,0 +1,30 @@
+[SkinFile]
+Up=ClamshellPhone1-5.png
+Down=ClamshellPhone1-5-pressed.png
+Closed=ClamshellPhone1-5-closed.png
+Screen=72 84 176 208
+Areas=22
+HasMouseHover=false
+
+"Power" 0x0100000a 205 563 249 586
+"1" 0x0031 62 414 119 438
+"2" 0x0032 130 414 189 438
+"3" 0x0033 198 413 257 438
+"4" 0x0034 54 444 117 470
+"5" 0x0035 128 444 189 471
+"6" 0x0036 202 444 264 471
+"7" 0x0037 47 477 113 507
+"8" 0x0038 126 477 190 507
+"9" 0x0039 205 478 270 509
+"*" 0x002a 39 515 110 552
+"0" 0x0030 122 515 195 553
+"#" 0x0023 207 516 280 553
+"Context1" 0x01100000 137 360 108 383 123 410 90 409 60 387 63 378 100 362
+"Back" 0x01000061 184 361 206 376 213 387 197 410 226 410 256 392 258 381 244 369
+"Backspace" 0x01000003 68 563 113 587
+"Select" 0x01010000 160 391 172 390 181 386 184 381 180 377 173 373 165 372 155 372 145 375 138 378 136 382 138 387 147 390
+"Left" 0x1000012 141 390 136 385 136 381 143 375 132 371 120 380 121 393 129 401
+"Down" 0x1000015 143 389 130 402 162 412 191 404 175 390
+"Right" 0x1000014 186 370 176 375 184 382 182 387 175 390 190 404 201 396 202 375
+"Up" 0x1000013 133 370 143 374 176 374 185 370 169 362 149 362
+"Flip" 0x01100006 98 325 225 353
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png
new file mode 100644
index 000000000..88ba3a147
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png
new file mode 100644
index 000000000..971cdef64
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png
new file mode 100644
index 000000000..f3550ee7d
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf
new file mode 100644
index 000000000..e349dbc1f
--- /dev/null
+++ b/src/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Flip
+Key4=Backspace
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#=#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/PortableMedia.qrc b/src/shared/deviceskin/skins/PortableMedia.qrc
new file mode 100644
index 000000000..a902f1a73
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>PortableMedia.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin b/src/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin
new file mode 100644
index 000000000..b76e5cfad
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin
@@ -0,0 +1,14 @@
+[SkinFile]
+Up=portablemedia.png
+Down=portablemedia-pressed.png
+Screen=18 20 480 272
+Areas=7
+HasMouseHover=false
+
+"Context1" 0x01100000 530 192 565 223
+"Back" 0x01000061 530 138 565 173
+"Select" 0x01010000 530 65 565 98
+"Left" 0x1000012 529 67 519 57 511 65 511 104 519 110 529 100 529 98
+"Down" 0x1000015 530 102 520 111 529 120 569 120 577 114 566 103 564 103
+"Right" 0x1000014 565 65 576 52 585 67 585 102 578 113 567 104
+"Up" 0x1000013 530 65 519 55 528 48 567 48 573 51 564 66
diff --git a/src/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf
new file mode 100644
index 000000000..514e8816e
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf
@@ -0,0 +1,23 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Map=123
+Default=1
+1=Applications/mediaplayer.desktop
+2=Applications/photoedit.desktop
+3=Settings
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png
new file mode 100644
index 000000000..730e76287
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png
new file mode 100644
index 000000000..e44cbe160
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf
new file mode 100644
index 000000000..127e07c8e
--- /dev/null
+++ b/src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf
Binary files differ
diff --git a/src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc b/src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc
new file mode 100644
index 000000000..813848479
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>S60-QVGA-Candybar.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png
new file mode 100644
index 000000000..89d40cbed
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png
new file mode 100644
index 000000000..0d0e598b9
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin
new file mode 100644
index 000000000..4f8fe5dca
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin
@@ -0,0 +1,15 @@
+[SkinFile]
+Up=S60-QVGA-Candybar.png
+Down=S60-QVGA-Candybar-down.png
+Screen=61 93 240 320
+Areas=7
+HasMouseHover=false
+
+
+"Context1" 0x01100000 54 469 151 469 140 483 88 485 81 496 54 498
+"Back" 0x01000061 211 468 307 467 307 498 278 497 219 486
+"Select" 0x01010000 165 491 196 522
+"Left" 0x1000012 149 474 166 492 163 519 143 538 142 481
+"Down" 0x1000015 164 521 195 522 212 539 204 545 154 544 145 536
+"Right" 0x1000014 214 475 219 487 219 528 212 539 196 522 197 492
+"Up" 0x1000013 150 474 156 467 209 467 213 476 197 489 165 489
diff --git a/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf
new file mode 100644
index 000000000..e349dbc1f
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Flip
+Key4=Backspace
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#=#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc
new file mode 100644
index 000000000..daf0cc363
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>S60-nHD-Touchscreen.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png
new file mode 100644
index 000000000..7253e3801
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png
new file mode 100644
index 000000000..675563e5c
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin
new file mode 100644
index 000000000..ed25d0eac
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin
@@ -0,0 +1,10 @@
+[SkinFile]
+Up=S60-nHD-Touchscreen.png
+Down=S60-nHD-Touchscreen-down.png
+Screen=53 183 360 640
+Areas=3
+HasMouseHover=false
+
+"Call" 0x01100004 76 874 171 899
+"Hangup" 0x01100005 300 876 393 899
+"Home" 0x1000010 174 878 298 899
diff --git a/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf
new file mode 100644
index 000000000..6665125c9
--- /dev/null
+++ b/src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf
@@ -0,0 +1,53 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/mediaplayer.desktop
+3=Applications/simapp.desktop,Applications/calculator.desktop
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Applications/datebook.desktop
+7=Games
+8=Settings/beaming.desktop
+9=Applications/todolist.desktop
+*=Settings
+0=Applications
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Back
+Key2=Select
+Key3=Call
+Key4=Hangup
+[Device]
+PrimaryInput=Touchscreen
+[Button]
+Count=2
+[Button0]
+Name[]=Home Button
+Key=Home
+PressedActionMappable=0
+PressedActionService=TaskManager
+PressedActionMessage=multitask()
+HeldActionMappable=0
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+[Button1]
+Name=Power Button
+Key=Hangup
+HeldActionService=Launcher
+HeldActionMessage=execute(QString)
+HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n)
diff --git a/src/shared/deviceskin/skins/SmartPhone.qrc b/src/shared/deviceskin/skins/SmartPhone.qrc
new file mode 100644
index 000000000..8bb53259a
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png
new file mode 100644
index 000000000..d0db2ed35
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png
new file mode 100644
index 000000000..e6ac5a0f3
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin
new file mode 100644
index 000000000..2f44c5aa8
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin
@@ -0,0 +1,28 @@
+[SkinFile]
+Up=SmartPhone.png
+Down=SmartPhone-pressed.png
+Screen=90 107 176 208
+Areas=21
+HasMouseHover=false
+
+"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454
+"2" 0x0032 153 467 202 492
+"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453
+"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487
+"5" 0x0035 153 499 202 524
+"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485
+"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519
+"8" 0x0038 153 531 202 556
+"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517
+"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551
+"0" 0x0030 153 564 202 589
+"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Select" 0x01010000 160 338 195 371
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
diff --git a/src/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf
new file mode 100644
index 000000000..110335055
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/SmartPhone2.qrc b/src/shared/deviceskin/skins/SmartPhone2.qrc
new file mode 100644
index 000000000..751e9852b
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone2.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhone2.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png
new file mode 100644
index 000000000..d4eb5b0c8
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png
new file mode 100644
index 000000000..48ccc1c5a
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin
new file mode 100644
index 000000000..16884bfb5
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin
@@ -0,0 +1,25 @@
+SmartPhone2.png SmartPhone2-pressed.png
+90 107
+176 220
+21
+"Menu" 0x01100000 70 400 115 427
+"Backspace" 0x01000003 238 400 285 427
+"1" 0x0031 138 437 149 451 142 461 120 462 102 455 95 442 99 435 121 432
+"2" 0x0032 153 445 202 470
+"3" 0x0033 258 435 260 448 243 461 215 462 207 452 218 438 248 431
+"4" 0x0034 138 470 149 484 142 494 120 495 102 488 95 475 99 468 121 465
+"5" 0x0035 153 477 202 502
+"6" 0x0036 258 467 260 480 243 493 215 494 207 484 218 470 248 463
+"7" 0x0037 138 502 149 516 142 526 120 527 102 520 95 507 99 500 121 497
+"8" 0x0038 153 509 202 534
+"9" 0x0039 258 499 260 512 243 525 215 526 207 516 218 502 248 495
+"*" 0x002a 138 534 149 548 142 558 120 559 102 552 95 539 99 532 121 529
+"0" 0x0030 153 542 202 567
+"#" 0x0023 258 532 260 545 243 558 215 559 207 549 218 535 248 528
+"Yes" 0x01010001 91 343 141 393
+"No" 0x01010002 219 343 269 393
+"Select" 0x01010000 160 356 195 389
+"Left" 0x1000012 159 356 149 346 141 354 141 391 149 399 159 389 159 387
+"Down" 0x1000015 160 391 150 400 159 409 199 409 207 403 196 392 194 392
+"Right" 0x1000014 195 354 206 341 215 356 215 391 208 402 197 393
+"Up" 0x1000013 160 354 149 344 158 337 197 337 203 340 194 355
diff --git a/src/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf
new file mode 100644
index 000000000..b08320347
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf
@@ -0,0 +1,52 @@
+[Button]
+[IMethod]
+key_count = 5
+key_hold_action_1 = insertText
+key_hold_action_2 = insertText
+key_hold_action_3 = insertSymbol
+key_hold_action_4 = changeMode
+key_hold_arg_1 = 1
+key_hold_arg_2 = 0
+key_id_1 = 1
+key_id_2 = 0
+key_id_3 = *
+key_id_4 = #
+key_id_5 = *
+key_mode_1 = Abc
+key_mode_2 = Abc
+key_mode_3 = Abc
+key_mode_4 = Abc
+key_mode_5 = Phone
+key_tap_action_1 = insertText
+key_tap_action_2 = insertSpace
+key_tap_action_3 = modifyText
+key_tap_action_4 = changeShift
+key_tap_action_5 = insertText
+key_tap_arg_1 = .,'?!-@:〓
+key_tap_arg_5 = *+pw
+[Menu]
+1 = Applications/camera.desktop
+2 = Applications/datebook.desktop
+3 = Games
+4 = Applications/qtmail.desktop
+5 = Applications/addressbook.desktop
+6 = Settings
+7 = Settings/Beaming.desktop
+8 = Applications
+9 = Documents
+Columns = 3
+Default = 5
+Map = 123456789
+Rows = 3
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+[SystemButtons]
+Count=5
+Key0=Yes
+Key1=Select
+Key2=No
+Key3=Menu
+Key4=Backspace
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/SmartPhoneWithButtons.qrc b/src/shared/deviceskin/skins/SmartPhoneWithButtons.qrc
new file mode 100644
index 000000000..f3393ba9d
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhoneWithButtons.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhoneWithButtons.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png
new file mode 100644
index 000000000..456a068ee
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png
new file mode 100644
index 000000000..5ffbd6e4e
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin
new file mode 100644
index 000000000..9afa67f30
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin
@@ -0,0 +1,31 @@
+[SkinFile]
+Up=SmartPhoneWithButtons.png
+Down=SmartPhoneWithButtons-pressed.png
+Screen=90 107 176 208
+Areas=24
+HasMouseHover=false
+
+"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454
+"2" 0x0032 153 467 202 492
+"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453
+"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487
+"5" 0x0035 153 499 202 524
+"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485
+"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519
+"8" 0x0038 153 531 202 556
+"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517
+"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551
+"0" 0x0030 153 564 202 589
+"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Select" 0x01010000 160 338 195 371
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
+"Home" 0x1000010 164 402 195 434
+"F1" 0x1000030 138 422 163 448
+"F2" 0x1000031 196 422 220 448
diff --git a/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf
new file mode 100644
index 000000000..ebd6926ae
--- /dev/null
+++ b/src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf
@@ -0,0 +1,103 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Button]
+Count=3
+[Button0]
+Name[]=Calendar Button
+Key=F1
+PressedActionService=Calendar
+PressedActionMessage=raiseToday()
+HeldActionService=Calendar
+HeldActionMessage=newEvent()
+[Button1]
+Name[]=Tasks Button
+Key=F2
+PressedActionService=Tasks
+PressedActionMessage=raise()
+HeldActionService=Tasks
+HeldActionMessage=newTask()
+[Button2]
+Name[]=Home Button
+Key=Home
+PressedActionMappable=0
+PressedActionService=TaskManager
+PressedActionMessage=multitask()
+HeldActionMappable=0
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/src/shared/deviceskin/skins/TouchscreenPhone.qrc b/src/shared/deviceskin/skins/TouchscreenPhone.qrc
new file mode 100644
index 000000000..023144d2f
--- /dev/null
+++ b/src/shared/deviceskin/skins/TouchscreenPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>TouchscreenPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png
new file mode 100644
index 000000000..01acb8654
--- /dev/null
+++ b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png
new file mode 100644
index 000000000..e90de0de4
--- /dev/null
+++ b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png
Binary files differ
diff --git a/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin
new file mode 100644
index 000000000..24316a1b4
--- /dev/null
+++ b/src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin
@@ -0,0 +1,16 @@
+[SkinFile]
+Up=TouchscreenPhone.png
+Down=TouchscreenPhone-pressed.png
+Screen=90 107 176 208
+Areas=9
+HasMouseHover=false
+
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
+"Select" 0x01010000 160 338 195 371
diff --git a/src/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf b/src/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf
new file mode 100644
index 000000000..a13dfdc3b
--- /dev/null
+++ b/src/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf
@@ -0,0 +1,45 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Back
+Key2=Select
+Key3=Call
+Key4=Hangup
+[Button]
+Count=1
+[Button0]
+Name=Power Button
+Key=Hangup
+HeldActionService=Launcher
+HeldActionMessage=execute(QString)
+HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n)
+[Device]
+PrimaryInput=Touchscreen
+